X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fchar%2Fsynclink.c;h=fee2aca3f6a5c7eb77c8c07135489644e5ec8ab2;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=deefd713a8fe9d3422d2be92b7c87a41116623c5;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index deefd713a..fee2aca3f 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -1,7 +1,7 @@ /* * linux/drivers/char/synclink.c * - * $Id: synclink.c,v 4.21 2004/03/08 15:29:22 paulkf Exp $ + * $Id: synclink.c,v 4.38 2005/11/07 16:30:34 paulkf Exp $ * * Device driver for Microgate SyncLink ISA and PCI * high speed multiprotocol serial adapters. @@ -53,7 +53,6 @@ * 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 @@ -82,6 +81,7 @@ #include #include #include +#include #include @@ -96,17 +96,15 @@ #include #include #include -#include +#include #include #include #include +#include +#include -#ifdef CONFIG_SYNCLINK_SYNCPPP_MODULE -#define CONFIG_SYNCLINK_SYNCPPP 1 -#endif - -#ifdef CONFIG_SYNCLINK_SYNCPPP -#include +#ifdef CONFIG_HDLC_MODULE +#define CONFIG_HDLC 1 #endif #define GET_USER(error,value,addr) error = get_user(value,addr) @@ -120,7 +118,7 @@ #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; */ @@ -144,13 +142,14 @@ MGSL_PARAMS default_params = { typedef struct _DMABUFFERENTRY { u32 phys_addr; /* 32-bit flat physical address of data buffer */ - u16 count; /* buffer size/data count */ - u16 status; /* Control/status field */ - u16 rcc; /* character count field */ + volatile u16 count; /* buffer size/data count */ + volatile u16 status; /* Control/status field */ + volatile u16 rcc; /* character count field */ u16 reserved; /* padding required by 16C32 */ u32 link; /* 32-bit flat link to next buffer entry */ char *virt_addr; /* virtual address of data buffer */ u32 phys_entry; /* physical address of this buffer entry */ + dma_addr_t dma_addr; } DMABUFFERENTRY, *DMAPBUFFERENTRY; /* The queue of BH actions to be performed */ @@ -187,7 +186,6 @@ struct tx_holding_buffer { */ struct mgsl_struct { - void *if_ptr; /* General purpose pointer (used by SPPP) */ int magic; int flags; int count; /* count of opens */ @@ -237,7 +235,8 @@ struct mgsl_struct { int ri_chkcount; char *buffer_list; /* virtual address of Rx & Tx buffer lists */ - unsigned long buffer_list_phys; + u32 buffer_list_phys; + dma_addr_t buffer_list_dma_addr; unsigned int rx_buffer_count; /* count of total allocated Rx buffers */ DMABUFFERENTRY *rx_buffer_list; /* list of receive buffer entries */ @@ -318,15 +317,13 @@ struct mgsl_struct { 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 }; @@ -684,13 +681,13 @@ void usc_ClearIrqPendingBits( struct mgsl_struct *info, u16 IrqMask ); #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 ); @@ -699,53 +696,46 @@ 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 /* @@ -764,78 +754,77 @@ struct net_device_stats *mgsl_net_stats(struct net_device *dev); ((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, @@ -853,23 +842,24 @@ static int tiocmget(struct tty_struct *tty, struct file *file); 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; /* @@ -897,19 +887,19 @@ static int dosyncppp[MAX_TOTAL_DEVICES]; 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.38 $"; static int synclink_init_one (struct pci_dev *dev, const struct pci_device_id *ent); @@ -940,30 +930,16 @@ static struct tty_driver *serial_driver; 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;} - -/* - * tmp_buf is used as a temporary buffer by mgsl_write. We need to - * lock it in case the COPY_FROM_USER blocks while swapping in a page, - * and some other program tries to do a serial write at the same time. - * Since the lock will only come under contention when the system is - * swapping and available memory is low, it makes sense to share one - * buffer across all the serial ioports, since it significantly saves - * memory if large numbers of serial ports are open. - */ -static unsigned char *tmp_buf; -static DECLARE_MUTEX(tmp_buf_sem); +static void* mgsl_get_text_ptr(void) +{ + return mgsl_get_text_ptr; +} static inline int mgsl_paranoia_check(struct mgsl_struct *info, char *name, const char *routine) @@ -989,6 +965,29 @@ static inline int mgsl_paranoia_check(struct mgsl_struct *info, 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 @@ -1042,7 +1041,7 @@ static void mgsl_start(struct tty_struct *tty) /* 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; @@ -1074,7 +1073,7 @@ int mgsl_bh_action(struct mgsl_struct *info) /* * 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; @@ -1118,7 +1117,7 @@ void mgsl_bh_handler(void* Context) __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); @@ -1139,7 +1138,7 @@ void mgsl_bh_receive(struct mgsl_struct *info) } 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; @@ -1149,13 +1148,7 @@ void mgsl_bh_transmit(struct mgsl_struct *info) __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); } @@ -1168,7 +1161,7 @@ void mgsl_bh_transmit(struct mgsl_struct *info) 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", @@ -1189,7 +1182,7 @@ void mgsl_bh_status(struct mgsl_struct *info) * 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 ); @@ -1241,7 +1234,7 @@ void mgsl_isr_receive_status( struct mgsl_struct *info ) * 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 ); @@ -1285,9 +1278,9 @@ void mgsl_isr_transmit_status( struct mgsl_struct *info ) 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 { @@ -1308,7 +1301,7 @@ void mgsl_isr_transmit_status( struct mgsl_struct *info ) * 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 ); @@ -1348,12 +1341,12 @@ void mgsl_isr_io_pin( struct mgsl_struct *info ) 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) { @@ -1426,7 +1419,7 @@ void mgsl_isr_io_pin( struct mgsl_struct *info ) * 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", @@ -1458,10 +1451,11 @@ void mgsl_isr_transmit_data( struct mgsl_struct *info ) * 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; + int work = 0; unsigned char DataByte; struct tty_struct *tty = info->tty; struct mgsl_icount *icount = &info->icount; @@ -1482,6 +1476,8 @@ void mgsl_isr_receive_data( struct mgsl_struct *info ) /* flush the receive FIFO */ while( (Fifocount = (usc_InReg(info,RICR) >> 8)) ) { + int flag; + /* read one byte from RxFIFO */ outw( (inw(info->io_base + CCAR) & 0x0780) | (RDR+LSBONLY), info->io_base + CCAR ); @@ -1493,13 +1489,9 @@ void mgsl_isr_receive_data( struct mgsl_struct *info ) RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) ) usc_UnlatchRxstatusBits(info,RXSTATUS_ALL); - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - continue; - - *tty->flip.char_buf_ptr = DataByte; icount->rx++; - *tty->flip.flag_buf_ptr = 0; + flag = 0; if ( status & (RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR + RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) ) { printk("rxerr=%04X\n",status); @@ -1525,41 +1517,31 @@ void mgsl_isr_receive_data( struct mgsl_struct *info ) status &= info->read_status_mask; if (status & RXSTATUS_BREAK_RECEIVED) { - *tty->flip.flag_buf_ptr = TTY_BREAK; + flag = TTY_BREAK; if (info->flags & ASYNC_SAK) do_SAK(tty); } else if (status & RXSTATUS_PARITY_ERROR) - *tty->flip.flag_buf_ptr = TTY_PARITY; + flag = TTY_PARITY; else if (status & RXSTATUS_FRAMING_ERROR) - *tty->flip.flag_buf_ptr = TTY_FRAME; - if (status & RXSTATUS_OVERRUN) { - /* Overrun is special, since it's - * reported immediately, and doesn't - * affect the current character - */ - if (tty->flip.count < TTY_FLIPBUF_SIZE) { - tty->flip.count++; - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - *tty->flip.flag_buf_ptr = TTY_OVERRUN; - } - } + flag = TTY_FRAME; } /* end of if (error) */ - - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; + tty_insert_flip_char(tty, DataByte, flag); + if (status & RXSTATUS_OVERRUN) { + /* Overrun is special, since it's + * reported immediately, and doesn't + * affect the current character + */ + work += tty_insert_flip_char(tty, 0, TTY_OVERRUN); + } } if ( debug_level >= DEBUG_LEVEL_ISR ) { - printk("%s(%d):mgsl_isr_receive_data flip count=%d\n", - __FILE__,__LINE__,tty->flip.count); printk("%s(%d):rx=%d brk=%d parity=%d frame=%d overrun=%d\n", __FILE__,__LINE__,icount->rx,icount->brk, icount->parity,icount->frame,icount->overrun); } - if ( tty->flip.count ) + if(work) tty_flip_buffer_push(tty); } @@ -1570,7 +1552,7 @@ void mgsl_isr_receive_data( struct mgsl_struct *info ) * 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 ); @@ -1606,7 +1588,7 @@ void mgsl_isr_misc( struct mgsl_struct *info ) * 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() */ @@ -1630,7 +1612,7 @@ void mgsl_isr_null( struct mgsl_struct *info ) * 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; @@ -1674,7 +1656,7 @@ void mgsl_isr_receive_dma( struct mgsl_struct *info ) * 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; @@ -1812,6 +1794,8 @@ static int startup(struct mgsl_struct * info) info->pending_bh = 0; + memset(&info->icount, 0, sizeof(info->icount)); + init_timer(&info->tx_timer); info->tx_timer.data = (unsigned long)info; info->tx_timer.function = mgsl_tx_timeout; @@ -1869,7 +1853,7 @@ static void shutdown(struct mgsl_struct * info) 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); @@ -2136,16 +2120,15 @@ static void mgsl_flush_chars(struct tty_struct *tty) * 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; @@ -2156,7 +2139,7 @@ static int mgsl_write(struct tty_struct * tty, int from_user, if (mgsl_paranoia_check(info, tty->name, "mgsl_write")) goto cleanup; - if (!tty || !info->xmit_buf || !tmp_buf) + if (!tty || !info->xmit_buf) goto cleanup; if ( info->params.mode == MGSL_MODE_HDLC || @@ -2182,20 +2165,7 @@ static int mgsl_write(struct tty_struct * tty, int from_user, /* 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 @@ -2235,70 +2205,26 @@ static int mgsl_write(struct tty_struct * tty, int from_user, __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; } } @@ -2411,11 +2337,8 @@ static void mgsl_flush_buffer(struct tty_struct *tty) 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() * @@ -2521,7 +2444,7 @@ static void mgsl_unthrottle(struct tty_struct * tty) * * 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; @@ -2529,12 +2452,12 @@ static int mgsl_get_stats(struct mgsl_struct * info, struct mgsl_icount *user_ic printk("%s(%d):mgsl_get_params(%s)\n", __FILE__,__LINE__, info->device_name); - COPY_TO_USER(err,user_icount, &info->icount, sizeof(struct mgsl_icount)); - if (err) { - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):mgsl_get_stats(%s) user buffer copy failed\n", - __FILE__,__LINE__,info->device_name); - return -EFAULT; + if (!user_icount) { + memset(&info->icount, 0, sizeof(info->icount)); + } else { + COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount)); + if (err) + return -EFAULT; } return 0; @@ -2550,7 +2473,7 @@ static int mgsl_get_stats(struct mgsl_struct * info, struct mgsl_icount *user_ic * * 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) @@ -2580,7 +2503,7 @@ static int mgsl_get_params(struct mgsl_struct * info, MGSL_PARAMS *user_params) * * 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; @@ -2616,7 +2539,7 @@ static int mgsl_set_params(struct mgsl_struct * info, MGSL_PARAMS *new_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; @@ -2763,7 +2686,7 @@ static int mgsl_rxenable(struct mgsl_struct * info, int enable) * 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; @@ -3047,20 +2970,21 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file, 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: @@ -3070,9 +2994,9 @@ int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long 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 @@ -3091,7 +3015,7 @@ int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long 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); @@ -3248,19 +3172,17 @@ static void mgsl_close(struct tty_struct *tty, struct file * filp) 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); } @@ -3321,13 +3243,12 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout) 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)) @@ -3336,8 +3257,7 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int 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)) @@ -3376,7 +3296,7 @@ static void mgsl_hangup(struct tty_struct *tty) info->count = 0; info->flags &= ~ASYNC_NORMAL_ACTIVE; - info->tty = 0; + info->tty = NULL; wake_up_interruptible(&info->open_wait); @@ -3507,7 +3427,6 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp) { struct mgsl_struct *info; int retval, line; - unsigned long page; unsigned long flags; /* verify range of specified line number */ @@ -3541,18 +3460,6 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp) goto cleanup; } - if (!tmp_buf) { - page = get_zeroed_page(GFP_KERNEL); - if (!page) { - retval = -ENOMEM; - goto cleanup; - } - if (tmp_buf) - free_page(page); - else - tmp_buf = (unsigned char *) page; - } - info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; spin_lock_irqsave(&info->netlock, flags); @@ -3587,7 +3494,7 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp) 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--; } @@ -3709,7 +3616,7 @@ static inline int line_info(char *buf, struct mgsl_struct *info) * * 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; @@ -3748,7 +3655,7 @@ done: * 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; @@ -3855,7 +3762,7 @@ int mgsl_allocate_dma_buffers(struct mgsl_struct *info) * 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; @@ -3871,11 +3778,10 @@ int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info ) /* inspect portions of the buffer while other portions are being */ /* updated by the adapter using Bus Master DMA. */ - info->buffer_list = kmalloc(BUFFERLISTSIZE, GFP_KERNEL | GFP_DMA); - if ( info->buffer_list == NULL ) + info->buffer_list = dma_alloc_coherent(NULL, BUFFERLISTSIZE, &info->buffer_list_dma_addr, GFP_KERNEL); + if (info->buffer_list == NULL) return -ENOMEM; - - info->buffer_list_phys = isa_virt_to_bus(info->buffer_list); + info->buffer_list_phys = (u32)(info->buffer_list_dma_addr); } /* We got the memory for the buffer entry lists. */ @@ -3940,10 +3846,10 @@ int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info ) * 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); + if (info->buffer_list && info->bus_type != MGSL_BUS_TYPE_PCI) + dma_free_coherent(NULL, BUFFERLISTSIZE, info->buffer_list, info->buffer_list_dma_addr); info->buffer_list = NULL; info->rx_buffer_list = NULL; @@ -3967,10 +3873,10 @@ void mgsl_free_buffer_list_memory( struct mgsl_struct *info ) * * 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; + u32 phys_addr; /* Allocate page sized buffers for the receive buffer list */ @@ -3982,11 +3888,10 @@ int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList, info->last_mem_alloc += DMABUFFERSIZE; } else { /* ISA adapter uses system memory. */ - BufferList[i].virt_addr = - kmalloc(DMABUFFERSIZE, GFP_KERNEL | GFP_DMA); - if ( BufferList[i].virt_addr == NULL ) + BufferList[i].virt_addr = dma_alloc_coherent(NULL, DMABUFFERSIZE, &BufferList[i].dma_addr, GFP_KERNEL); + if (BufferList[i].virt_addr == NULL) return -ENOMEM; - phys_addr = isa_virt_to_bus(BufferList[i].virt_addr); + phys_addr = (u32)(BufferList[i].dma_addr); } BufferList[i].phys_addr = phys_addr; } @@ -4009,7 +3914,7 @@ int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList, * * 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; @@ -4017,7 +3922,7 @@ void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList for ( i = 0 ; i < Buffercount ; i++ ) { if ( BufferList[i].virt_addr ) { if ( info->bus_type != MGSL_BUS_TYPE_PCI ) - kfree(BufferList[i].virt_addr); + dma_free_coherent(NULL, DMABUFFERSIZE, BufferList[i].virt_addr, BufferList[i].dma_addr); BufferList[i].virt_addr = NULL; } } @@ -4032,7 +3937,7 @@ void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList * 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 ); @@ -4053,7 +3958,7 @@ void mgsl_free_dma_buffers( struct mgsl_struct *info ) * * 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 ) @@ -4073,11 +3978,9 @@ int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info) * * 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); - + kfree(info->intermediate_rxbuffer); info->intermediate_rxbuffer = NULL; } /* end of mgsl_free_intermediate_rxbuffer_memory() */ @@ -4095,7 +3998,7 @@ void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info) * * 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; @@ -4126,15 +4029,13 @@ int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info) * * 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; for ( i=0; inum_tx_holding_buffers; ++i ) { - if ( info->tx_holding_buffers[i].buffer ) { - kfree(info->tx_holding_buffers[i].buffer); - info->tx_holding_buffers[i].buffer=NULL; - } + kfree(info->tx_holding_buffers[i].buffer); + info->tx_holding_buffers[i].buffer = NULL; } info->get_tx_holding_index = 0; @@ -4158,7 +4059,7 @@ void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info) * 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; @@ -4182,7 +4083,7 @@ int load_next_tx_holding_buffer(struct mgsl_struct *info) 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; } @@ -4204,7 +4105,7 @@ int load_next_tx_holding_buffer(struct mgsl_struct *info) * * 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; @@ -4223,7 +4124,7 @@ int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned 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", @@ -4303,7 +4204,7 @@ errout: } /* 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", @@ -4336,11 +4237,11 @@ void mgsl_release_resources(struct mgsl_struct *info) } 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 ) @@ -4357,7 +4258,7 @@ void mgsl_release_resources(struct mgsl_struct *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; @@ -4410,12 +4311,10 @@ void mgsl_add_device( struct mgsl_struct *info ) 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() @@ -4425,7 +4324,7 @@ void mgsl_add_device( struct mgsl_struct *info ) * 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; @@ -4484,10 +4383,11 @@ static struct tty_operations mgsl_ops = { /* * 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; @@ -4503,9 +4403,13 @@ int mgsl_init_tty() 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, @@ -4515,7 +4419,7 @@ int mgsl_init_tty() /* enumerate user specified ISA adapters */ -int mgsl_enum_isa_devices() +static void mgsl_enum_isa_devices(void) { struct mgsl_struct *info; int i; @@ -4546,51 +4450,9 @@ int mgsl_enum_isa_devices() 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; @@ -4598,16 +4460,17 @@ static void __exit synclink_exit(void) 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; @@ -4615,12 +4478,40 @@ static void __exit synclink_exit(void) kfree(tmp); } - if (tmp_buf) { - free_page((unsigned long) tmp_buf); - tmp_buf = NULL; + 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(); } - - pci_unregister_driver(&synclink_pci_driver); + + 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); @@ -4647,7 +4538,7 @@ module_exit(synclink_exit); * * 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 */ @@ -4674,7 +4565,7 @@ void usc_RTCmd( struct mgsl_struct *info, u16 Cmd ) * * 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 ); @@ -4701,7 +4592,7 @@ void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd ) * 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 */ @@ -4730,7 +4621,7 @@ void usc_OutDmaReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue ) * 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 */ @@ -4757,7 +4648,7 @@ u16 usc_InDmaReg( struct mgsl_struct *info, u16 RegAddr ) * 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 ); @@ -4782,7 +4673,7 @@ void usc_OutReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue ) * * 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 ); @@ -4796,7 +4687,7 @@ u16 usc_InReg( struct mgsl_struct *info, u16 RegAddr ) * 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; @@ -5376,7 +5267,7 @@ void usc_set_sdlc_mode( struct mgsl_struct *info ) * 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 */ @@ -5440,7 +5331,7 @@ void usc_enable_loopback(struct mgsl_struct *info, int enable) * * 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; @@ -5497,7 +5388,7 @@ void usc_enable_aux_clock( struct mgsl_struct *info, u32 data_rate ) * * 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; @@ -5636,7 +5527,7 @@ void usc_process_rxoverrun_sync( struct mgsl_struct *info ) * 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", @@ -5669,7 +5560,7 @@ void usc_stop_receiver( struct mgsl_struct *info ) * 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; @@ -5733,7 +5624,7 @@ void usc_start_receiver( struct mgsl_struct *info ) * 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; @@ -5816,7 +5707,7 @@ void usc_start_transmitter( struct mgsl_struct *info ) 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; @@ -5839,7 +5730,7 @@ void usc_start_transmitter( struct mgsl_struct *info ) * 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", @@ -5868,7 +5759,7 @@ void usc_stop_transmitter( struct mgsl_struct *info ) * 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]; @@ -5925,7 +5816,7 @@ void usc_load_txfifo( struct mgsl_struct *info ) * 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; @@ -6039,7 +5930,7 @@ void usc_reset( struct mgsl_struct *info ) * 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; @@ -6105,7 +5996,7 @@ void usc_set_async_mode( struct mgsl_struct *info ) * <15..8> ? RxFIFO IRQ Request Level * * Note: For async mode the receive FIFO level must be set - * to 0 to aviod the situation where the FIFO contains fewer bytes + * to 0 to avoid the situation where the FIFO contains fewer bytes * than the trigger level and no more data is expected. * * <7> 0 Exited Hunt IA (Interrupt Arm) @@ -6216,6 +6107,11 @@ void usc_set_async_mode( struct mgsl_struct *info ) usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12)); } + if (info->params.loopback) { + info->loopback_bits = 0x300; + outw(0x0300, info->io_base + CCAR); + } + } /* end of usc_set_async_mode() */ /* usc_loopback_frame() @@ -6232,7 +6128,7 @@ void usc_set_async_mode( struct mgsl_struct *info ) * 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; @@ -6300,7 +6196,7 @@ void usc_loopback_frame( struct mgsl_struct *info ) * 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 ); @@ -6323,7 +6219,7 @@ void usc_set_sync_mode( struct mgsl_struct *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; @@ -6386,7 +6282,7 @@ void usc_set_txidle( struct mgsl_struct *info ) * 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; @@ -6422,7 +6318,7 @@ void usc_get_serial_signals( struct mgsl_struct *info ) * 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; @@ -6454,7 +6350,7 @@ void usc_set_serial_signals( struct mgsl_struct *info ) * 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 ) { /* @@ -6564,7 +6460,7 @@ void usc_enable_async_clock( struct mgsl_struct *info, u32 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; @@ -6590,7 +6486,7 @@ void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info ) * 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; } @@ -6605,7 +6501,7 @@ int num_free_tx_dma_buffers(struct mgsl_struct *info) * 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; @@ -6633,7 +6529,7 @@ void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info ) * * 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; @@ -6676,7 +6572,7 @@ void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartInd * 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; @@ -6747,9 +6643,12 @@ int mgsl_get_rx_frame(struct mgsl_struct *info) 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; @@ -6776,7 +6675,7 @@ int mgsl_get_rx_frame(struct mgsl_struct *info) 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) && @@ -6820,18 +6719,12 @@ int mgsl_get_rx_frame(struct mgsl_struct *info) *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. */ @@ -6878,7 +6771,7 @@ Cleanup: * 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; @@ -6993,7 +6886,7 @@ int mgsl_get_raw_rx_frame(struct mgsl_struct *info) 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 */ @@ -7003,9 +6896,7 @@ int mgsl_get_raw_rx_frame(struct mgsl_struct *info) 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. */ @@ -7045,15 +6936,15 @@ int mgsl_get_raw_rx_frame(struct mgsl_struct *info) * * 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 @@ -7122,11 +7013,11 @@ void mgsl_load_tx_dma_buffer(struct mgsl_struct *info, const char *Buffer, * 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 }; - static unsigned int Patterncount = sizeof(BitPatterns)/sizeof(unsigned short); + static unsigned int Patterncount = ARRAY_SIZE(BitPatterns); unsigned int i; BOOLEAN rc = TRUE; unsigned long flags; @@ -7178,7 +7069,7 @@ BOOLEAN mgsl_register_test( struct mgsl_struct *info ) * 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; @@ -7210,8 +7101,7 @@ BOOLEAN mgsl_irq_test( struct mgsl_struct *info ) 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); @@ -7234,7 +7124,7 @@ BOOLEAN mgsl_irq_test( struct mgsl_struct *info ) * 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; @@ -7350,7 +7240,7 @@ BOOLEAN mgsl_dma_test( struct mgsl_struct *info ) /*************************************************************/ /* Wait 100ms for interrupt. */ - EndTime = jiffies + jiffies_from_ms(100); + EndTime = jiffies + msecs_to_jiffies(100); for(;;) { if (time_after(jiffies, EndTime)) { @@ -7406,7 +7296,7 @@ BOOLEAN mgsl_dma_test( struct mgsl_struct *info ) /**********************************/ /* Wait 100ms */ - EndTime = jiffies + jiffies_from_ms(100); + EndTime = jiffies + msecs_to_jiffies(100); for(;;) { if (time_after(jiffies, EndTime)) { @@ -7448,7 +7338,7 @@ BOOLEAN mgsl_dma_test( struct mgsl_struct *info ) /******************************/ /* Wait 100ms */ - EndTime = jiffies + jiffies_from_ms(100); + EndTime = jiffies + msecs_to_jiffies(100); /* While timer not expired wait for transmit complete */ @@ -7479,7 +7369,7 @@ BOOLEAN mgsl_dma_test( struct mgsl_struct *info ) /* 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; @@ -7526,7 +7416,7 @@ BOOLEAN mgsl_dma_test( struct mgsl_struct *info ) * 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", @@ -7568,11 +7458,11 @@ int mgsl_adapter_test( struct mgsl_struct *info ) * 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 }; - unsigned long Patterncount = sizeof(BitPatterns)/sizeof(unsigned long); + static unsigned long BitPatterns[] = + { 0x0, 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999, 0xffffffff, 0x12345678 }; + unsigned long Patterncount = ARRAY_SIZE(BitPatterns); unsigned long i; unsigned long TestLimit = SHARED_MEM_ADDRESS_SIZE/sizeof(unsigned long); unsigned long * TestAddr; @@ -7649,7 +7539,7 @@ BOOLEAN mgsl_memory_test( struct mgsl_struct *info ) * * 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 */ @@ -7671,7 +7561,7 @@ void mgsl_load_pci_memory( char* TargetPtr, const char* SourcePtr, } /* 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; @@ -7711,7 +7601,7 @@ void mgsl_trace_block(struct mgsl_struct *info,const char* data, int count, int * 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; @@ -7733,9 +7623,9 @@ void mgsl_tx_timeout(unsigned long context) 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); @@ -7765,7 +7655,7 @@ static int mgsl_loopmode_send_done( struct mgsl_struct * 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 */ @@ -7775,7 +7665,7 @@ void usc_loopmode_send_done( struct mgsl_struct * info ) /* 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 ); @@ -7787,7 +7677,7 @@ void usc_loopmode_cancel_transmit( struct mgsl_struct * info ) * 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; @@ -7804,91 +7694,130 @@ void usc_loopmode_insert_request( struct mgsl_struct * info ) /* 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; } @@ -7896,141 +7825,299 @@ int mgsl_sppp_open(struct net_device *d) 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)