Path: blob/master/drivers/char/pcmcia/synclink_cs.c
15115 views
/*1* linux/drivers/char/pcmcia/synclink_cs.c2*3* $Id: synclink_cs.c,v 4.34 2005/09/08 13:20:54 paulkf Exp $4*5* Device driver for Microgate SyncLink PC Card6* multiprotocol serial adapter.7*8* written by Paul Fulghum for Microgate Corporation9* [email protected]10*11* Microgate and SyncLink are trademarks of Microgate Corporation12*13* This code is released under the GNU General Public License (GPL)14*15* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED16* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES17* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE18* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,19* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES20* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR21* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)22* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,23* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)24* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED25* OF THE POSSIBILITY OF SUCH DAMAGE.26*/2728#define VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq))29#if defined(__i386__)30# define BREAKPOINT() asm(" int $3");31#else32# define BREAKPOINT() { }33#endif3435#define MAX_DEVICE_COUNT 43637#include <linux/module.h>38#include <linux/errno.h>39#include <linux/signal.h>40#include <linux/sched.h>41#include <linux/timer.h>42#include <linux/time.h>43#include <linux/interrupt.h>44#include <linux/tty.h>45#include <linux/tty_flip.h>46#include <linux/serial.h>47#include <linux/major.h>48#include <linux/string.h>49#include <linux/fcntl.h>50#include <linux/ptrace.h>51#include <linux/ioport.h>52#include <linux/mm.h>53#include <linux/seq_file.h>54#include <linux/slab.h>55#include <linux/netdevice.h>56#include <linux/vmalloc.h>57#include <linux/init.h>58#include <linux/delay.h>59#include <linux/ioctl.h>60#include <linux/synclink.h>6162#include <asm/system.h>63#include <asm/io.h>64#include <asm/irq.h>65#include <asm/dma.h>66#include <linux/bitops.h>67#include <asm/types.h>68#include <linux/termios.h>69#include <linux/workqueue.h>70#include <linux/hdlc.h>7172#include <pcmcia/cistpl.h>73#include <pcmcia/cisreg.h>74#include <pcmcia/ds.h>7576#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_CS_MODULE))77#define SYNCLINK_GENERIC_HDLC 178#else79#define SYNCLINK_GENERIC_HDLC 080#endif8182#define GET_USER(error,value,addr) error = get_user(value,addr)83#define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 084#define PUT_USER(error,value,addr) error = put_user(value,addr)85#define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 08687#include <asm/uaccess.h>8889static MGSL_PARAMS default_params = {90MGSL_MODE_HDLC, /* unsigned long mode */910, /* unsigned char loopback; */92HDLC_FLAG_UNDERRUN_ABORT15, /* unsigned short flags; */93HDLC_ENCODING_NRZI_SPACE, /* unsigned char encoding; */940, /* unsigned long clock_speed; */950xff, /* unsigned char addr_filter; */96HDLC_CRC_16_CCITT, /* unsigned short crc_type; */97HDLC_PREAMBLE_LENGTH_8BITS, /* unsigned char preamble_length; */98HDLC_PREAMBLE_PATTERN_NONE, /* unsigned char preamble; */999600, /* unsigned long data_rate; */1008, /* unsigned char data_bits; */1011, /* unsigned char stop_bits; */102ASYNC_PARITY_NONE /* unsigned char parity; */103};104105typedef struct106{107int count;108unsigned char status;109char data[1];110} RXBUF;111112/* The queue of BH actions to be performed */113114#define BH_RECEIVE 1115#define BH_TRANSMIT 2116#define BH_STATUS 4117118#define IO_PIN_SHUTDOWN_LIMIT 100119120#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))121122struct _input_signal_events {123int ri_up;124int ri_down;125int dsr_up;126int dsr_down;127int dcd_up;128int dcd_down;129int cts_up;130int cts_down;131};132133134/*135* Device instance data structure136*/137138typedef struct _mgslpc_info {139struct tty_port port;140void *if_ptr; /* General purpose pointer (used by SPPP) */141int magic;142int line;143144struct mgsl_icount icount;145146int timeout;147int x_char; /* xon/xoff character */148unsigned char read_status_mask;149unsigned char ignore_status_mask;150151unsigned char *tx_buf;152int tx_put;153int tx_get;154int tx_count;155156/* circular list of fixed length rx buffers */157158unsigned char *rx_buf; /* memory allocated for all rx buffers */159int rx_buf_total_size; /* size of memory allocated for rx buffers */160int rx_put; /* index of next empty rx buffer */161int rx_get; /* index of next full rx buffer */162int rx_buf_size; /* size in bytes of single rx buffer */163int rx_buf_count; /* total number of rx buffers */164int rx_frame_count; /* number of full rx buffers */165166wait_queue_head_t status_event_wait_q;167wait_queue_head_t event_wait_q;168struct timer_list tx_timer; /* HDLC transmit timeout timer */169struct _mgslpc_info *next_device; /* device list link */170171unsigned short imra_value;172unsigned short imrb_value;173unsigned char pim_value;174175spinlock_t lock;176struct work_struct task; /* task structure for scheduling bh */177178u32 max_frame_size;179180u32 pending_bh;181182bool bh_running;183bool bh_requested;184185int dcd_chkcount; /* check counts to prevent */186int cts_chkcount; /* too many IRQs if a signal */187int dsr_chkcount; /* is floating */188int ri_chkcount;189190bool rx_enabled;191bool rx_overflow;192193bool tx_enabled;194bool tx_active;195bool tx_aborting;196u32 idle_mode;197198int if_mode; /* serial interface selection (RS-232, v.35 etc) */199200char device_name[25]; /* device instance name */201202unsigned int io_base; /* base I/O address of adapter */203unsigned int irq_level;204205MGSL_PARAMS params; /* communications parameters */206207unsigned char serial_signals; /* current serial signal states */208209bool irq_occurred; /* for diagnostics use */210char testing_irq;211unsigned int init_error; /* startup error (DIAGS) */212213char flag_buf[MAX_ASYNC_BUFFER_SIZE];214bool drop_rts_on_tx_done;215216struct _input_signal_events input_signal_events;217218/* PCMCIA support */219struct pcmcia_device *p_dev;220int stop;221222/* SPPP/Cisco HDLC device parts */223int netcount;224spinlock_t netlock;225226#if SYNCLINK_GENERIC_HDLC227struct net_device *netdev;228#endif229230} MGSLPC_INFO;231232#define MGSLPC_MAGIC 0x5402233234/*235* The size of the serial xmit buffer is 1 page, or 4096 bytes236*/237#define TXBUFSIZE 4096238239240#define CHA 0x00 /* channel A offset */241#define CHB 0x40 /* channel B offset */242243/*244* FIXME: PPC has PVR defined in asm/reg.h. For now we just undef it.245*/246#undef PVR247248#define RXFIFO 0249#define TXFIFO 0250#define STAR 0x20251#define CMDR 0x20252#define RSTA 0x21253#define PRE 0x21254#define MODE 0x22255#define TIMR 0x23256#define XAD1 0x24257#define XAD2 0x25258#define RAH1 0x26259#define RAH2 0x27260#define DAFO 0x27261#define RAL1 0x28262#define RFC 0x28263#define RHCR 0x29264#define RAL2 0x29265#define RBCL 0x2a266#define XBCL 0x2a267#define RBCH 0x2b268#define XBCH 0x2b269#define CCR0 0x2c270#define CCR1 0x2d271#define CCR2 0x2e272#define CCR3 0x2f273#define VSTR 0x34274#define BGR 0x34275#define RLCR 0x35276#define AML 0x36277#define AMH 0x37278#define GIS 0x38279#define IVA 0x38280#define IPC 0x39281#define ISR 0x3a282#define IMR 0x3a283#define PVR 0x3c284#define PIS 0x3d285#define PIM 0x3d286#define PCR 0x3e287#define CCR4 0x3f288289// IMR/ISR290291#define IRQ_BREAK_ON BIT15 // rx break detected292#define IRQ_DATAOVERRUN BIT14 // receive data overflow293#define IRQ_ALLSENT BIT13 // all sent294#define IRQ_UNDERRUN BIT12 // transmit data underrun295#define IRQ_TIMER BIT11 // timer interrupt296#define IRQ_CTS BIT10 // CTS status change297#define IRQ_TXREPEAT BIT9 // tx message repeat298#define IRQ_TXFIFO BIT8 // transmit pool ready299#define IRQ_RXEOM BIT7 // receive message end300#define IRQ_EXITHUNT BIT6 // receive frame start301#define IRQ_RXTIME BIT6 // rx char timeout302#define IRQ_DCD BIT2 // carrier detect status change303#define IRQ_OVERRUN BIT1 // receive frame overflow304#define IRQ_RXFIFO BIT0 // receive pool full305306// STAR307308#define XFW BIT6 // transmit FIFO write enable309#define CEC BIT2 // command executing310#define CTS BIT1 // CTS state311312#define PVR_DTR BIT0313#define PVR_DSR BIT1314#define PVR_RI BIT2315#define PVR_AUTOCTS BIT3316#define PVR_RS232 0x20 /* 0010b */317#define PVR_V35 0xe0 /* 1110b */318#define PVR_RS422 0x40 /* 0100b */319320/* Register access functions */321322#define write_reg(info, reg, val) outb((val),(info)->io_base + (reg))323#define read_reg(info, reg) inb((info)->io_base + (reg))324325#define read_reg16(info, reg) inw((info)->io_base + (reg))326#define write_reg16(info, reg, val) outw((val), (info)->io_base + (reg))327328#define set_reg_bits(info, reg, mask) \329write_reg(info, (reg), \330(unsigned char) (read_reg(info, (reg)) | (mask)))331#define clear_reg_bits(info, reg, mask) \332write_reg(info, (reg), \333(unsigned char) (read_reg(info, (reg)) & ~(mask)))334/*335* interrupt enable/disable routines336*/337static void irq_disable(MGSLPC_INFO *info, unsigned char channel, unsigned short mask)338{339if (channel == CHA) {340info->imra_value |= mask;341write_reg16(info, CHA + IMR, info->imra_value);342} else {343info->imrb_value |= mask;344write_reg16(info, CHB + IMR, info->imrb_value);345}346}347static void irq_enable(MGSLPC_INFO *info, unsigned char channel, unsigned short mask)348{349if (channel == CHA) {350info->imra_value &= ~mask;351write_reg16(info, CHA + IMR, info->imra_value);352} else {353info->imrb_value &= ~mask;354write_reg16(info, CHB + IMR, info->imrb_value);355}356}357358#define port_irq_disable(info, mask) \359{ info->pim_value |= (mask); write_reg(info, PIM, info->pim_value); }360361#define port_irq_enable(info, mask) \362{ info->pim_value &= ~(mask); write_reg(info, PIM, info->pim_value); }363364static void rx_start(MGSLPC_INFO *info);365static void rx_stop(MGSLPC_INFO *info);366367static void tx_start(MGSLPC_INFO *info, struct tty_struct *tty);368static void tx_stop(MGSLPC_INFO *info);369static void tx_set_idle(MGSLPC_INFO *info);370371static void get_signals(MGSLPC_INFO *info);372static void set_signals(MGSLPC_INFO *info);373374static void reset_device(MGSLPC_INFO *info);375376static void hdlc_mode(MGSLPC_INFO *info);377static void async_mode(MGSLPC_INFO *info);378379static void tx_timeout(unsigned long context);380381static int carrier_raised(struct tty_port *port);382static void dtr_rts(struct tty_port *port, int onoff);383384#if SYNCLINK_GENERIC_HDLC385#define dev_to_port(D) (dev_to_hdlc(D)->priv)386static void hdlcdev_tx_done(MGSLPC_INFO *info);387static void hdlcdev_rx(MGSLPC_INFO *info, char *buf, int size);388static int hdlcdev_init(MGSLPC_INFO *info);389static void hdlcdev_exit(MGSLPC_INFO *info);390#endif391392static void trace_block(MGSLPC_INFO *info,const char* data, int count, int xmit);393394static bool register_test(MGSLPC_INFO *info);395static bool irq_test(MGSLPC_INFO *info);396static int adapter_test(MGSLPC_INFO *info);397398static int claim_resources(MGSLPC_INFO *info);399static void release_resources(MGSLPC_INFO *info);400static void mgslpc_add_device(MGSLPC_INFO *info);401static void mgslpc_remove_device(MGSLPC_INFO *info);402403static bool rx_get_frame(MGSLPC_INFO *info, struct tty_struct *tty);404static void rx_reset_buffers(MGSLPC_INFO *info);405static int rx_alloc_buffers(MGSLPC_INFO *info);406static void rx_free_buffers(MGSLPC_INFO *info);407408static irqreturn_t mgslpc_isr(int irq, void *dev_id);409410/*411* Bottom half interrupt handlers412*/413static void bh_handler(struct work_struct *work);414static void bh_transmit(MGSLPC_INFO *info, struct tty_struct *tty);415static void bh_status(MGSLPC_INFO *info);416417/*418* ioctl handlers419*/420static int tiocmget(struct tty_struct *tty);421static int tiocmset(struct tty_struct *tty,422unsigned int set, unsigned int clear);423static int get_stats(MGSLPC_INFO *info, struct mgsl_icount __user *user_icount);424static int get_params(MGSLPC_INFO *info, MGSL_PARAMS __user *user_params);425static int set_params(MGSLPC_INFO *info, MGSL_PARAMS __user *new_params, struct tty_struct *tty);426static int get_txidle(MGSLPC_INFO *info, int __user *idle_mode);427static int set_txidle(MGSLPC_INFO *info, int idle_mode);428static int set_txenable(MGSLPC_INFO *info, int enable, struct tty_struct *tty);429static int tx_abort(MGSLPC_INFO *info);430static int set_rxenable(MGSLPC_INFO *info, int enable);431static int wait_events(MGSLPC_INFO *info, int __user *mask);432433static MGSLPC_INFO *mgslpc_device_list = NULL;434static int mgslpc_device_count = 0;435436/*437* Set this param to non-zero to load eax with the438* .text section address and breakpoint on module load.439* This is useful for use with gdb and add-symbol-file command.440*/441static int break_on_load=0;442443/*444* Driver major number, defaults to zero to get auto445* assigned major number. May be forced as module parameter.446*/447static int ttymajor=0;448449static int debug_level = 0;450static int maxframe[MAX_DEVICE_COUNT] = {0,};451452module_param(break_on_load, bool, 0);453module_param(ttymajor, int, 0);454module_param(debug_level, int, 0);455module_param_array(maxframe, int, NULL, 0);456457MODULE_LICENSE("GPL");458459static char *driver_name = "SyncLink PC Card driver";460static char *driver_version = "$Revision: 4.34 $";461462static struct tty_driver *serial_driver;463464/* number of characters left in xmit buffer before we ask for more */465#define WAKEUP_CHARS 256466467static void mgslpc_change_params(MGSLPC_INFO *info, struct tty_struct *tty);468static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout);469470/* PCMCIA prototypes */471472static int mgslpc_config(struct pcmcia_device *link);473static void mgslpc_release(u_long arg);474static void mgslpc_detach(struct pcmcia_device *p_dev);475476/*477* 1st function defined in .text section. Calling this function in478* init_module() followed by a breakpoint allows a remote debugger479* (gdb) to get the .text address for the add-symbol-file command.480* This allows remote debugging of dynamically loadable modules.481*/482static void* mgslpc_get_text_ptr(void)483{484return mgslpc_get_text_ptr;485}486487/**488* line discipline callback wrappers489*490* The wrappers maintain line discipline references491* while calling into the line discipline.492*493* ldisc_receive_buf - pass receive data to line discipline494*/495496static void ldisc_receive_buf(struct tty_struct *tty,497const __u8 *data, char *flags, int count)498{499struct tty_ldisc *ld;500if (!tty)501return;502ld = tty_ldisc_ref(tty);503if (ld) {504if (ld->ops->receive_buf)505ld->ops->receive_buf(tty, data, flags, count);506tty_ldisc_deref(ld);507}508}509510static const struct tty_port_operations mgslpc_port_ops = {511.carrier_raised = carrier_raised,512.dtr_rts = dtr_rts513};514515static int mgslpc_probe(struct pcmcia_device *link)516{517MGSLPC_INFO *info;518int ret;519520if (debug_level >= DEBUG_LEVEL_INFO)521printk("mgslpc_attach\n");522523info = kzalloc(sizeof(MGSLPC_INFO), GFP_KERNEL);524if (!info) {525printk("Error can't allocate device instance data\n");526return -ENOMEM;527}528529info->magic = MGSLPC_MAGIC;530tty_port_init(&info->port);531info->port.ops = &mgslpc_port_ops;532INIT_WORK(&info->task, bh_handler);533info->max_frame_size = 4096;534info->port.close_delay = 5*HZ/10;535info->port.closing_wait = 30*HZ;536init_waitqueue_head(&info->status_event_wait_q);537init_waitqueue_head(&info->event_wait_q);538spin_lock_init(&info->lock);539spin_lock_init(&info->netlock);540memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS));541info->idle_mode = HDLC_TXIDLE_FLAGS;542info->imra_value = 0xffff;543info->imrb_value = 0xffff;544info->pim_value = 0xff;545546info->p_dev = link;547link->priv = info;548549/* Initialize the struct pcmcia_device structure */550551ret = mgslpc_config(link);552if (ret)553return ret;554555mgslpc_add_device(info);556557return 0;558}559560/* Card has been inserted.561*/562563static int mgslpc_ioprobe(struct pcmcia_device *p_dev, void *priv_data)564{565return pcmcia_request_io(p_dev);566}567568static int mgslpc_config(struct pcmcia_device *link)569{570MGSLPC_INFO *info = link->priv;571int ret;572573if (debug_level >= DEBUG_LEVEL_INFO)574printk("mgslpc_config(0x%p)\n", link);575576link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;577578ret = pcmcia_loop_config(link, mgslpc_ioprobe, NULL);579if (ret != 0)580goto failed;581582link->config_index = 8;583link->config_regs = PRESENT_OPTION;584585ret = pcmcia_request_irq(link, mgslpc_isr);586if (ret)587goto failed;588ret = pcmcia_enable_device(link);589if (ret)590goto failed;591592info->io_base = link->resource[0]->start;593info->irq_level = link->irq;594return 0;595596failed:597mgslpc_release((u_long)link);598return -ENODEV;599}600601/* Card has been removed.602* Unregister device and release PCMCIA configuration.603* If device is open, postpone until it is closed.604*/605static void mgslpc_release(u_long arg)606{607struct pcmcia_device *link = (struct pcmcia_device *)arg;608609if (debug_level >= DEBUG_LEVEL_INFO)610printk("mgslpc_release(0x%p)\n", link);611612pcmcia_disable_device(link);613}614615static void mgslpc_detach(struct pcmcia_device *link)616{617if (debug_level >= DEBUG_LEVEL_INFO)618printk("mgslpc_detach(0x%p)\n", link);619620((MGSLPC_INFO *)link->priv)->stop = 1;621mgslpc_release((u_long)link);622623mgslpc_remove_device((MGSLPC_INFO *)link->priv);624}625626static int mgslpc_suspend(struct pcmcia_device *link)627{628MGSLPC_INFO *info = link->priv;629630info->stop = 1;631632return 0;633}634635static int mgslpc_resume(struct pcmcia_device *link)636{637MGSLPC_INFO *info = link->priv;638639info->stop = 0;640641return 0;642}643644645static inline bool mgslpc_paranoia_check(MGSLPC_INFO *info,646char *name, const char *routine)647{648#ifdef MGSLPC_PARANOIA_CHECK649static const char *badmagic =650"Warning: bad magic number for mgsl struct (%s) in %s\n";651static const char *badinfo =652"Warning: null mgslpc_info for (%s) in %s\n";653654if (!info) {655printk(badinfo, name, routine);656return true;657}658if (info->magic != MGSLPC_MAGIC) {659printk(badmagic, name, routine);660return true;661}662#else663if (!info)664return true;665#endif666return false;667}668669670#define CMD_RXFIFO BIT7 // release current rx FIFO671#define CMD_RXRESET BIT6 // receiver reset672#define CMD_RXFIFO_READ BIT5673#define CMD_START_TIMER BIT4674#define CMD_TXFIFO BIT3 // release current tx FIFO675#define CMD_TXEOM BIT1 // transmit end message676#define CMD_TXRESET BIT0 // transmit reset677678static bool wait_command_complete(MGSLPC_INFO *info, unsigned char channel)679{680int i = 0;681/* wait for command completion */682while (read_reg(info, (unsigned char)(channel+STAR)) & BIT2) {683udelay(1);684if (i++ == 1000)685return false;686}687return true;688}689690static void issue_command(MGSLPC_INFO *info, unsigned char channel, unsigned char cmd)691{692wait_command_complete(info, channel);693write_reg(info, (unsigned char) (channel + CMDR), cmd);694}695696static void tx_pause(struct tty_struct *tty)697{698MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;699unsigned long flags;700701if (mgslpc_paranoia_check(info, tty->name, "tx_pause"))702return;703if (debug_level >= DEBUG_LEVEL_INFO)704printk("tx_pause(%s)\n",info->device_name);705706spin_lock_irqsave(&info->lock,flags);707if (info->tx_enabled)708tx_stop(info);709spin_unlock_irqrestore(&info->lock,flags);710}711712static void tx_release(struct tty_struct *tty)713{714MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;715unsigned long flags;716717if (mgslpc_paranoia_check(info, tty->name, "tx_release"))718return;719if (debug_level >= DEBUG_LEVEL_INFO)720printk("tx_release(%s)\n",info->device_name);721722spin_lock_irqsave(&info->lock,flags);723if (!info->tx_enabled)724tx_start(info, tty);725spin_unlock_irqrestore(&info->lock,flags);726}727728/* Return next bottom half action to perform.729* or 0 if nothing to do.730*/731static int bh_action(MGSLPC_INFO *info)732{733unsigned long flags;734int rc = 0;735736spin_lock_irqsave(&info->lock,flags);737738if (info->pending_bh & BH_RECEIVE) {739info->pending_bh &= ~BH_RECEIVE;740rc = BH_RECEIVE;741} else if (info->pending_bh & BH_TRANSMIT) {742info->pending_bh &= ~BH_TRANSMIT;743rc = BH_TRANSMIT;744} else if (info->pending_bh & BH_STATUS) {745info->pending_bh &= ~BH_STATUS;746rc = BH_STATUS;747}748749if (!rc) {750/* Mark BH routine as complete */751info->bh_running = false;752info->bh_requested = false;753}754755spin_unlock_irqrestore(&info->lock,flags);756757return rc;758}759760static void bh_handler(struct work_struct *work)761{762MGSLPC_INFO *info = container_of(work, MGSLPC_INFO, task);763struct tty_struct *tty;764int action;765766if (!info)767return;768769if (debug_level >= DEBUG_LEVEL_BH)770printk( "%s(%d):bh_handler(%s) entry\n",771__FILE__,__LINE__,info->device_name);772773info->bh_running = true;774tty = tty_port_tty_get(&info->port);775776while((action = bh_action(info)) != 0) {777778/* Process work item */779if ( debug_level >= DEBUG_LEVEL_BH )780printk( "%s(%d):bh_handler() work item action=%d\n",781__FILE__,__LINE__,action);782783switch (action) {784785case BH_RECEIVE:786while(rx_get_frame(info, tty));787break;788case BH_TRANSMIT:789bh_transmit(info, tty);790break;791case BH_STATUS:792bh_status(info);793break;794default:795/* unknown work item ID */796printk("Unknown work item ID=%08X!\n", action);797break;798}799}800801tty_kref_put(tty);802if (debug_level >= DEBUG_LEVEL_BH)803printk( "%s(%d):bh_handler(%s) exit\n",804__FILE__,__LINE__,info->device_name);805}806807static void bh_transmit(MGSLPC_INFO *info, struct tty_struct *tty)808{809if (debug_level >= DEBUG_LEVEL_BH)810printk("bh_transmit() entry on %s\n", info->device_name);811812if (tty)813tty_wakeup(tty);814}815816static void bh_status(MGSLPC_INFO *info)817{818info->ri_chkcount = 0;819info->dsr_chkcount = 0;820info->dcd_chkcount = 0;821info->cts_chkcount = 0;822}823824/* eom: non-zero = end of frame */825static void rx_ready_hdlc(MGSLPC_INFO *info, int eom)826{827unsigned char data[2];828unsigned char fifo_count, read_count, i;829RXBUF *buf = (RXBUF*)(info->rx_buf + (info->rx_put * info->rx_buf_size));830831if (debug_level >= DEBUG_LEVEL_ISR)832printk("%s(%d):rx_ready_hdlc(eom=%d)\n",__FILE__,__LINE__,eom);833834if (!info->rx_enabled)835return;836837if (info->rx_frame_count >= info->rx_buf_count) {838/* no more free buffers */839issue_command(info, CHA, CMD_RXRESET);840info->pending_bh |= BH_RECEIVE;841info->rx_overflow = true;842info->icount.buf_overrun++;843return;844}845846if (eom) {847/* end of frame, get FIFO count from RBCL register */848if (!(fifo_count = (unsigned char)(read_reg(info, CHA+RBCL) & 0x1f)))849fifo_count = 32;850} else851fifo_count = 32;852853do {854if (fifo_count == 1) {855read_count = 1;856data[0] = read_reg(info, CHA + RXFIFO);857} else {858read_count = 2;859*((unsigned short *) data) = read_reg16(info, CHA + RXFIFO);860}861fifo_count -= read_count;862if (!fifo_count && eom)863buf->status = data[--read_count];864865for (i = 0; i < read_count; i++) {866if (buf->count >= info->max_frame_size) {867/* frame too large, reset receiver and reset current buffer */868issue_command(info, CHA, CMD_RXRESET);869buf->count = 0;870return;871}872*(buf->data + buf->count) = data[i];873buf->count++;874}875} while (fifo_count);876877if (eom) {878info->pending_bh |= BH_RECEIVE;879info->rx_frame_count++;880info->rx_put++;881if (info->rx_put >= info->rx_buf_count)882info->rx_put = 0;883}884issue_command(info, CHA, CMD_RXFIFO);885}886887static void rx_ready_async(MGSLPC_INFO *info, int tcd, struct tty_struct *tty)888{889unsigned char data, status, flag;890int fifo_count;891int work = 0;892struct mgsl_icount *icount = &info->icount;893894if (tcd) {895/* early termination, get FIFO count from RBCL register */896fifo_count = (unsigned char)(read_reg(info, CHA+RBCL) & 0x1f);897898/* Zero fifo count could mean 0 or 32 bytes available.899* If BIT5 of STAR is set then at least 1 byte is available.900*/901if (!fifo_count && (read_reg(info,CHA+STAR) & BIT5))902fifo_count = 32;903} else904fifo_count = 32;905906tty_buffer_request_room(tty, fifo_count);907/* Flush received async data to receive data buffer. */908while (fifo_count) {909data = read_reg(info, CHA + RXFIFO);910status = read_reg(info, CHA + RXFIFO);911fifo_count -= 2;912913icount->rx++;914flag = TTY_NORMAL;915916// if no frameing/crc error then save data917// BIT7:parity error918// BIT6:framing error919920if (status & (BIT7 + BIT6)) {921if (status & BIT7)922icount->parity++;923else924icount->frame++;925926/* discard char if tty control flags say so */927if (status & info->ignore_status_mask)928continue;929930status &= info->read_status_mask;931932if (status & BIT7)933flag = TTY_PARITY;934else if (status & BIT6)935flag = TTY_FRAME;936}937work += tty_insert_flip_char(tty, data, flag);938}939issue_command(info, CHA, CMD_RXFIFO);940941if (debug_level >= DEBUG_LEVEL_ISR) {942printk("%s(%d):rx_ready_async",943__FILE__,__LINE__);944printk("%s(%d):rx=%d brk=%d parity=%d frame=%d overrun=%d\n",945__FILE__,__LINE__,icount->rx,icount->brk,946icount->parity,icount->frame,icount->overrun);947}948949if (work)950tty_flip_buffer_push(tty);951}952953954static void tx_done(MGSLPC_INFO *info, struct tty_struct *tty)955{956if (!info->tx_active)957return;958959info->tx_active = false;960info->tx_aborting = false;961962if (info->params.mode == MGSL_MODE_ASYNC)963return;964965info->tx_count = info->tx_put = info->tx_get = 0;966del_timer(&info->tx_timer);967968if (info->drop_rts_on_tx_done) {969get_signals(info);970if (info->serial_signals & SerialSignal_RTS) {971info->serial_signals &= ~SerialSignal_RTS;972set_signals(info);973}974info->drop_rts_on_tx_done = false;975}976977#if SYNCLINK_GENERIC_HDLC978if (info->netcount)979hdlcdev_tx_done(info);980else981#endif982{983if (tty->stopped || tty->hw_stopped) {984tx_stop(info);985return;986}987info->pending_bh |= BH_TRANSMIT;988}989}990991static void tx_ready(MGSLPC_INFO *info, struct tty_struct *tty)992{993unsigned char fifo_count = 32;994int c;995996if (debug_level >= DEBUG_LEVEL_ISR)997printk("%s(%d):tx_ready(%s)\n", __FILE__,__LINE__,info->device_name);998999if (info->params.mode == MGSL_MODE_HDLC) {1000if (!info->tx_active)1001return;1002} else {1003if (tty->stopped || tty->hw_stopped) {1004tx_stop(info);1005return;1006}1007if (!info->tx_count)1008info->tx_active = false;1009}10101011if (!info->tx_count)1012return;10131014while (info->tx_count && fifo_count) {1015c = min(2, min_t(int, fifo_count, min(info->tx_count, TXBUFSIZE - info->tx_get)));10161017if (c == 1) {1018write_reg(info, CHA + TXFIFO, *(info->tx_buf + info->tx_get));1019} else {1020write_reg16(info, CHA + TXFIFO,1021*((unsigned short*)(info->tx_buf + info->tx_get)));1022}1023info->tx_count -= c;1024info->tx_get = (info->tx_get + c) & (TXBUFSIZE - 1);1025fifo_count -= c;1026}10271028if (info->params.mode == MGSL_MODE_ASYNC) {1029if (info->tx_count < WAKEUP_CHARS)1030info->pending_bh |= BH_TRANSMIT;1031issue_command(info, CHA, CMD_TXFIFO);1032} else {1033if (info->tx_count)1034issue_command(info, CHA, CMD_TXFIFO);1035else1036issue_command(info, CHA, CMD_TXFIFO + CMD_TXEOM);1037}1038}10391040static void cts_change(MGSLPC_INFO *info, struct tty_struct *tty)1041{1042get_signals(info);1043if ((info->cts_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)1044irq_disable(info, CHB, IRQ_CTS);1045info->icount.cts++;1046if (info->serial_signals & SerialSignal_CTS)1047info->input_signal_events.cts_up++;1048else1049info->input_signal_events.cts_down++;1050wake_up_interruptible(&info->status_event_wait_q);1051wake_up_interruptible(&info->event_wait_q);10521053if (info->port.flags & ASYNC_CTS_FLOW) {1054if (tty->hw_stopped) {1055if (info->serial_signals & SerialSignal_CTS) {1056if (debug_level >= DEBUG_LEVEL_ISR)1057printk("CTS tx start...");1058if (tty)1059tty->hw_stopped = 0;1060tx_start(info, tty);1061info->pending_bh |= BH_TRANSMIT;1062return;1063}1064} else {1065if (!(info->serial_signals & SerialSignal_CTS)) {1066if (debug_level >= DEBUG_LEVEL_ISR)1067printk("CTS tx stop...");1068if (tty)1069tty->hw_stopped = 1;1070tx_stop(info);1071}1072}1073}1074info->pending_bh |= BH_STATUS;1075}10761077static void dcd_change(MGSLPC_INFO *info, struct tty_struct *tty)1078{1079get_signals(info);1080if ((info->dcd_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)1081irq_disable(info, CHB, IRQ_DCD);1082info->icount.dcd++;1083if (info->serial_signals & SerialSignal_DCD) {1084info->input_signal_events.dcd_up++;1085}1086else1087info->input_signal_events.dcd_down++;1088#if SYNCLINK_GENERIC_HDLC1089if (info->netcount) {1090if (info->serial_signals & SerialSignal_DCD)1091netif_carrier_on(info->netdev);1092else1093netif_carrier_off(info->netdev);1094}1095#endif1096wake_up_interruptible(&info->status_event_wait_q);1097wake_up_interruptible(&info->event_wait_q);10981099if (info->port.flags & ASYNC_CHECK_CD) {1100if (debug_level >= DEBUG_LEVEL_ISR)1101printk("%s CD now %s...", info->device_name,1102(info->serial_signals & SerialSignal_DCD) ? "on" : "off");1103if (info->serial_signals & SerialSignal_DCD)1104wake_up_interruptible(&info->port.open_wait);1105else {1106if (debug_level >= DEBUG_LEVEL_ISR)1107printk("doing serial hangup...");1108if (tty)1109tty_hangup(tty);1110}1111}1112info->pending_bh |= BH_STATUS;1113}11141115static void dsr_change(MGSLPC_INFO *info)1116{1117get_signals(info);1118if ((info->dsr_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)1119port_irq_disable(info, PVR_DSR);1120info->icount.dsr++;1121if (info->serial_signals & SerialSignal_DSR)1122info->input_signal_events.dsr_up++;1123else1124info->input_signal_events.dsr_down++;1125wake_up_interruptible(&info->status_event_wait_q);1126wake_up_interruptible(&info->event_wait_q);1127info->pending_bh |= BH_STATUS;1128}11291130static void ri_change(MGSLPC_INFO *info)1131{1132get_signals(info);1133if ((info->ri_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)1134port_irq_disable(info, PVR_RI);1135info->icount.rng++;1136if (info->serial_signals & SerialSignal_RI)1137info->input_signal_events.ri_up++;1138else1139info->input_signal_events.ri_down++;1140wake_up_interruptible(&info->status_event_wait_q);1141wake_up_interruptible(&info->event_wait_q);1142info->pending_bh |= BH_STATUS;1143}11441145/* Interrupt service routine entry point.1146*1147* Arguments:1148*1149* irq interrupt number that caused interrupt1150* dev_id device ID supplied during interrupt registration1151*/1152static irqreturn_t mgslpc_isr(int dummy, void *dev_id)1153{1154MGSLPC_INFO *info = dev_id;1155struct tty_struct *tty;1156unsigned short isr;1157unsigned char gis, pis;1158int count=0;11591160if (debug_level >= DEBUG_LEVEL_ISR)1161printk("mgslpc_isr(%d) entry.\n", info->irq_level);11621163if (!(info->p_dev->_locked))1164return IRQ_HANDLED;11651166tty = tty_port_tty_get(&info->port);11671168spin_lock(&info->lock);11691170while ((gis = read_reg(info, CHA + GIS))) {1171if (debug_level >= DEBUG_LEVEL_ISR)1172printk("mgslpc_isr %s gis=%04X\n", info->device_name,gis);11731174if ((gis & 0x70) || count > 1000) {1175printk("synclink_cs:hardware failed or ejected\n");1176break;1177}1178count++;11791180if (gis & (BIT1 + BIT0)) {1181isr = read_reg16(info, CHB + ISR);1182if (isr & IRQ_DCD)1183dcd_change(info, tty);1184if (isr & IRQ_CTS)1185cts_change(info, tty);1186}1187if (gis & (BIT3 + BIT2))1188{1189isr = read_reg16(info, CHA + ISR);1190if (isr & IRQ_TIMER) {1191info->irq_occurred = true;1192irq_disable(info, CHA, IRQ_TIMER);1193}11941195/* receive IRQs */1196if (isr & IRQ_EXITHUNT) {1197info->icount.exithunt++;1198wake_up_interruptible(&info->event_wait_q);1199}1200if (isr & IRQ_BREAK_ON) {1201info->icount.brk++;1202if (info->port.flags & ASYNC_SAK)1203do_SAK(tty);1204}1205if (isr & IRQ_RXTIME) {1206issue_command(info, CHA, CMD_RXFIFO_READ);1207}1208if (isr & (IRQ_RXEOM + IRQ_RXFIFO)) {1209if (info->params.mode == MGSL_MODE_HDLC)1210rx_ready_hdlc(info, isr & IRQ_RXEOM);1211else1212rx_ready_async(info, isr & IRQ_RXEOM, tty);1213}12141215/* transmit IRQs */1216if (isr & IRQ_UNDERRUN) {1217if (info->tx_aborting)1218info->icount.txabort++;1219else1220info->icount.txunder++;1221tx_done(info, tty);1222}1223else if (isr & IRQ_ALLSENT) {1224info->icount.txok++;1225tx_done(info, tty);1226}1227else if (isr & IRQ_TXFIFO)1228tx_ready(info, tty);1229}1230if (gis & BIT7) {1231pis = read_reg(info, CHA + PIS);1232if (pis & BIT1)1233dsr_change(info);1234if (pis & BIT2)1235ri_change(info);1236}1237}12381239/* Request bottom half processing if there's something1240* for it to do and the bh is not already running1241*/12421243if (info->pending_bh && !info->bh_running && !info->bh_requested) {1244if ( debug_level >= DEBUG_LEVEL_ISR )1245printk("%s(%d):%s queueing bh task.\n",1246__FILE__,__LINE__,info->device_name);1247schedule_work(&info->task);1248info->bh_requested = true;1249}12501251spin_unlock(&info->lock);1252tty_kref_put(tty);12531254if (debug_level >= DEBUG_LEVEL_ISR)1255printk("%s(%d):mgslpc_isr(%d)exit.\n",1256__FILE__, __LINE__, info->irq_level);12571258return IRQ_HANDLED;1259}12601261/* Initialize and start device.1262*/1263static int startup(MGSLPC_INFO * info, struct tty_struct *tty)1264{1265int retval = 0;12661267if (debug_level >= DEBUG_LEVEL_INFO)1268printk("%s(%d):startup(%s)\n",__FILE__,__LINE__,info->device_name);12691270if (info->port.flags & ASYNC_INITIALIZED)1271return 0;12721273if (!info->tx_buf) {1274/* allocate a page of memory for a transmit buffer */1275info->tx_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);1276if (!info->tx_buf) {1277printk(KERN_ERR"%s(%d):%s can't allocate transmit buffer\n",1278__FILE__,__LINE__,info->device_name);1279return -ENOMEM;1280}1281}12821283info->pending_bh = 0;12841285memset(&info->icount, 0, sizeof(info->icount));12861287setup_timer(&info->tx_timer, tx_timeout, (unsigned long)info);12881289/* Allocate and claim adapter resources */1290retval = claim_resources(info);12911292/* perform existence check and diagnostics */1293if ( !retval )1294retval = adapter_test(info);12951296if ( retval ) {1297if (capable(CAP_SYS_ADMIN) && tty)1298set_bit(TTY_IO_ERROR, &tty->flags);1299release_resources(info);1300return retval;1301}13021303/* program hardware for current parameters */1304mgslpc_change_params(info, tty);13051306if (tty)1307clear_bit(TTY_IO_ERROR, &tty->flags);13081309info->port.flags |= ASYNC_INITIALIZED;13101311return 0;1312}13131314/* Called by mgslpc_close() and mgslpc_hangup() to shutdown hardware1315*/1316static void shutdown(MGSLPC_INFO * info, struct tty_struct *tty)1317{1318unsigned long flags;13191320if (!(info->port.flags & ASYNC_INITIALIZED))1321return;13221323if (debug_level >= DEBUG_LEVEL_INFO)1324printk("%s(%d):mgslpc_shutdown(%s)\n",1325__FILE__,__LINE__, info->device_name );13261327/* clear status wait queue because status changes */1328/* can't happen after shutting down the hardware */1329wake_up_interruptible(&info->status_event_wait_q);1330wake_up_interruptible(&info->event_wait_q);13311332del_timer_sync(&info->tx_timer);13331334if (info->tx_buf) {1335free_page((unsigned long) info->tx_buf);1336info->tx_buf = NULL;1337}13381339spin_lock_irqsave(&info->lock,flags);13401341rx_stop(info);1342tx_stop(info);13431344/* TODO:disable interrupts instead of reset to preserve signal states */1345reset_device(info);13461347if (!tty || tty->termios->c_cflag & HUPCL) {1348info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS);1349set_signals(info);1350}13511352spin_unlock_irqrestore(&info->lock,flags);13531354release_resources(info);13551356if (tty)1357set_bit(TTY_IO_ERROR, &tty->flags);13581359info->port.flags &= ~ASYNC_INITIALIZED;1360}13611362static void mgslpc_program_hw(MGSLPC_INFO *info, struct tty_struct *tty)1363{1364unsigned long flags;13651366spin_lock_irqsave(&info->lock,flags);13671368rx_stop(info);1369tx_stop(info);1370info->tx_count = info->tx_put = info->tx_get = 0;13711372if (info->params.mode == MGSL_MODE_HDLC || info->netcount)1373hdlc_mode(info);1374else1375async_mode(info);13761377set_signals(info);13781379info->dcd_chkcount = 0;1380info->cts_chkcount = 0;1381info->ri_chkcount = 0;1382info->dsr_chkcount = 0;13831384irq_enable(info, CHB, IRQ_DCD | IRQ_CTS);1385port_irq_enable(info, (unsigned char) PVR_DSR | PVR_RI);1386get_signals(info);13871388if (info->netcount || (tty && (tty->termios->c_cflag & CREAD)))1389rx_start(info);13901391spin_unlock_irqrestore(&info->lock,flags);1392}13931394/* Reconfigure adapter based on new parameters1395*/1396static void mgslpc_change_params(MGSLPC_INFO *info, struct tty_struct *tty)1397{1398unsigned cflag;1399int bits_per_char;14001401if (!tty || !tty->termios)1402return;14031404if (debug_level >= DEBUG_LEVEL_INFO)1405printk("%s(%d):mgslpc_change_params(%s)\n",1406__FILE__,__LINE__, info->device_name );14071408cflag = tty->termios->c_cflag;14091410/* if B0 rate (hangup) specified then negate DTR and RTS */1411/* otherwise assert DTR and RTS */1412if (cflag & CBAUD)1413info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;1414else1415info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);14161417/* byte size and parity */14181419switch (cflag & CSIZE) {1420case CS5: info->params.data_bits = 5; break;1421case CS6: info->params.data_bits = 6; break;1422case CS7: info->params.data_bits = 7; break;1423case CS8: info->params.data_bits = 8; break;1424default: info->params.data_bits = 7; break;1425}14261427if (cflag & CSTOPB)1428info->params.stop_bits = 2;1429else1430info->params.stop_bits = 1;14311432info->params.parity = ASYNC_PARITY_NONE;1433if (cflag & PARENB) {1434if (cflag & PARODD)1435info->params.parity = ASYNC_PARITY_ODD;1436else1437info->params.parity = ASYNC_PARITY_EVEN;1438#ifdef CMSPAR1439if (cflag & CMSPAR)1440info->params.parity = ASYNC_PARITY_SPACE;1441#endif1442}14431444/* calculate number of jiffies to transmit a full1445* FIFO (32 bytes) at specified data rate1446*/1447bits_per_char = info->params.data_bits +1448info->params.stop_bits + 1;14491450/* if port data rate is set to 460800 or less then1451* allow tty settings to override, otherwise keep the1452* current data rate.1453*/1454if (info->params.data_rate <= 460800) {1455info->params.data_rate = tty_get_baud_rate(tty);1456}14571458if ( info->params.data_rate ) {1459info->timeout = (32*HZ*bits_per_char) /1460info->params.data_rate;1461}1462info->timeout += HZ/50; /* Add .02 seconds of slop */14631464if (cflag & CRTSCTS)1465info->port.flags |= ASYNC_CTS_FLOW;1466else1467info->port.flags &= ~ASYNC_CTS_FLOW;14681469if (cflag & CLOCAL)1470info->port.flags &= ~ASYNC_CHECK_CD;1471else1472info->port.flags |= ASYNC_CHECK_CD;14731474/* process tty input control flags */14751476info->read_status_mask = 0;1477if (I_INPCK(tty))1478info->read_status_mask |= BIT7 | BIT6;1479if (I_IGNPAR(tty))1480info->ignore_status_mask |= BIT7 | BIT6;14811482mgslpc_program_hw(info, tty);1483}14841485/* Add a character to the transmit buffer1486*/1487static int mgslpc_put_char(struct tty_struct *tty, unsigned char ch)1488{1489MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;1490unsigned long flags;14911492if (debug_level >= DEBUG_LEVEL_INFO) {1493printk( "%s(%d):mgslpc_put_char(%d) on %s\n",1494__FILE__,__LINE__,ch,info->device_name);1495}14961497if (mgslpc_paranoia_check(info, tty->name, "mgslpc_put_char"))1498return 0;14991500if (!info->tx_buf)1501return 0;15021503spin_lock_irqsave(&info->lock,flags);15041505if (info->params.mode == MGSL_MODE_ASYNC || !info->tx_active) {1506if (info->tx_count < TXBUFSIZE - 1) {1507info->tx_buf[info->tx_put++] = ch;1508info->tx_put &= TXBUFSIZE-1;1509info->tx_count++;1510}1511}15121513spin_unlock_irqrestore(&info->lock,flags);1514return 1;1515}15161517/* Enable transmitter so remaining characters in the1518* transmit buffer are sent.1519*/1520static void mgslpc_flush_chars(struct tty_struct *tty)1521{1522MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;1523unsigned long flags;15241525if (debug_level >= DEBUG_LEVEL_INFO)1526printk( "%s(%d):mgslpc_flush_chars() entry on %s tx_count=%d\n",1527__FILE__,__LINE__,info->device_name,info->tx_count);15281529if (mgslpc_paranoia_check(info, tty->name, "mgslpc_flush_chars"))1530return;15311532if (info->tx_count <= 0 || tty->stopped ||1533tty->hw_stopped || !info->tx_buf)1534return;15351536if (debug_level >= DEBUG_LEVEL_INFO)1537printk( "%s(%d):mgslpc_flush_chars() entry on %s starting transmitter\n",1538__FILE__,__LINE__,info->device_name);15391540spin_lock_irqsave(&info->lock,flags);1541if (!info->tx_active)1542tx_start(info, tty);1543spin_unlock_irqrestore(&info->lock,flags);1544}15451546/* Send a block of data1547*1548* Arguments:1549*1550* tty pointer to tty information structure1551* buf pointer to buffer containing send data1552* count size of send data in bytes1553*1554* Returns: number of characters written1555*/1556static int mgslpc_write(struct tty_struct * tty,1557const unsigned char *buf, int count)1558{1559int c, ret = 0;1560MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;1561unsigned long flags;15621563if (debug_level >= DEBUG_LEVEL_INFO)1564printk( "%s(%d):mgslpc_write(%s) count=%d\n",1565__FILE__,__LINE__,info->device_name,count);15661567if (mgslpc_paranoia_check(info, tty->name, "mgslpc_write") ||1568!info->tx_buf)1569goto cleanup;15701571if (info->params.mode == MGSL_MODE_HDLC) {1572if (count > TXBUFSIZE) {1573ret = -EIO;1574goto cleanup;1575}1576if (info->tx_active)1577goto cleanup;1578else if (info->tx_count)1579goto start;1580}15811582for (;;) {1583c = min(count,1584min(TXBUFSIZE - info->tx_count - 1,1585TXBUFSIZE - info->tx_put));1586if (c <= 0)1587break;15881589memcpy(info->tx_buf + info->tx_put, buf, c);15901591spin_lock_irqsave(&info->lock,flags);1592info->tx_put = (info->tx_put + c) & (TXBUFSIZE-1);1593info->tx_count += c;1594spin_unlock_irqrestore(&info->lock,flags);15951596buf += c;1597count -= c;1598ret += c;1599}1600start:1601if (info->tx_count && !tty->stopped && !tty->hw_stopped) {1602spin_lock_irqsave(&info->lock,flags);1603if (!info->tx_active)1604tx_start(info, tty);1605spin_unlock_irqrestore(&info->lock,flags);1606}1607cleanup:1608if (debug_level >= DEBUG_LEVEL_INFO)1609printk( "%s(%d):mgslpc_write(%s) returning=%d\n",1610__FILE__,__LINE__,info->device_name,ret);1611return ret;1612}16131614/* Return the count of free bytes in transmit buffer1615*/1616static int mgslpc_write_room(struct tty_struct *tty)1617{1618MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;1619int ret;16201621if (mgslpc_paranoia_check(info, tty->name, "mgslpc_write_room"))1622return 0;16231624if (info->params.mode == MGSL_MODE_HDLC) {1625/* HDLC (frame oriented) mode */1626if (info->tx_active)1627return 0;1628else1629return HDLC_MAX_FRAME_SIZE;1630} else {1631ret = TXBUFSIZE - info->tx_count - 1;1632if (ret < 0)1633ret = 0;1634}16351636if (debug_level >= DEBUG_LEVEL_INFO)1637printk("%s(%d):mgslpc_write_room(%s)=%d\n",1638__FILE__,__LINE__, info->device_name, ret);1639return ret;1640}16411642/* Return the count of bytes in transmit buffer1643*/1644static int mgslpc_chars_in_buffer(struct tty_struct *tty)1645{1646MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;1647int rc;16481649if (debug_level >= DEBUG_LEVEL_INFO)1650printk("%s(%d):mgslpc_chars_in_buffer(%s)\n",1651__FILE__,__LINE__, info->device_name );16521653if (mgslpc_paranoia_check(info, tty->name, "mgslpc_chars_in_buffer"))1654return 0;16551656if (info->params.mode == MGSL_MODE_HDLC)1657rc = info->tx_active ? info->max_frame_size : 0;1658else1659rc = info->tx_count;16601661if (debug_level >= DEBUG_LEVEL_INFO)1662printk("%s(%d):mgslpc_chars_in_buffer(%s)=%d\n",1663__FILE__,__LINE__, info->device_name, rc);16641665return rc;1666}16671668/* Discard all data in the send buffer1669*/1670static void mgslpc_flush_buffer(struct tty_struct *tty)1671{1672MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;1673unsigned long flags;16741675if (debug_level >= DEBUG_LEVEL_INFO)1676printk("%s(%d):mgslpc_flush_buffer(%s) entry\n",1677__FILE__,__LINE__, info->device_name );16781679if (mgslpc_paranoia_check(info, tty->name, "mgslpc_flush_buffer"))1680return;16811682spin_lock_irqsave(&info->lock,flags);1683info->tx_count = info->tx_put = info->tx_get = 0;1684del_timer(&info->tx_timer);1685spin_unlock_irqrestore(&info->lock,flags);16861687wake_up_interruptible(&tty->write_wait);1688tty_wakeup(tty);1689}16901691/* Send a high-priority XON/XOFF character1692*/1693static void mgslpc_send_xchar(struct tty_struct *tty, char ch)1694{1695MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;1696unsigned long flags;16971698if (debug_level >= DEBUG_LEVEL_INFO)1699printk("%s(%d):mgslpc_send_xchar(%s,%d)\n",1700__FILE__,__LINE__, info->device_name, ch );17011702if (mgslpc_paranoia_check(info, tty->name, "mgslpc_send_xchar"))1703return;17041705info->x_char = ch;1706if (ch) {1707spin_lock_irqsave(&info->lock,flags);1708if (!info->tx_enabled)1709tx_start(info, tty);1710spin_unlock_irqrestore(&info->lock,flags);1711}1712}17131714/* Signal remote device to throttle send data (our receive data)1715*/1716static void mgslpc_throttle(struct tty_struct * tty)1717{1718MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;1719unsigned long flags;17201721if (debug_level >= DEBUG_LEVEL_INFO)1722printk("%s(%d):mgslpc_throttle(%s) entry\n",1723__FILE__,__LINE__, info->device_name );17241725if (mgslpc_paranoia_check(info, tty->name, "mgslpc_throttle"))1726return;17271728if (I_IXOFF(tty))1729mgslpc_send_xchar(tty, STOP_CHAR(tty));17301731if (tty->termios->c_cflag & CRTSCTS) {1732spin_lock_irqsave(&info->lock,flags);1733info->serial_signals &= ~SerialSignal_RTS;1734set_signals(info);1735spin_unlock_irqrestore(&info->lock,flags);1736}1737}17381739/* Signal remote device to stop throttling send data (our receive data)1740*/1741static void mgslpc_unthrottle(struct tty_struct * tty)1742{1743MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;1744unsigned long flags;17451746if (debug_level >= DEBUG_LEVEL_INFO)1747printk("%s(%d):mgslpc_unthrottle(%s) entry\n",1748__FILE__,__LINE__, info->device_name );17491750if (mgslpc_paranoia_check(info, tty->name, "mgslpc_unthrottle"))1751return;17521753if (I_IXOFF(tty)) {1754if (info->x_char)1755info->x_char = 0;1756else1757mgslpc_send_xchar(tty, START_CHAR(tty));1758}17591760if (tty->termios->c_cflag & CRTSCTS) {1761spin_lock_irqsave(&info->lock,flags);1762info->serial_signals |= SerialSignal_RTS;1763set_signals(info);1764spin_unlock_irqrestore(&info->lock,flags);1765}1766}17671768/* get the current serial statistics1769*/1770static int get_stats(MGSLPC_INFO * info, struct mgsl_icount __user *user_icount)1771{1772int err;1773if (debug_level >= DEBUG_LEVEL_INFO)1774printk("get_params(%s)\n", info->device_name);1775if (!user_icount) {1776memset(&info->icount, 0, sizeof(info->icount));1777} else {1778COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount));1779if (err)1780return -EFAULT;1781}1782return 0;1783}17841785/* get the current serial parameters1786*/1787static int get_params(MGSLPC_INFO * info, MGSL_PARAMS __user *user_params)1788{1789int err;1790if (debug_level >= DEBUG_LEVEL_INFO)1791printk("get_params(%s)\n", info->device_name);1792COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS));1793if (err)1794return -EFAULT;1795return 0;1796}17971798/* set the serial parameters1799*1800* Arguments:1801*1802* info pointer to device instance data1803* new_params user buffer containing new serial params1804*1805* Returns: 0 if success, otherwise error code1806*/1807static int set_params(MGSLPC_INFO * info, MGSL_PARAMS __user *new_params, struct tty_struct *tty)1808{1809unsigned long flags;1810MGSL_PARAMS tmp_params;1811int err;18121813if (debug_level >= DEBUG_LEVEL_INFO)1814printk("%s(%d):set_params %s\n", __FILE__,__LINE__,1815info->device_name );1816COPY_FROM_USER(err,&tmp_params, new_params, sizeof(MGSL_PARAMS));1817if (err) {1818if ( debug_level >= DEBUG_LEVEL_INFO )1819printk( "%s(%d):set_params(%s) user buffer copy failed\n",1820__FILE__,__LINE__,info->device_name);1821return -EFAULT;1822}18231824spin_lock_irqsave(&info->lock,flags);1825memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS));1826spin_unlock_irqrestore(&info->lock,flags);18271828mgslpc_change_params(info, tty);18291830return 0;1831}18321833static int get_txidle(MGSLPC_INFO * info, int __user *idle_mode)1834{1835int err;1836if (debug_level >= DEBUG_LEVEL_INFO)1837printk("get_txidle(%s)=%d\n", info->device_name, info->idle_mode);1838COPY_TO_USER(err,idle_mode, &info->idle_mode, sizeof(int));1839if (err)1840return -EFAULT;1841return 0;1842}18431844static int set_txidle(MGSLPC_INFO * info, int idle_mode)1845{1846unsigned long flags;1847if (debug_level >= DEBUG_LEVEL_INFO)1848printk("set_txidle(%s,%d)\n", info->device_name, idle_mode);1849spin_lock_irqsave(&info->lock,flags);1850info->idle_mode = idle_mode;1851tx_set_idle(info);1852spin_unlock_irqrestore(&info->lock,flags);1853return 0;1854}18551856static int get_interface(MGSLPC_INFO * info, int __user *if_mode)1857{1858int err;1859if (debug_level >= DEBUG_LEVEL_INFO)1860printk("get_interface(%s)=%d\n", info->device_name, info->if_mode);1861COPY_TO_USER(err,if_mode, &info->if_mode, sizeof(int));1862if (err)1863return -EFAULT;1864return 0;1865}18661867static int set_interface(MGSLPC_INFO * info, int if_mode)1868{1869unsigned long flags;1870unsigned char val;1871if (debug_level >= DEBUG_LEVEL_INFO)1872printk("set_interface(%s,%d)\n", info->device_name, if_mode);1873spin_lock_irqsave(&info->lock,flags);1874info->if_mode = if_mode;18751876val = read_reg(info, PVR) & 0x0f;1877switch (info->if_mode)1878{1879case MGSL_INTERFACE_RS232: val |= PVR_RS232; break;1880case MGSL_INTERFACE_V35: val |= PVR_V35; break;1881case MGSL_INTERFACE_RS422: val |= PVR_RS422; break;1882}1883write_reg(info, PVR, val);18841885spin_unlock_irqrestore(&info->lock,flags);1886return 0;1887}18881889static int set_txenable(MGSLPC_INFO * info, int enable, struct tty_struct *tty)1890{1891unsigned long flags;18921893if (debug_level >= DEBUG_LEVEL_INFO)1894printk("set_txenable(%s,%d)\n", info->device_name, enable);18951896spin_lock_irqsave(&info->lock,flags);1897if (enable) {1898if (!info->tx_enabled)1899tx_start(info, tty);1900} else {1901if (info->tx_enabled)1902tx_stop(info);1903}1904spin_unlock_irqrestore(&info->lock,flags);1905return 0;1906}19071908static int tx_abort(MGSLPC_INFO * info)1909{1910unsigned long flags;19111912if (debug_level >= DEBUG_LEVEL_INFO)1913printk("tx_abort(%s)\n", info->device_name);19141915spin_lock_irqsave(&info->lock,flags);1916if (info->tx_active && info->tx_count &&1917info->params.mode == MGSL_MODE_HDLC) {1918/* clear data count so FIFO is not filled on next IRQ.1919* This results in underrun and abort transmission.1920*/1921info->tx_count = info->tx_put = info->tx_get = 0;1922info->tx_aborting = true;1923}1924spin_unlock_irqrestore(&info->lock,flags);1925return 0;1926}19271928static int set_rxenable(MGSLPC_INFO * info, int enable)1929{1930unsigned long flags;19311932if (debug_level >= DEBUG_LEVEL_INFO)1933printk("set_rxenable(%s,%d)\n", info->device_name, enable);19341935spin_lock_irqsave(&info->lock,flags);1936if (enable) {1937if (!info->rx_enabled)1938rx_start(info);1939} else {1940if (info->rx_enabled)1941rx_stop(info);1942}1943spin_unlock_irqrestore(&info->lock,flags);1944return 0;1945}19461947/* wait for specified event to occur1948*1949* Arguments: info pointer to device instance data1950* mask pointer to bitmask of events to wait for1951* Return Value: 0 if successful and bit mask updated with1952* of events triggerred,1953* otherwise error code1954*/1955static int wait_events(MGSLPC_INFO * info, int __user *mask_ptr)1956{1957unsigned long flags;1958int s;1959int rc=0;1960struct mgsl_icount cprev, cnow;1961int events;1962int mask;1963struct _input_signal_events oldsigs, newsigs;1964DECLARE_WAITQUEUE(wait, current);19651966COPY_FROM_USER(rc,&mask, mask_ptr, sizeof(int));1967if (rc)1968return -EFAULT;19691970if (debug_level >= DEBUG_LEVEL_INFO)1971printk("wait_events(%s,%d)\n", info->device_name, mask);19721973spin_lock_irqsave(&info->lock,flags);19741975/* return immediately if state matches requested events */1976get_signals(info);1977s = info->serial_signals;1978events = mask &1979( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) +1980((s & SerialSignal_DCD) ? MgslEvent_DcdActive:MgslEvent_DcdInactive) +1981((s & SerialSignal_CTS) ? MgslEvent_CtsActive:MgslEvent_CtsInactive) +1982((s & SerialSignal_RI) ? MgslEvent_RiActive :MgslEvent_RiInactive) );1983if (events) {1984spin_unlock_irqrestore(&info->lock,flags);1985goto exit;1986}19871988/* save current irq counts */1989cprev = info->icount;1990oldsigs = info->input_signal_events;19911992if ((info->params.mode == MGSL_MODE_HDLC) &&1993(mask & MgslEvent_ExitHuntMode))1994irq_enable(info, CHA, IRQ_EXITHUNT);19951996set_current_state(TASK_INTERRUPTIBLE);1997add_wait_queue(&info->event_wait_q, &wait);19981999spin_unlock_irqrestore(&info->lock,flags);200020012002for(;;) {2003schedule();2004if (signal_pending(current)) {2005rc = -ERESTARTSYS;2006break;2007}20082009/* get current irq counts */2010spin_lock_irqsave(&info->lock,flags);2011cnow = info->icount;2012newsigs = info->input_signal_events;2013set_current_state(TASK_INTERRUPTIBLE);2014spin_unlock_irqrestore(&info->lock,flags);20152016/* if no change, wait aborted for some reason */2017if (newsigs.dsr_up == oldsigs.dsr_up &&2018newsigs.dsr_down == oldsigs.dsr_down &&2019newsigs.dcd_up == oldsigs.dcd_up &&2020newsigs.dcd_down == oldsigs.dcd_down &&2021newsigs.cts_up == oldsigs.cts_up &&2022newsigs.cts_down == oldsigs.cts_down &&2023newsigs.ri_up == oldsigs.ri_up &&2024newsigs.ri_down == oldsigs.ri_down &&2025cnow.exithunt == cprev.exithunt &&2026cnow.rxidle == cprev.rxidle) {2027rc = -EIO;2028break;2029}20302031events = mask &2032( (newsigs.dsr_up != oldsigs.dsr_up ? MgslEvent_DsrActive:0) +2033(newsigs.dsr_down != oldsigs.dsr_down ? MgslEvent_DsrInactive:0) +2034(newsigs.dcd_up != oldsigs.dcd_up ? MgslEvent_DcdActive:0) +2035(newsigs.dcd_down != oldsigs.dcd_down ? MgslEvent_DcdInactive:0) +2036(newsigs.cts_up != oldsigs.cts_up ? MgslEvent_CtsActive:0) +2037(newsigs.cts_down != oldsigs.cts_down ? MgslEvent_CtsInactive:0) +2038(newsigs.ri_up != oldsigs.ri_up ? MgslEvent_RiActive:0) +2039(newsigs.ri_down != oldsigs.ri_down ? MgslEvent_RiInactive:0) +2040(cnow.exithunt != cprev.exithunt ? MgslEvent_ExitHuntMode:0) +2041(cnow.rxidle != cprev.rxidle ? MgslEvent_IdleReceived:0) );2042if (events)2043break;20442045cprev = cnow;2046oldsigs = newsigs;2047}20482049remove_wait_queue(&info->event_wait_q, &wait);2050set_current_state(TASK_RUNNING);20512052if (mask & MgslEvent_ExitHuntMode) {2053spin_lock_irqsave(&info->lock,flags);2054if (!waitqueue_active(&info->event_wait_q))2055irq_disable(info, CHA, IRQ_EXITHUNT);2056spin_unlock_irqrestore(&info->lock,flags);2057}2058exit:2059if (rc == 0)2060PUT_USER(rc, events, mask_ptr);2061return rc;2062}20632064static int modem_input_wait(MGSLPC_INFO *info,int arg)2065{2066unsigned long flags;2067int rc;2068struct mgsl_icount cprev, cnow;2069DECLARE_WAITQUEUE(wait, current);20702071/* save current irq counts */2072spin_lock_irqsave(&info->lock,flags);2073cprev = info->icount;2074add_wait_queue(&info->status_event_wait_q, &wait);2075set_current_state(TASK_INTERRUPTIBLE);2076spin_unlock_irqrestore(&info->lock,flags);20772078for(;;) {2079schedule();2080if (signal_pending(current)) {2081rc = -ERESTARTSYS;2082break;2083}20842085/* get new irq counts */2086spin_lock_irqsave(&info->lock,flags);2087cnow = info->icount;2088set_current_state(TASK_INTERRUPTIBLE);2089spin_unlock_irqrestore(&info->lock,flags);20902091/* if no change, wait aborted for some reason */2092if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&2093cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {2094rc = -EIO;2095break;2096}20972098/* check for change in caller specified modem input */2099if ((arg & TIOCM_RNG && cnow.rng != cprev.rng) ||2100(arg & TIOCM_DSR && cnow.dsr != cprev.dsr) ||2101(arg & TIOCM_CD && cnow.dcd != cprev.dcd) ||2102(arg & TIOCM_CTS && cnow.cts != cprev.cts)) {2103rc = 0;2104break;2105}21062107cprev = cnow;2108}2109remove_wait_queue(&info->status_event_wait_q, &wait);2110set_current_state(TASK_RUNNING);2111return rc;2112}21132114/* return the state of the serial control and status signals2115*/2116static int tiocmget(struct tty_struct *tty)2117{2118MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;2119unsigned int result;2120unsigned long flags;21212122spin_lock_irqsave(&info->lock,flags);2123get_signals(info);2124spin_unlock_irqrestore(&info->lock,flags);21252126result = ((info->serial_signals & SerialSignal_RTS) ? TIOCM_RTS:0) +2127((info->serial_signals & SerialSignal_DTR) ? TIOCM_DTR:0) +2128((info->serial_signals & SerialSignal_DCD) ? TIOCM_CAR:0) +2129((info->serial_signals & SerialSignal_RI) ? TIOCM_RNG:0) +2130((info->serial_signals & SerialSignal_DSR) ? TIOCM_DSR:0) +2131((info->serial_signals & SerialSignal_CTS) ? TIOCM_CTS:0);21322133if (debug_level >= DEBUG_LEVEL_INFO)2134printk("%s(%d):%s tiocmget() value=%08X\n",2135__FILE__,__LINE__, info->device_name, result );2136return result;2137}21382139/* set modem control signals (DTR/RTS)2140*/2141static int tiocmset(struct tty_struct *tty,2142unsigned int set, unsigned int clear)2143{2144MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;2145unsigned long flags;21462147if (debug_level >= DEBUG_LEVEL_INFO)2148printk("%s(%d):%s tiocmset(%x,%x)\n",2149__FILE__,__LINE__,info->device_name, set, clear);21502151if (set & TIOCM_RTS)2152info->serial_signals |= SerialSignal_RTS;2153if (set & TIOCM_DTR)2154info->serial_signals |= SerialSignal_DTR;2155if (clear & TIOCM_RTS)2156info->serial_signals &= ~SerialSignal_RTS;2157if (clear & TIOCM_DTR)2158info->serial_signals &= ~SerialSignal_DTR;21592160spin_lock_irqsave(&info->lock,flags);2161set_signals(info);2162spin_unlock_irqrestore(&info->lock,flags);21632164return 0;2165}21662167/* Set or clear transmit break condition2168*2169* Arguments: tty pointer to tty instance data2170* break_state -1=set break condition, 0=clear2171*/2172static int mgslpc_break(struct tty_struct *tty, int break_state)2173{2174MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;2175unsigned long flags;21762177if (debug_level >= DEBUG_LEVEL_INFO)2178printk("%s(%d):mgslpc_break(%s,%d)\n",2179__FILE__,__LINE__, info->device_name, break_state);21802181if (mgslpc_paranoia_check(info, tty->name, "mgslpc_break"))2182return -EINVAL;21832184spin_lock_irqsave(&info->lock,flags);2185if (break_state == -1)2186set_reg_bits(info, CHA+DAFO, BIT6);2187else2188clear_reg_bits(info, CHA+DAFO, BIT6);2189spin_unlock_irqrestore(&info->lock,flags);2190return 0;2191}21922193static int mgslpc_get_icount(struct tty_struct *tty,2194struct serial_icounter_struct *icount)2195{2196MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;2197struct mgsl_icount cnow; /* kernel counter temps */2198unsigned long flags;21992200spin_lock_irqsave(&info->lock,flags);2201cnow = info->icount;2202spin_unlock_irqrestore(&info->lock,flags);22032204icount->cts = cnow.cts;2205icount->dsr = cnow.dsr;2206icount->rng = cnow.rng;2207icount->dcd = cnow.dcd;2208icount->rx = cnow.rx;2209icount->tx = cnow.tx;2210icount->frame = cnow.frame;2211icount->overrun = cnow.overrun;2212icount->parity = cnow.parity;2213icount->brk = cnow.brk;2214icount->buf_overrun = cnow.buf_overrun;22152216return 0;2217}22182219/* Service an IOCTL request2220*2221* Arguments:2222*2223* tty pointer to tty instance data2224* cmd IOCTL command code2225* arg command argument/context2226*2227* Return Value: 0 if success, otherwise error code2228*/2229static int mgslpc_ioctl(struct tty_struct *tty,2230unsigned int cmd, unsigned long arg)2231{2232MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;2233void __user *argp = (void __user *)arg;22342235if (debug_level >= DEBUG_LEVEL_INFO)2236printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__,2237info->device_name, cmd );22382239if (mgslpc_paranoia_check(info, tty->name, "mgslpc_ioctl"))2240return -ENODEV;22412242if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&2243(cmd != TIOCMIWAIT)) {2244if (tty->flags & (1 << TTY_IO_ERROR))2245return -EIO;2246}22472248switch (cmd) {2249case MGSL_IOCGPARAMS:2250return get_params(info, argp);2251case MGSL_IOCSPARAMS:2252return set_params(info, argp, tty);2253case MGSL_IOCGTXIDLE:2254return get_txidle(info, argp);2255case MGSL_IOCSTXIDLE:2256return set_txidle(info, (int)arg);2257case MGSL_IOCGIF:2258return get_interface(info, argp);2259case MGSL_IOCSIF:2260return set_interface(info,(int)arg);2261case MGSL_IOCTXENABLE:2262return set_txenable(info,(int)arg, tty);2263case MGSL_IOCRXENABLE:2264return set_rxenable(info,(int)arg);2265case MGSL_IOCTXABORT:2266return tx_abort(info);2267case MGSL_IOCGSTATS:2268return get_stats(info, argp);2269case MGSL_IOCWAITEVENT:2270return wait_events(info, argp);2271case TIOCMIWAIT:2272return modem_input_wait(info,(int)arg);2273default:2274return -ENOIOCTLCMD;2275}2276return 0;2277}22782279/* Set new termios settings2280*2281* Arguments:2282*2283* tty pointer to tty structure2284* termios pointer to buffer to hold returned old termios2285*/2286static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_termios)2287{2288MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;2289unsigned long flags;22902291if (debug_level >= DEBUG_LEVEL_INFO)2292printk("%s(%d):mgslpc_set_termios %s\n", __FILE__,__LINE__,2293tty->driver->name );22942295/* just return if nothing has changed */2296if ((tty->termios->c_cflag == old_termios->c_cflag)2297&& (RELEVANT_IFLAG(tty->termios->c_iflag)2298== RELEVANT_IFLAG(old_termios->c_iflag)))2299return;23002301mgslpc_change_params(info, tty);23022303/* Handle transition to B0 status */2304if (old_termios->c_cflag & CBAUD &&2305!(tty->termios->c_cflag & CBAUD)) {2306info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);2307spin_lock_irqsave(&info->lock,flags);2308set_signals(info);2309spin_unlock_irqrestore(&info->lock,flags);2310}23112312/* Handle transition away from B0 status */2313if (!(old_termios->c_cflag & CBAUD) &&2314tty->termios->c_cflag & CBAUD) {2315info->serial_signals |= SerialSignal_DTR;2316if (!(tty->termios->c_cflag & CRTSCTS) ||2317!test_bit(TTY_THROTTLED, &tty->flags)) {2318info->serial_signals |= SerialSignal_RTS;2319}2320spin_lock_irqsave(&info->lock,flags);2321set_signals(info);2322spin_unlock_irqrestore(&info->lock,flags);2323}23242325/* Handle turning off CRTSCTS */2326if (old_termios->c_cflag & CRTSCTS &&2327!(tty->termios->c_cflag & CRTSCTS)) {2328tty->hw_stopped = 0;2329tx_release(tty);2330}2331}23322333static void mgslpc_close(struct tty_struct *tty, struct file * filp)2334{2335MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;2336struct tty_port *port = &info->port;23372338if (mgslpc_paranoia_check(info, tty->name, "mgslpc_close"))2339return;23402341if (debug_level >= DEBUG_LEVEL_INFO)2342printk("%s(%d):mgslpc_close(%s) entry, count=%d\n",2343__FILE__,__LINE__, info->device_name, port->count);23442345WARN_ON(!port->count);23462347if (tty_port_close_start(port, tty, filp) == 0)2348goto cleanup;23492350if (port->flags & ASYNC_INITIALIZED)2351mgslpc_wait_until_sent(tty, info->timeout);23522353mgslpc_flush_buffer(tty);23542355tty_ldisc_flush(tty);2356shutdown(info, tty);23572358tty_port_close_end(port, tty);2359tty_port_tty_set(port, NULL);2360cleanup:2361if (debug_level >= DEBUG_LEVEL_INFO)2362printk("%s(%d):mgslpc_close(%s) exit, count=%d\n", __FILE__,__LINE__,2363tty->driver->name, port->count);2364}23652366/* Wait until the transmitter is empty.2367*/2368static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout)2369{2370MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;2371unsigned long orig_jiffies, char_time;23722373if (!info )2374return;23752376if (debug_level >= DEBUG_LEVEL_INFO)2377printk("%s(%d):mgslpc_wait_until_sent(%s) entry\n",2378__FILE__,__LINE__, info->device_name );23792380if (mgslpc_paranoia_check(info, tty->name, "mgslpc_wait_until_sent"))2381return;23822383if (!(info->port.flags & ASYNC_INITIALIZED))2384goto exit;23852386orig_jiffies = jiffies;23872388/* Set check interval to 1/5 of estimated time to2389* send a character, and make it at least 1. The check2390* interval should also be less than the timeout.2391* Note: use tight timings here to satisfy the NIST-PCTS.2392*/23932394if ( info->params.data_rate ) {2395char_time = info->timeout/(32 * 5);2396if (!char_time)2397char_time++;2398} else2399char_time = 1;24002401if (timeout)2402char_time = min_t(unsigned long, char_time, timeout);24032404if (info->params.mode == MGSL_MODE_HDLC) {2405while (info->tx_active) {2406msleep_interruptible(jiffies_to_msecs(char_time));2407if (signal_pending(current))2408break;2409if (timeout && time_after(jiffies, orig_jiffies + timeout))2410break;2411}2412} else {2413while ((info->tx_count || info->tx_active) &&2414info->tx_enabled) {2415msleep_interruptible(jiffies_to_msecs(char_time));2416if (signal_pending(current))2417break;2418if (timeout && time_after(jiffies, orig_jiffies + timeout))2419break;2420}2421}24222423exit:2424if (debug_level >= DEBUG_LEVEL_INFO)2425printk("%s(%d):mgslpc_wait_until_sent(%s) exit\n",2426__FILE__,__LINE__, info->device_name );2427}24282429/* Called by tty_hangup() when a hangup is signaled.2430* This is the same as closing all open files for the port.2431*/2432static void mgslpc_hangup(struct tty_struct *tty)2433{2434MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;24352436if (debug_level >= DEBUG_LEVEL_INFO)2437printk("%s(%d):mgslpc_hangup(%s)\n",2438__FILE__,__LINE__, info->device_name );24392440if (mgslpc_paranoia_check(info, tty->name, "mgslpc_hangup"))2441return;24422443mgslpc_flush_buffer(tty);2444shutdown(info, tty);2445tty_port_hangup(&info->port);2446}24472448static int carrier_raised(struct tty_port *port)2449{2450MGSLPC_INFO *info = container_of(port, MGSLPC_INFO, port);2451unsigned long flags;24522453spin_lock_irqsave(&info->lock,flags);2454get_signals(info);2455spin_unlock_irqrestore(&info->lock,flags);24562457if (info->serial_signals & SerialSignal_DCD)2458return 1;2459return 0;2460}24612462static void dtr_rts(struct tty_port *port, int onoff)2463{2464MGSLPC_INFO *info = container_of(port, MGSLPC_INFO, port);2465unsigned long flags;24662467spin_lock_irqsave(&info->lock,flags);2468if (onoff)2469info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;2470else2471info->serial_signals &= ~SerialSignal_RTS + SerialSignal_DTR;2472set_signals(info);2473spin_unlock_irqrestore(&info->lock,flags);2474}247524762477static int mgslpc_open(struct tty_struct *tty, struct file * filp)2478{2479MGSLPC_INFO *info;2480struct tty_port *port;2481int retval, line;2482unsigned long flags;24832484/* verify range of specified line number */2485line = tty->index;2486if ((line < 0) || (line >= mgslpc_device_count)) {2487printk("%s(%d):mgslpc_open with invalid line #%d.\n",2488__FILE__,__LINE__,line);2489return -ENODEV;2490}24912492/* find the info structure for the specified line */2493info = mgslpc_device_list;2494while(info && info->line != line)2495info = info->next_device;2496if (mgslpc_paranoia_check(info, tty->name, "mgslpc_open"))2497return -ENODEV;24982499port = &info->port;2500tty->driver_data = info;2501tty_port_tty_set(port, tty);25022503if (debug_level >= DEBUG_LEVEL_INFO)2504printk("%s(%d):mgslpc_open(%s), old ref count = %d\n",2505__FILE__,__LINE__,tty->driver->name, port->count);25062507/* If port is closing, signal caller to try again */2508if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING){2509if (port->flags & ASYNC_CLOSING)2510interruptible_sleep_on(&port->close_wait);2511retval = ((port->flags & ASYNC_HUP_NOTIFY) ?2512-EAGAIN : -ERESTARTSYS);2513goto cleanup;2514}25152516tty->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0;25172518spin_lock_irqsave(&info->netlock, flags);2519if (info->netcount) {2520retval = -EBUSY;2521spin_unlock_irqrestore(&info->netlock, flags);2522goto cleanup;2523}2524spin_lock(&port->lock);2525port->count++;2526spin_unlock(&port->lock);2527spin_unlock_irqrestore(&info->netlock, flags);25282529if (port->count == 1) {2530/* 1st open on this device, init hardware */2531retval = startup(info, tty);2532if (retval < 0)2533goto cleanup;2534}25352536retval = tty_port_block_til_ready(&info->port, tty, filp);2537if (retval) {2538if (debug_level >= DEBUG_LEVEL_INFO)2539printk("%s(%d):block_til_ready(%s) returned %d\n",2540__FILE__,__LINE__, info->device_name, retval);2541goto cleanup;2542}25432544if (debug_level >= DEBUG_LEVEL_INFO)2545printk("%s(%d):mgslpc_open(%s) success\n",2546__FILE__,__LINE__, info->device_name);2547retval = 0;25482549cleanup:2550return retval;2551}25522553/*2554* /proc fs routines....2555*/25562557static inline void line_info(struct seq_file *m, MGSLPC_INFO *info)2558{2559char stat_buf[30];2560unsigned long flags;25612562seq_printf(m, "%s:io:%04X irq:%d",2563info->device_name, info->io_base, info->irq_level);25642565/* output current serial signal states */2566spin_lock_irqsave(&info->lock,flags);2567get_signals(info);2568spin_unlock_irqrestore(&info->lock,flags);25692570stat_buf[0] = 0;2571stat_buf[1] = 0;2572if (info->serial_signals & SerialSignal_RTS)2573strcat(stat_buf, "|RTS");2574if (info->serial_signals & SerialSignal_CTS)2575strcat(stat_buf, "|CTS");2576if (info->serial_signals & SerialSignal_DTR)2577strcat(stat_buf, "|DTR");2578if (info->serial_signals & SerialSignal_DSR)2579strcat(stat_buf, "|DSR");2580if (info->serial_signals & SerialSignal_DCD)2581strcat(stat_buf, "|CD");2582if (info->serial_signals & SerialSignal_RI)2583strcat(stat_buf, "|RI");25842585if (info->params.mode == MGSL_MODE_HDLC) {2586seq_printf(m, " HDLC txok:%d rxok:%d",2587info->icount.txok, info->icount.rxok);2588if (info->icount.txunder)2589seq_printf(m, " txunder:%d", info->icount.txunder);2590if (info->icount.txabort)2591seq_printf(m, " txabort:%d", info->icount.txabort);2592if (info->icount.rxshort)2593seq_printf(m, " rxshort:%d", info->icount.rxshort);2594if (info->icount.rxlong)2595seq_printf(m, " rxlong:%d", info->icount.rxlong);2596if (info->icount.rxover)2597seq_printf(m, " rxover:%d", info->icount.rxover);2598if (info->icount.rxcrc)2599seq_printf(m, " rxcrc:%d", info->icount.rxcrc);2600} else {2601seq_printf(m, " ASYNC tx:%d rx:%d",2602info->icount.tx, info->icount.rx);2603if (info->icount.frame)2604seq_printf(m, " fe:%d", info->icount.frame);2605if (info->icount.parity)2606seq_printf(m, " pe:%d", info->icount.parity);2607if (info->icount.brk)2608seq_printf(m, " brk:%d", info->icount.brk);2609if (info->icount.overrun)2610seq_printf(m, " oe:%d", info->icount.overrun);2611}26122613/* Append serial signal status to end */2614seq_printf(m, " %s\n", stat_buf+1);26152616seq_printf(m, "txactive=%d bh_req=%d bh_run=%d pending_bh=%x\n",2617info->tx_active,info->bh_requested,info->bh_running,2618info->pending_bh);2619}26202621/* Called to print information about devices2622*/2623static int mgslpc_proc_show(struct seq_file *m, void *v)2624{2625MGSLPC_INFO *info;26262627seq_printf(m, "synclink driver:%s\n", driver_version);26282629info = mgslpc_device_list;2630while( info ) {2631line_info(m, info);2632info = info->next_device;2633}2634return 0;2635}26362637static int mgslpc_proc_open(struct inode *inode, struct file *file)2638{2639return single_open(file, mgslpc_proc_show, NULL);2640}26412642static const struct file_operations mgslpc_proc_fops = {2643.owner = THIS_MODULE,2644.open = mgslpc_proc_open,2645.read = seq_read,2646.llseek = seq_lseek,2647.release = single_release,2648};26492650static int rx_alloc_buffers(MGSLPC_INFO *info)2651{2652/* each buffer has header and data */2653info->rx_buf_size = sizeof(RXBUF) + info->max_frame_size;26542655/* calculate total allocation size for 8 buffers */2656info->rx_buf_total_size = info->rx_buf_size * 8;26572658/* limit total allocated memory */2659if (info->rx_buf_total_size > 0x10000)2660info->rx_buf_total_size = 0x10000;26612662/* calculate number of buffers */2663info->rx_buf_count = info->rx_buf_total_size / info->rx_buf_size;26642665info->rx_buf = kmalloc(info->rx_buf_total_size, GFP_KERNEL);2666if (info->rx_buf == NULL)2667return -ENOMEM;26682669rx_reset_buffers(info);2670return 0;2671}26722673static void rx_free_buffers(MGSLPC_INFO *info)2674{2675kfree(info->rx_buf);2676info->rx_buf = NULL;2677}26782679static int claim_resources(MGSLPC_INFO *info)2680{2681if (rx_alloc_buffers(info) < 0 ) {2682printk( "Can't allocate rx buffer %s\n", info->device_name);2683release_resources(info);2684return -ENODEV;2685}2686return 0;2687}26882689static void release_resources(MGSLPC_INFO *info)2690{2691if (debug_level >= DEBUG_LEVEL_INFO)2692printk("release_resources(%s)\n", info->device_name);2693rx_free_buffers(info);2694}26952696/* Add the specified device instance data structure to the2697* global linked list of devices and increment the device count.2698*2699* Arguments: info pointer to device instance data2700*/2701static void mgslpc_add_device(MGSLPC_INFO *info)2702{2703info->next_device = NULL;2704info->line = mgslpc_device_count;2705sprintf(info->device_name,"ttySLP%d",info->line);27062707if (info->line < MAX_DEVICE_COUNT) {2708if (maxframe[info->line])2709info->max_frame_size = maxframe[info->line];2710}27112712mgslpc_device_count++;27132714if (!mgslpc_device_list)2715mgslpc_device_list = info;2716else {2717MGSLPC_INFO *current_dev = mgslpc_device_list;2718while( current_dev->next_device )2719current_dev = current_dev->next_device;2720current_dev->next_device = info;2721}27222723if (info->max_frame_size < 4096)2724info->max_frame_size = 4096;2725else if (info->max_frame_size > 65535)2726info->max_frame_size = 65535;27272728printk( "SyncLink PC Card %s:IO=%04X IRQ=%d\n",2729info->device_name, info->io_base, info->irq_level);27302731#if SYNCLINK_GENERIC_HDLC2732hdlcdev_init(info);2733#endif2734}27352736static void mgslpc_remove_device(MGSLPC_INFO *remove_info)2737{2738MGSLPC_INFO *info = mgslpc_device_list;2739MGSLPC_INFO *last = NULL;27402741while(info) {2742if (info == remove_info) {2743if (last)2744last->next_device = info->next_device;2745else2746mgslpc_device_list = info->next_device;2747#if SYNCLINK_GENERIC_HDLC2748hdlcdev_exit(info);2749#endif2750release_resources(info);2751kfree(info);2752mgslpc_device_count--;2753return;2754}2755last = info;2756info = info->next_device;2757}2758}27592760static const struct pcmcia_device_id mgslpc_ids[] = {2761PCMCIA_DEVICE_MANF_CARD(0x02c5, 0x0050),2762PCMCIA_DEVICE_NULL2763};2764MODULE_DEVICE_TABLE(pcmcia, mgslpc_ids);27652766static struct pcmcia_driver mgslpc_driver = {2767.owner = THIS_MODULE,2768.name = "synclink_cs",2769.probe = mgslpc_probe,2770.remove = mgslpc_detach,2771.id_table = mgslpc_ids,2772.suspend = mgslpc_suspend,2773.resume = mgslpc_resume,2774};27752776static const struct tty_operations mgslpc_ops = {2777.open = mgslpc_open,2778.close = mgslpc_close,2779.write = mgslpc_write,2780.put_char = mgslpc_put_char,2781.flush_chars = mgslpc_flush_chars,2782.write_room = mgslpc_write_room,2783.chars_in_buffer = mgslpc_chars_in_buffer,2784.flush_buffer = mgslpc_flush_buffer,2785.ioctl = mgslpc_ioctl,2786.throttle = mgslpc_throttle,2787.unthrottle = mgslpc_unthrottle,2788.send_xchar = mgslpc_send_xchar,2789.break_ctl = mgslpc_break,2790.wait_until_sent = mgslpc_wait_until_sent,2791.set_termios = mgslpc_set_termios,2792.stop = tx_pause,2793.start = tx_release,2794.hangup = mgslpc_hangup,2795.tiocmget = tiocmget,2796.tiocmset = tiocmset,2797.get_icount = mgslpc_get_icount,2798.proc_fops = &mgslpc_proc_fops,2799};28002801static void synclink_cs_cleanup(void)2802{2803int rc;28042805while(mgslpc_device_list)2806mgslpc_remove_device(mgslpc_device_list);28072808if (serial_driver) {2809if ((rc = tty_unregister_driver(serial_driver)))2810printk("%s(%d) failed to unregister tty driver err=%d\n",2811__FILE__,__LINE__,rc);2812put_tty_driver(serial_driver);2813}28142815pcmcia_unregister_driver(&mgslpc_driver);2816}28172818static int __init synclink_cs_init(void)2819{2820int rc;28212822if (break_on_load) {2823mgslpc_get_text_ptr();2824BREAKPOINT();2825}28262827if ((rc = pcmcia_register_driver(&mgslpc_driver)) < 0)2828return rc;28292830serial_driver = alloc_tty_driver(MAX_DEVICE_COUNT);2831if (!serial_driver) {2832rc = -ENOMEM;2833goto error;2834}28352836/* Initialize the tty_driver structure */28372838serial_driver->owner = THIS_MODULE;2839serial_driver->driver_name = "synclink_cs";2840serial_driver->name = "ttySLP";2841serial_driver->major = ttymajor;2842serial_driver->minor_start = 64;2843serial_driver->type = TTY_DRIVER_TYPE_SERIAL;2844serial_driver->subtype = SERIAL_TYPE_NORMAL;2845serial_driver->init_termios = tty_std_termios;2846serial_driver->init_termios.c_cflag =2847B9600 | CS8 | CREAD | HUPCL | CLOCAL;2848serial_driver->flags = TTY_DRIVER_REAL_RAW;2849tty_set_operations(serial_driver, &mgslpc_ops);28502851if ((rc = tty_register_driver(serial_driver)) < 0) {2852printk("%s(%d):Couldn't register serial driver\n",2853__FILE__,__LINE__);2854put_tty_driver(serial_driver);2855serial_driver = NULL;2856goto error;2857}28582859printk("%s %s, tty major#%d\n",2860driver_name, driver_version,2861serial_driver->major);28622863return 0;28642865error:2866synclink_cs_cleanup();2867return rc;2868}28692870static void __exit synclink_cs_exit(void)2871{2872synclink_cs_cleanup();2873}28742875module_init(synclink_cs_init);2876module_exit(synclink_cs_exit);28772878static void mgslpc_set_rate(MGSLPC_INFO *info, unsigned char channel, unsigned int rate)2879{2880unsigned int M, N;2881unsigned char val;28822883/* note:standard BRG mode is broken in V3.2 chip2884* so enhanced mode is always used2885*/28862887if (rate) {2888N = 3686400 / rate;2889if (!N)2890N = 1;2891N >>= 1;2892for (M = 1; N > 64 && M < 16; M++)2893N >>= 1;2894N--;28952896/* BGR[5..0] = N2897* BGR[9..6] = M2898* BGR[7..0] contained in BGR register2899* BGR[9..8] contained in CCR2[7..6]2900* divisor = (N+1)*2^M2901*2902* Note: M *must* not be zero (causes asymetric duty cycle)2903*/2904write_reg(info, (unsigned char) (channel + BGR),2905(unsigned char) ((M << 6) + N));2906val = read_reg(info, (unsigned char) (channel + CCR2)) & 0x3f;2907val |= ((M << 4) & 0xc0);2908write_reg(info, (unsigned char) (channel + CCR2), val);2909}2910}29112912/* Enabled the AUX clock output at the specified frequency.2913*/2914static void enable_auxclk(MGSLPC_INFO *info)2915{2916unsigned char val;29172918/* MODE2919*2920* 07..06 MDS[1..0] 10 = transparent HDLC mode2921* 05 ADM Address Mode, 0 = no addr recognition2922* 04 TMD Timer Mode, 0 = external2923* 03 RAC Receiver Active, 0 = inactive2924* 02 RTS 0=RTS active during xmit, 1=RTS always active2925* 01 TRS Timer Resolution, 1=5122926* 00 TLP Test Loop, 0 = no loop2927*2928* 1000 00102929*/2930val = 0x82;29312932/* channel B RTS is used to enable AUXCLK driver on SP505 */2933if (info->params.mode == MGSL_MODE_HDLC && info->params.clock_speed)2934val |= BIT2;2935write_reg(info, CHB + MODE, val);29362937/* CCR02938*2939* 07 PU Power Up, 1=active, 0=power down2940* 06 MCE Master Clock Enable, 1=enabled2941* 05 Reserved, 02942* 04..02 SC[2..0] Encoding2943* 01..00 SM[1..0] Serial Mode, 00=HDLC2944*2945* 110000002946*/2947write_reg(info, CHB + CCR0, 0xc0);29482949/* CCR12950*2951* 07 SFLG Shared Flag, 0 = disable shared flags2952* 06 GALP Go Active On Loop, 0 = not used2953* 05 GLP Go On Loop, 0 = not used2954* 04 ODS Output Driver Select, 1=TxD is push-pull output2955* 03 ITF Interframe Time Fill, 0=mark, 1=flag2956* 02..00 CM[2..0] Clock Mode2957*2958* 0001 01112959*/2960write_reg(info, CHB + CCR1, 0x17);29612962/* CCR2 (Channel B)2963*2964* 07..06 BGR[9..8] Baud rate bits 9..82965* 05 BDF Baud rate divisor factor, 0=1, 1=BGR value2966* 04 SSEL Clock source select, 1=submode b2967* 03 TOE 0=TxCLK is input, 1=TxCLK is output2968* 02 RWX Read/Write Exchange 0=disabled2969* 01 C32, CRC select, 0=CRC-16, 1=CRC-322970* 00 DIV, data inversion 0=disabled, 1=enabled2971*2972* 0011 10002973*/2974if (info->params.mode == MGSL_MODE_HDLC && info->params.clock_speed)2975write_reg(info, CHB + CCR2, 0x38);2976else2977write_reg(info, CHB + CCR2, 0x30);29782979/* CCR42980*2981* 07 MCK4 Master Clock Divide by 4, 1=enabled2982* 06 EBRG Enhanced Baud Rate Generator Mode, 1=enabled2983* 05 TST1 Test Pin, 0=normal operation2984* 04 ICD Ivert Carrier Detect, 1=enabled (active low)2985* 03..02 Reserved, must be 02986* 01..00 RFT[1..0] RxFIFO Threshold 00=32 bytes2987*2988* 0101 00002989*/2990write_reg(info, CHB + CCR4, 0x50);29912992/* if auxclk not enabled, set internal BRG so2993* CTS transitions can be detected (requires TxC)2994*/2995if (info->params.mode == MGSL_MODE_HDLC && info->params.clock_speed)2996mgslpc_set_rate(info, CHB, info->params.clock_speed);2997else2998mgslpc_set_rate(info, CHB, 921600);2999}30003001static void loopback_enable(MGSLPC_INFO *info)3002{3003unsigned char val;30043005/* CCR1:02..00 CM[2..0] Clock Mode = 111 (clock mode 7) */3006val = read_reg(info, CHA + CCR1) | (BIT2 + BIT1 + BIT0);3007write_reg(info, CHA + CCR1, val);30083009/* CCR2:04 SSEL Clock source select, 1=submode b */3010val = read_reg(info, CHA + CCR2) | (BIT4 + BIT5);3011write_reg(info, CHA + CCR2, val);30123013/* set LinkSpeed if available, otherwise default to 2Mbps */3014if (info->params.clock_speed)3015mgslpc_set_rate(info, CHA, info->params.clock_speed);3016else3017mgslpc_set_rate(info, CHA, 1843200);30183019/* MODE:00 TLP Test Loop, 1=loopback enabled */3020val = read_reg(info, CHA + MODE) | BIT0;3021write_reg(info, CHA + MODE, val);3022}30233024static void hdlc_mode(MGSLPC_INFO *info)3025{3026unsigned char val;3027unsigned char clkmode, clksubmode;30283029/* disable all interrupts */3030irq_disable(info, CHA, 0xffff);3031irq_disable(info, CHB, 0xffff);3032port_irq_disable(info, 0xff);30333034/* assume clock mode 0a, rcv=RxC xmt=TxC */3035clkmode = clksubmode = 0;3036if (info->params.flags & HDLC_FLAG_RXC_DPLL3037&& info->params.flags & HDLC_FLAG_TXC_DPLL) {3038/* clock mode 7a, rcv = DPLL, xmt = DPLL */3039clkmode = 7;3040} else if (info->params.flags & HDLC_FLAG_RXC_BRG3041&& info->params.flags & HDLC_FLAG_TXC_BRG) {3042/* clock mode 7b, rcv = BRG, xmt = BRG */3043clkmode = 7;3044clksubmode = 1;3045} else if (info->params.flags & HDLC_FLAG_RXC_DPLL) {3046if (info->params.flags & HDLC_FLAG_TXC_BRG) {3047/* clock mode 6b, rcv = DPLL, xmt = BRG/16 */3048clkmode = 6;3049clksubmode = 1;3050} else {3051/* clock mode 6a, rcv = DPLL, xmt = TxC */3052clkmode = 6;3053}3054} else if (info->params.flags & HDLC_FLAG_TXC_BRG) {3055/* clock mode 0b, rcv = RxC, xmt = BRG */3056clksubmode = 1;3057}30583059/* MODE3060*3061* 07..06 MDS[1..0] 10 = transparent HDLC mode3062* 05 ADM Address Mode, 0 = no addr recognition3063* 04 TMD Timer Mode, 0 = external3064* 03 RAC Receiver Active, 0 = inactive3065* 02 RTS 0=RTS active during xmit, 1=RTS always active3066* 01 TRS Timer Resolution, 1=5123067* 00 TLP Test Loop, 0 = no loop3068*3069* 1000 00103070*/3071val = 0x82;3072if (info->params.loopback)3073val |= BIT0;30743075/* preserve RTS state */3076if (info->serial_signals & SerialSignal_RTS)3077val |= BIT2;3078write_reg(info, CHA + MODE, val);30793080/* CCR03081*3082* 07 PU Power Up, 1=active, 0=power down3083* 06 MCE Master Clock Enable, 1=enabled3084* 05 Reserved, 03085* 04..02 SC[2..0] Encoding3086* 01..00 SM[1..0] Serial Mode, 00=HDLC3087*3088* 110000003089*/3090val = 0xc0;3091switch (info->params.encoding)3092{3093case HDLC_ENCODING_NRZI:3094val |= BIT3;3095break;3096case HDLC_ENCODING_BIPHASE_SPACE:3097val |= BIT4;3098break; // FM03099case HDLC_ENCODING_BIPHASE_MARK:3100val |= BIT4 + BIT2;3101break; // FM13102case HDLC_ENCODING_BIPHASE_LEVEL:3103val |= BIT4 + BIT3;3104break; // Manchester3105}3106write_reg(info, CHA + CCR0, val);31073108/* CCR13109*3110* 07 SFLG Shared Flag, 0 = disable shared flags3111* 06 GALP Go Active On Loop, 0 = not used3112* 05 GLP Go On Loop, 0 = not used3113* 04 ODS Output Driver Select, 1=TxD is push-pull output3114* 03 ITF Interframe Time Fill, 0=mark, 1=flag3115* 02..00 CM[2..0] Clock Mode3116*3117* 0001 00003118*/3119val = 0x10 + clkmode;3120write_reg(info, CHA + CCR1, val);31213122/* CCR23123*3124* 07..06 BGR[9..8] Baud rate bits 9..83125* 05 BDF Baud rate divisor factor, 0=1, 1=BGR value3126* 04 SSEL Clock source select, 1=submode b3127* 03 TOE 0=TxCLK is input, 0=TxCLK is input3128* 02 RWX Read/Write Exchange 0=disabled3129* 01 C32, CRC select, 0=CRC-16, 1=CRC-323130* 00 DIV, data inversion 0=disabled, 1=enabled3131*3132* 0000 00003133*/3134val = 0x00;3135if (clkmode == 2 || clkmode == 3 || clkmode == 63136|| clkmode == 7 || (clkmode == 0 && clksubmode == 1))3137val |= BIT5;3138if (clksubmode)3139val |= BIT4;3140if (info->params.crc_type == HDLC_CRC_32_CCITT)3141val |= BIT1;3142if (info->params.encoding == HDLC_ENCODING_NRZB)3143val |= BIT0;3144write_reg(info, CHA + CCR2, val);31453146/* CCR33147*3148* 07..06 PRE[1..0] Preamble count 00=1, 01=2, 10=4, 11=83149* 05 EPT Enable preamble transmission, 1=enabled3150* 04 RADD Receive address pushed to FIFO, 0=disabled3151* 03 CRL CRC Reset Level, 0=FFFF3152* 02 RCRC Rx CRC 0=On 1=Off3153* 01 TCRC Tx CRC 0=On 1=Off3154* 00 PSD DPLL Phase Shift Disable3155*3156* 0000 00003157*/3158val = 0x00;3159if (info->params.crc_type == HDLC_CRC_NONE)3160val |= BIT2 + BIT1;3161if (info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE)3162val |= BIT5;3163switch (info->params.preamble_length)3164{3165case HDLC_PREAMBLE_LENGTH_16BITS:3166val |= BIT6;3167break;3168case HDLC_PREAMBLE_LENGTH_32BITS:3169val |= BIT6;3170break;3171case HDLC_PREAMBLE_LENGTH_64BITS:3172val |= BIT7 + BIT6;3173break;3174}3175write_reg(info, CHA + CCR3, val);31763177/* PRE - Preamble pattern */3178val = 0;3179switch (info->params.preamble)3180{3181case HDLC_PREAMBLE_PATTERN_FLAGS: val = 0x7e; break;3182case HDLC_PREAMBLE_PATTERN_10: val = 0xaa; break;3183case HDLC_PREAMBLE_PATTERN_01: val = 0x55; break;3184case HDLC_PREAMBLE_PATTERN_ONES: val = 0xff; break;3185}3186write_reg(info, CHA + PRE, val);31873188/* CCR43189*3190* 07 MCK4 Master Clock Divide by 4, 1=enabled3191* 06 EBRG Enhanced Baud Rate Generator Mode, 1=enabled3192* 05 TST1 Test Pin, 0=normal operation3193* 04 ICD Ivert Carrier Detect, 1=enabled (active low)3194* 03..02 Reserved, must be 03195* 01..00 RFT[1..0] RxFIFO Threshold 00=32 bytes3196*3197* 0101 00003198*/3199val = 0x50;3200write_reg(info, CHA + CCR4, val);3201if (info->params.flags & HDLC_FLAG_RXC_DPLL)3202mgslpc_set_rate(info, CHA, info->params.clock_speed * 16);3203else3204mgslpc_set_rate(info, CHA, info->params.clock_speed);32053206/* RLCR Receive length check register3207*3208* 7 1=enable receive length check3209* 6..0 Max frame length = (RL + 1) * 323210*/3211write_reg(info, CHA + RLCR, 0);32123213/* XBCH Transmit Byte Count High3214*3215* 07 DMA mode, 0 = interrupt driven3216* 06 NRM, 0=ABM (ignored)3217* 05 CAS Carrier Auto Start3218* 04 XC Transmit Continuously (ignored)3219* 03..00 XBC[10..8] Transmit byte count bits 10..83220*3221* 0000 00003222*/3223val = 0x00;3224if (info->params.flags & HDLC_FLAG_AUTO_DCD)3225val |= BIT5;3226write_reg(info, CHA + XBCH, val);3227enable_auxclk(info);3228if (info->params.loopback || info->testing_irq)3229loopback_enable(info);3230if (info->params.flags & HDLC_FLAG_AUTO_CTS)3231{3232irq_enable(info, CHB, IRQ_CTS);3233/* PVR[3] 1=AUTO CTS active */3234set_reg_bits(info, CHA + PVR, BIT3);3235} else3236clear_reg_bits(info, CHA + PVR, BIT3);32373238irq_enable(info, CHA,3239IRQ_RXEOM + IRQ_RXFIFO + IRQ_ALLSENT +3240IRQ_UNDERRUN + IRQ_TXFIFO);3241issue_command(info, CHA, CMD_TXRESET + CMD_RXRESET);3242wait_command_complete(info, CHA);3243read_reg16(info, CHA + ISR); /* clear pending IRQs */32443245/* Master clock mode enabled above to allow reset commands3246* to complete even if no data clocks are present.3247*3248* Disable master clock mode for normal communications because3249* V3.2 of the ESCC2 has a bug that prevents the transmit all sent3250* IRQ when in master clock mode.3251*3252* Leave master clock mode enabled for IRQ test because the3253* timer IRQ used by the test can only happen in master clock mode.3254*/3255if (!info->testing_irq)3256clear_reg_bits(info, CHA + CCR0, BIT6);32573258tx_set_idle(info);32593260tx_stop(info);3261rx_stop(info);3262}32633264static void rx_stop(MGSLPC_INFO *info)3265{3266if (debug_level >= DEBUG_LEVEL_ISR)3267printk("%s(%d):rx_stop(%s)\n",3268__FILE__,__LINE__, info->device_name );32693270/* MODE:03 RAC Receiver Active, 0=inactive */3271clear_reg_bits(info, CHA + MODE, BIT3);32723273info->rx_enabled = false;3274info->rx_overflow = false;3275}32763277static void rx_start(MGSLPC_INFO *info)3278{3279if (debug_level >= DEBUG_LEVEL_ISR)3280printk("%s(%d):rx_start(%s)\n",3281__FILE__,__LINE__, info->device_name );32823283rx_reset_buffers(info);3284info->rx_enabled = false;3285info->rx_overflow = false;32863287/* MODE:03 RAC Receiver Active, 1=active */3288set_reg_bits(info, CHA + MODE, BIT3);32893290info->rx_enabled = true;3291}32923293static void tx_start(MGSLPC_INFO *info, struct tty_struct *tty)3294{3295if (debug_level >= DEBUG_LEVEL_ISR)3296printk("%s(%d):tx_start(%s)\n",3297__FILE__,__LINE__, info->device_name );32983299if (info->tx_count) {3300/* If auto RTS enabled and RTS is inactive, then assert */3301/* RTS and set a flag indicating that the driver should */3302/* negate RTS when the transmission completes. */3303info->drop_rts_on_tx_done = false;33043305if (info->params.flags & HDLC_FLAG_AUTO_RTS) {3306get_signals(info);3307if (!(info->serial_signals & SerialSignal_RTS)) {3308info->serial_signals |= SerialSignal_RTS;3309set_signals(info);3310info->drop_rts_on_tx_done = true;3311}3312}33133314if (info->params.mode == MGSL_MODE_ASYNC) {3315if (!info->tx_active) {3316info->tx_active = true;3317tx_ready(info, tty);3318}3319} else {3320info->tx_active = true;3321tx_ready(info, tty);3322mod_timer(&info->tx_timer, jiffies +3323msecs_to_jiffies(5000));3324}3325}33263327if (!info->tx_enabled)3328info->tx_enabled = true;3329}33303331static void tx_stop(MGSLPC_INFO *info)3332{3333if (debug_level >= DEBUG_LEVEL_ISR)3334printk("%s(%d):tx_stop(%s)\n",3335__FILE__,__LINE__, info->device_name );33363337del_timer(&info->tx_timer);33383339info->tx_enabled = false;3340info->tx_active = false;3341}33423343/* Reset the adapter to a known state and prepare it for further use.3344*/3345static void reset_device(MGSLPC_INFO *info)3346{3347/* power up both channels (set BIT7) */3348write_reg(info, CHA + CCR0, 0x80);3349write_reg(info, CHB + CCR0, 0x80);3350write_reg(info, CHA + MODE, 0);3351write_reg(info, CHB + MODE, 0);33523353/* disable all interrupts */3354irq_disable(info, CHA, 0xffff);3355irq_disable(info, CHB, 0xffff);3356port_irq_disable(info, 0xff);33573358/* PCR Port Configuration Register3359*3360* 07..04 DEC[3..0] Serial I/F select outputs3361* 03 output, 1=AUTO CTS control enabled3362* 02 RI Ring Indicator input 0=active3363* 01 DSR input 0=active3364* 00 DTR output 0=active3365*3366* 0000 01103367*/3368write_reg(info, PCR, 0x06);33693370/* PVR Port Value Register3371*3372* 07..04 DEC[3..0] Serial I/F select (0000=disabled)3373* 03 AUTO CTS output 1=enabled3374* 02 RI Ring Indicator input3375* 01 DSR input3376* 00 DTR output (1=inactive)3377*3378* 0000 00013379*/3380// write_reg(info, PVR, PVR_DTR);33813382/* IPC Interrupt Port Configuration3383*3384* 07 VIS 1=Masked interrupts visible3385* 06..05 Reserved, 03386* 04..03 SLA Slave address, 00 ignored3387* 02 CASM Cascading Mode, 1=daisy chain3388* 01..00 IC[1..0] Interrupt Config, 01=push-pull output, active low3389*3390* 0000 01013391*/3392write_reg(info, IPC, 0x05);3393}33943395static void async_mode(MGSLPC_INFO *info)3396{3397unsigned char val;33983399/* disable all interrupts */3400irq_disable(info, CHA, 0xffff);3401irq_disable(info, CHB, 0xffff);3402port_irq_disable(info, 0xff);34033404/* MODE3405*3406* 07 Reserved, 03407* 06 FRTS RTS State, 0=active3408* 05 FCTS Flow Control on CTS3409* 04 FLON Flow Control Enable3410* 03 RAC Receiver Active, 0 = inactive3411* 02 RTS 0=Auto RTS, 1=manual RTS3412* 01 TRS Timer Resolution, 1=5123413* 00 TLP Test Loop, 0 = no loop3414*3415* 0000 01103416*/3417val = 0x06;3418if (info->params.loopback)3419val |= BIT0;34203421/* preserve RTS state */3422if (!(info->serial_signals & SerialSignal_RTS))3423val |= BIT6;3424write_reg(info, CHA + MODE, val);34253426/* CCR03427*3428* 07 PU Power Up, 1=active, 0=power down3429* 06 MCE Master Clock Enable, 1=enabled3430* 05 Reserved, 03431* 04..02 SC[2..0] Encoding, 000=NRZ3432* 01..00 SM[1..0] Serial Mode, 11=Async3433*3434* 1000 00113435*/3436write_reg(info, CHA + CCR0, 0x83);34373438/* CCR13439*3440* 07..05 Reserved, 03441* 04 ODS Output Driver Select, 1=TxD is push-pull output3442* 03 BCR Bit Clock Rate, 1=16x3443* 02..00 CM[2..0] Clock Mode, 111=BRG3444*3445* 0001 11113446*/3447write_reg(info, CHA + CCR1, 0x1f);34483449/* CCR2 (channel A)3450*3451* 07..06 BGR[9..8] Baud rate bits 9..83452* 05 BDF Baud rate divisor factor, 0=1, 1=BGR value3453* 04 SSEL Clock source select, 1=submode b3454* 03 TOE 0=TxCLK is input, 0=TxCLK is input3455* 02 RWX Read/Write Exchange 0=disabled3456* 01 Reserved, 03457* 00 DIV, data inversion 0=disabled, 1=enabled3458*3459* 0001 00003460*/3461write_reg(info, CHA + CCR2, 0x10);34623463/* CCR33464*3465* 07..01 Reserved, 03466* 00 PSD DPLL Phase Shift Disable3467*3468* 0000 00003469*/3470write_reg(info, CHA + CCR3, 0);34713472/* CCR43473*3474* 07 MCK4 Master Clock Divide by 4, 1=enabled3475* 06 EBRG Enhanced Baud Rate Generator Mode, 1=enabled3476* 05 TST1 Test Pin, 0=normal operation3477* 04 ICD Ivert Carrier Detect, 1=enabled (active low)3478* 03..00 Reserved, must be 03479*3480* 0101 00003481*/3482write_reg(info, CHA + CCR4, 0x50);3483mgslpc_set_rate(info, CHA, info->params.data_rate * 16);34843485/* DAFO Data Format3486*3487* 07 Reserved, 03488* 06 XBRK transmit break, 0=normal operation3489* 05 Stop bits (0=1, 1=2)3490* 04..03 PAR[1..0] Parity (01=odd, 10=even)3491* 02 PAREN Parity Enable3492* 01..00 CHL[1..0] Character Length (00=8, 01=7)3493*3494*/3495val = 0x00;3496if (info->params.data_bits != 8)3497val |= BIT0; /* 7 bits */3498if (info->params.stop_bits != 1)3499val |= BIT5;3500if (info->params.parity != ASYNC_PARITY_NONE)3501{3502val |= BIT2; /* Parity enable */3503if (info->params.parity == ASYNC_PARITY_ODD)3504val |= BIT3;3505else3506val |= BIT4;3507}3508write_reg(info, CHA + DAFO, val);35093510/* RFC Rx FIFO Control3511*3512* 07 Reserved, 03513* 06 DPS, 1=parity bit not stored in data byte3514* 05 DXS, 0=all data stored in FIFO (including XON/XOFF)3515* 04 RFDF Rx FIFO Data Format, 1=status byte stored in FIFO3516* 03..02 RFTH[1..0], rx threshold, 11=16 status + 16 data byte3517* 01 Reserved, 03518* 00 TCDE Terminate Char Detect Enable, 0=disabled3519*3520* 0101 11003521*/3522write_reg(info, CHA + RFC, 0x5c);35233524/* RLCR Receive length check register3525*3526* Max frame length = (RL + 1) * 323527*/3528write_reg(info, CHA + RLCR, 0);35293530/* XBCH Transmit Byte Count High3531*3532* 07 DMA mode, 0 = interrupt driven3533* 06 NRM, 0=ABM (ignored)3534* 05 CAS Carrier Auto Start3535* 04 XC Transmit Continuously (ignored)3536* 03..00 XBC[10..8] Transmit byte count bits 10..83537*3538* 0000 00003539*/3540val = 0x00;3541if (info->params.flags & HDLC_FLAG_AUTO_DCD)3542val |= BIT5;3543write_reg(info, CHA + XBCH, val);3544if (info->params.flags & HDLC_FLAG_AUTO_CTS)3545irq_enable(info, CHA, IRQ_CTS);35463547/* MODE:03 RAC Receiver Active, 1=active */3548set_reg_bits(info, CHA + MODE, BIT3);3549enable_auxclk(info);3550if (info->params.flags & HDLC_FLAG_AUTO_CTS) {3551irq_enable(info, CHB, IRQ_CTS);3552/* PVR[3] 1=AUTO CTS active */3553set_reg_bits(info, CHA + PVR, BIT3);3554} else3555clear_reg_bits(info, CHA + PVR, BIT3);3556irq_enable(info, CHA,3557IRQ_RXEOM + IRQ_RXFIFO + IRQ_BREAK_ON + IRQ_RXTIME +3558IRQ_ALLSENT + IRQ_TXFIFO);3559issue_command(info, CHA, CMD_TXRESET + CMD_RXRESET);3560wait_command_complete(info, CHA);3561read_reg16(info, CHA + ISR); /* clear pending IRQs */3562}35633564/* Set the HDLC idle mode for the transmitter.3565*/3566static void tx_set_idle(MGSLPC_INFO *info)3567{3568/* Note: ESCC2 only supports flags and one idle modes */3569if (info->idle_mode == HDLC_TXIDLE_FLAGS)3570set_reg_bits(info, CHA + CCR1, BIT3);3571else3572clear_reg_bits(info, CHA + CCR1, BIT3);3573}35743575/* get state of the V24 status (input) signals.3576*/3577static void get_signals(MGSLPC_INFO *info)3578{3579unsigned char status = 0;35803581/* preserve DTR and RTS */3582info->serial_signals &= SerialSignal_DTR + SerialSignal_RTS;35833584if (read_reg(info, CHB + VSTR) & BIT7)3585info->serial_signals |= SerialSignal_DCD;3586if (read_reg(info, CHB + STAR) & BIT1)3587info->serial_signals |= SerialSignal_CTS;35883589status = read_reg(info, CHA + PVR);3590if (!(status & PVR_RI))3591info->serial_signals |= SerialSignal_RI;3592if (!(status & PVR_DSR))3593info->serial_signals |= SerialSignal_DSR;3594}35953596/* Set the state of DTR and RTS based on contents of3597* serial_signals member of device extension.3598*/3599static void set_signals(MGSLPC_INFO *info)3600{3601unsigned char val;36023603val = read_reg(info, CHA + MODE);3604if (info->params.mode == MGSL_MODE_ASYNC) {3605if (info->serial_signals & SerialSignal_RTS)3606val &= ~BIT6;3607else3608val |= BIT6;3609} else {3610if (info->serial_signals & SerialSignal_RTS)3611val |= BIT2;3612else3613val &= ~BIT2;3614}3615write_reg(info, CHA + MODE, val);36163617if (info->serial_signals & SerialSignal_DTR)3618clear_reg_bits(info, CHA + PVR, PVR_DTR);3619else3620set_reg_bits(info, CHA + PVR, PVR_DTR);3621}36223623static void rx_reset_buffers(MGSLPC_INFO *info)3624{3625RXBUF *buf;3626int i;36273628info->rx_put = 0;3629info->rx_get = 0;3630info->rx_frame_count = 0;3631for (i=0 ; i < info->rx_buf_count ; i++) {3632buf = (RXBUF*)(info->rx_buf + (i * info->rx_buf_size));3633buf->status = buf->count = 0;3634}3635}36363637/* Attempt to return a received HDLC frame3638* Only frames received without errors are returned.3639*3640* Returns true if frame returned, otherwise false3641*/3642static bool rx_get_frame(MGSLPC_INFO *info, struct tty_struct *tty)3643{3644unsigned short status;3645RXBUF *buf;3646unsigned int framesize = 0;3647unsigned long flags;3648bool return_frame = false;36493650if (info->rx_frame_count == 0)3651return false;36523653buf = (RXBUF*)(info->rx_buf + (info->rx_get * info->rx_buf_size));36543655status = buf->status;36563657/* 07 VFR 1=valid frame3658* 06 RDO 1=data overrun3659* 05 CRC 1=OK, 0=error3660* 04 RAB 1=frame aborted3661*/3662if ((status & 0xf0) != 0xA0) {3663if (!(status & BIT7) || (status & BIT4))3664info->icount.rxabort++;3665else if (status & BIT6)3666info->icount.rxover++;3667else if (!(status & BIT5)) {3668info->icount.rxcrc++;3669if (info->params.crc_type & HDLC_CRC_RETURN_EX)3670return_frame = true;3671}3672framesize = 0;3673#if SYNCLINK_GENERIC_HDLC3674{3675info->netdev->stats.rx_errors++;3676info->netdev->stats.rx_frame_errors++;3677}3678#endif3679} else3680return_frame = true;36813682if (return_frame)3683framesize = buf->count;36843685if (debug_level >= DEBUG_LEVEL_BH)3686printk("%s(%d):rx_get_frame(%s) status=%04X size=%d\n",3687__FILE__,__LINE__,info->device_name,status,framesize);36883689if (debug_level >= DEBUG_LEVEL_DATA)3690trace_block(info, buf->data, framesize, 0);36913692if (framesize) {3693if ((info->params.crc_type & HDLC_CRC_RETURN_EX &&3694framesize+1 > info->max_frame_size) ||3695framesize > info->max_frame_size)3696info->icount.rxlong++;3697else {3698if (status & BIT5)3699info->icount.rxok++;37003701if (info->params.crc_type & HDLC_CRC_RETURN_EX) {3702*(buf->data + framesize) = status & BIT5 ? RX_OK:RX_CRC_ERROR;3703++framesize;3704}37053706#if SYNCLINK_GENERIC_HDLC3707if (info->netcount)3708hdlcdev_rx(info, buf->data, framesize);3709else3710#endif3711ldisc_receive_buf(tty, buf->data, info->flag_buf, framesize);3712}3713}37143715spin_lock_irqsave(&info->lock,flags);3716buf->status = buf->count = 0;3717info->rx_frame_count--;3718info->rx_get++;3719if (info->rx_get >= info->rx_buf_count)3720info->rx_get = 0;3721spin_unlock_irqrestore(&info->lock,flags);37223723return true;3724}37253726static bool register_test(MGSLPC_INFO *info)3727{3728static unsigned char patterns[] =3729{ 0x00, 0xff, 0xaa, 0x55, 0x69, 0x96, 0x0f };3730static unsigned int count = ARRAY_SIZE(patterns);3731unsigned int i;3732bool rc = true;3733unsigned long flags;37343735spin_lock_irqsave(&info->lock,flags);3736reset_device(info);37373738for (i = 0; i < count; i++) {3739write_reg(info, XAD1, patterns[i]);3740write_reg(info, XAD2, patterns[(i + 1) % count]);3741if ((read_reg(info, XAD1) != patterns[i]) ||3742(read_reg(info, XAD2) != patterns[(i + 1) % count])) {3743rc = false;3744break;3745}3746}37473748spin_unlock_irqrestore(&info->lock,flags);3749return rc;3750}37513752static bool irq_test(MGSLPC_INFO *info)3753{3754unsigned long end_time;3755unsigned long flags;37563757spin_lock_irqsave(&info->lock,flags);3758reset_device(info);37593760info->testing_irq = true;3761hdlc_mode(info);37623763info->irq_occurred = false;37643765/* init hdlc mode */37663767irq_enable(info, CHA, IRQ_TIMER);3768write_reg(info, CHA + TIMR, 0); /* 512 cycles */3769issue_command(info, CHA, CMD_START_TIMER);37703771spin_unlock_irqrestore(&info->lock,flags);37723773end_time=100;3774while(end_time-- && !info->irq_occurred) {3775msleep_interruptible(10);3776}37773778info->testing_irq = false;37793780spin_lock_irqsave(&info->lock,flags);3781reset_device(info);3782spin_unlock_irqrestore(&info->lock,flags);37833784return info->irq_occurred;3785}37863787static int adapter_test(MGSLPC_INFO *info)3788{3789if (!register_test(info)) {3790info->init_error = DiagStatus_AddressFailure;3791printk( "%s(%d):Register test failure for device %s Addr=%04X\n",3792__FILE__,__LINE__,info->device_name, (unsigned short)(info->io_base) );3793return -ENODEV;3794}37953796if (!irq_test(info)) {3797info->init_error = DiagStatus_IrqFailure;3798printk( "%s(%d):Interrupt test failure for device %s IRQ=%d\n",3799__FILE__,__LINE__,info->device_name, (unsigned short)(info->irq_level) );3800return -ENODEV;3801}38023803if (debug_level >= DEBUG_LEVEL_INFO)3804printk("%s(%d):device %s passed diagnostics\n",3805__FILE__,__LINE__,info->device_name);3806return 0;3807}38083809static void trace_block(MGSLPC_INFO *info,const char* data, int count, int xmit)3810{3811int i;3812int linecount;3813if (xmit)3814printk("%s tx data:\n",info->device_name);3815else3816printk("%s rx data:\n",info->device_name);38173818while(count) {3819if (count > 16)3820linecount = 16;3821else3822linecount = count;38233824for(i=0;i<linecount;i++)3825printk("%02X ",(unsigned char)data[i]);3826for(;i<17;i++)3827printk(" ");3828for(i=0;i<linecount;i++) {3829if (data[i]>=040 && data[i]<=0176)3830printk("%c",data[i]);3831else3832printk(".");3833}3834printk("\n");38353836data += linecount;3837count -= linecount;3838}3839}38403841/* HDLC frame time out3842* update stats and do tx completion processing3843*/3844static void tx_timeout(unsigned long context)3845{3846MGSLPC_INFO *info = (MGSLPC_INFO*)context;3847unsigned long flags;38483849if ( debug_level >= DEBUG_LEVEL_INFO )3850printk( "%s(%d):tx_timeout(%s)\n",3851__FILE__,__LINE__,info->device_name);3852if(info->tx_active &&3853info->params.mode == MGSL_MODE_HDLC) {3854info->icount.txtimeout++;3855}3856spin_lock_irqsave(&info->lock,flags);3857info->tx_active = false;3858info->tx_count = info->tx_put = info->tx_get = 0;38593860spin_unlock_irqrestore(&info->lock,flags);38613862#if SYNCLINK_GENERIC_HDLC3863if (info->netcount)3864hdlcdev_tx_done(info);3865else3866#endif3867{3868struct tty_struct *tty = tty_port_tty_get(&info->port);3869bh_transmit(info, tty);3870tty_kref_put(tty);3871}3872}38733874#if SYNCLINK_GENERIC_HDLC38753876/**3877* called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)3878* set encoding and frame check sequence (FCS) options3879*3880* dev pointer to network device structure3881* encoding serial encoding setting3882* parity FCS setting3883*3884* returns 0 if success, otherwise error code3885*/3886static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,3887unsigned short parity)3888{3889MGSLPC_INFO *info = dev_to_port(dev);3890struct tty_struct *tty;3891unsigned char new_encoding;3892unsigned short new_crctype;38933894/* return error if TTY interface open */3895if (info->port.count)3896return -EBUSY;38973898switch (encoding)3899{3900case ENCODING_NRZ: new_encoding = HDLC_ENCODING_NRZ; break;3901case ENCODING_NRZI: new_encoding = HDLC_ENCODING_NRZI_SPACE; break;3902case ENCODING_FM_MARK: new_encoding = HDLC_ENCODING_BIPHASE_MARK; break;3903case ENCODING_FM_SPACE: new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break;3904case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break;3905default: return -EINVAL;3906}39073908switch (parity)3909{3910case PARITY_NONE: new_crctype = HDLC_CRC_NONE; break;3911case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break;3912case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break;3913default: return -EINVAL;3914}39153916info->params.encoding = new_encoding;3917info->params.crc_type = new_crctype;39183919/* if network interface up, reprogram hardware */3920if (info->netcount) {3921tty = tty_port_tty_get(&info->port);3922mgslpc_program_hw(info, tty);3923tty_kref_put(tty);3924}39253926return 0;3927}39283929/**3930* called by generic HDLC layer to send frame3931*3932* skb socket buffer containing HDLC frame3933* dev pointer to network device structure3934*/3935static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb,3936struct net_device *dev)3937{3938MGSLPC_INFO *info = dev_to_port(dev);3939unsigned long flags;39403941if (debug_level >= DEBUG_LEVEL_INFO)3942printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name);39433944/* stop sending until this frame completes */3945netif_stop_queue(dev);39463947/* copy data to device buffers */3948skb_copy_from_linear_data(skb, info->tx_buf, skb->len);3949info->tx_get = 0;3950info->tx_put = info->tx_count = skb->len;39513952/* update network statistics */3953dev->stats.tx_packets++;3954dev->stats.tx_bytes += skb->len;39553956/* done with socket buffer, so free it */3957dev_kfree_skb(skb);39583959/* save start time for transmit timeout detection */3960dev->trans_start = jiffies;39613962/* start hardware transmitter if necessary */3963spin_lock_irqsave(&info->lock,flags);3964if (!info->tx_active) {3965struct tty_struct *tty = tty_port_tty_get(&info->port);3966tx_start(info, tty);3967tty_kref_put(tty);3968}3969spin_unlock_irqrestore(&info->lock,flags);39703971return NETDEV_TX_OK;3972}39733974/**3975* called by network layer when interface enabled3976* claim resources and initialize hardware3977*3978* dev pointer to network device structure3979*3980* returns 0 if success, otherwise error code3981*/3982static int hdlcdev_open(struct net_device *dev)3983{3984MGSLPC_INFO *info = dev_to_port(dev);3985struct tty_struct *tty;3986int rc;3987unsigned long flags;39883989if (debug_level >= DEBUG_LEVEL_INFO)3990printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name);39913992/* generic HDLC layer open processing */3993if ((rc = hdlc_open(dev)))3994return rc;39953996/* arbitrate between network and tty opens */3997spin_lock_irqsave(&info->netlock, flags);3998if (info->port.count != 0 || info->netcount != 0) {3999printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name);4000spin_unlock_irqrestore(&info->netlock, flags);4001return -EBUSY;4002}4003info->netcount=1;4004spin_unlock_irqrestore(&info->netlock, flags);40054006tty = tty_port_tty_get(&info->port);4007/* claim resources and init adapter */4008if ((rc = startup(info, tty)) != 0) {4009tty_kref_put(tty);4010spin_lock_irqsave(&info->netlock, flags);4011info->netcount=0;4012spin_unlock_irqrestore(&info->netlock, flags);4013return rc;4014}4015/* assert DTR and RTS, apply hardware settings */4016info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;4017mgslpc_program_hw(info, tty);4018tty_kref_put(tty);40194020/* enable network layer transmit */4021dev->trans_start = jiffies;4022netif_start_queue(dev);40234024/* inform generic HDLC layer of current DCD status */4025spin_lock_irqsave(&info->lock, flags);4026get_signals(info);4027spin_unlock_irqrestore(&info->lock, flags);4028if (info->serial_signals & SerialSignal_DCD)4029netif_carrier_on(dev);4030else4031netif_carrier_off(dev);4032return 0;4033}40344035/**4036* called by network layer when interface is disabled4037* shutdown hardware and release resources4038*4039* dev pointer to network device structure4040*4041* returns 0 if success, otherwise error code4042*/4043static int hdlcdev_close(struct net_device *dev)4044{4045MGSLPC_INFO *info = dev_to_port(dev);4046struct tty_struct *tty = tty_port_tty_get(&info->port);4047unsigned long flags;40484049if (debug_level >= DEBUG_LEVEL_INFO)4050printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name);40514052netif_stop_queue(dev);40534054/* shutdown adapter and release resources */4055shutdown(info, tty);4056tty_kref_put(tty);4057hdlc_close(dev);40584059spin_lock_irqsave(&info->netlock, flags);4060info->netcount=0;4061spin_unlock_irqrestore(&info->netlock, flags);40624063return 0;4064}40654066/**4067* called by network layer to process IOCTL call to network device4068*4069* dev pointer to network device structure4070* ifr pointer to network interface request structure4071* cmd IOCTL command code4072*4073* returns 0 if success, otherwise error code4074*/4075static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)4076{4077const size_t size = sizeof(sync_serial_settings);4078sync_serial_settings new_line;4079sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;4080MGSLPC_INFO *info = dev_to_port(dev);4081unsigned int flags;40824083if (debug_level >= DEBUG_LEVEL_INFO)4084printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name);40854086/* return error if TTY interface open */4087if (info->port.count)4088return -EBUSY;40894090if (cmd != SIOCWANDEV)4091return hdlc_ioctl(dev, ifr, cmd);40924093memset(&new_line, 0, size);40944095switch(ifr->ifr_settings.type) {4096case IF_GET_IFACE: /* return current sync_serial_settings */40974098ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;4099if (ifr->ifr_settings.size < size) {4100ifr->ifr_settings.size = size; /* data size wanted */4101return -ENOBUFS;4102}41034104flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |4105HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN |4106HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |4107HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN);41084109switch (flags){4110case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;4111case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break;4112case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_TXINT; break;4113case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break;4114default: new_line.clock_type = CLOCK_DEFAULT;4115}41164117new_line.clock_rate = info->params.clock_speed;4118new_line.loopback = info->params.loopback ? 1:0;41194120if (copy_to_user(line, &new_line, size))4121return -EFAULT;4122return 0;41234124case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */41254126if(!capable(CAP_NET_ADMIN))4127return -EPERM;4128if (copy_from_user(&new_line, line, size))4129return -EFAULT;41304131switch (new_line.clock_type)4132{4133case CLOCK_EXT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break;4134case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break;4135case CLOCK_INT: flags = HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG; break;4136case CLOCK_TXINT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG; break;4137case CLOCK_DEFAULT: flags = info->params.flags &4138(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |4139HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN |4140HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |4141HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); break;4142default: return -EINVAL;4143}41444145if (new_line.loopback != 0 && new_line.loopback != 1)4146return -EINVAL;41474148info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |4149HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN |4150HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |4151HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN);4152info->params.flags |= flags;41534154info->params.loopback = new_line.loopback;41554156if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG))4157info->params.clock_speed = new_line.clock_rate;4158else4159info->params.clock_speed = 0;41604161/* if network interface up, reprogram hardware */4162if (info->netcount) {4163struct tty_struct *tty = tty_port_tty_get(&info->port);4164mgslpc_program_hw(info, tty);4165tty_kref_put(tty);4166}4167return 0;41684169default:4170return hdlc_ioctl(dev, ifr, cmd);4171}4172}41734174/**4175* called by network layer when transmit timeout is detected4176*4177* dev pointer to network device structure4178*/4179static void hdlcdev_tx_timeout(struct net_device *dev)4180{4181MGSLPC_INFO *info = dev_to_port(dev);4182unsigned long flags;41834184if (debug_level >= DEBUG_LEVEL_INFO)4185printk("hdlcdev_tx_timeout(%s)\n",dev->name);41864187dev->stats.tx_errors++;4188dev->stats.tx_aborted_errors++;41894190spin_lock_irqsave(&info->lock,flags);4191tx_stop(info);4192spin_unlock_irqrestore(&info->lock,flags);41934194netif_wake_queue(dev);4195}41964197/**4198* called by device driver when transmit completes4199* reenable network layer transmit if stopped4200*4201* info pointer to device instance information4202*/4203static void hdlcdev_tx_done(MGSLPC_INFO *info)4204{4205if (netif_queue_stopped(info->netdev))4206netif_wake_queue(info->netdev);4207}42084209/**4210* called by device driver when frame received4211* pass frame to network layer4212*4213* info pointer to device instance information4214* buf pointer to buffer contianing frame data4215* size count of data bytes in buf4216*/4217static void hdlcdev_rx(MGSLPC_INFO *info, char *buf, int size)4218{4219struct sk_buff *skb = dev_alloc_skb(size);4220struct net_device *dev = info->netdev;42214222if (debug_level >= DEBUG_LEVEL_INFO)4223printk("hdlcdev_rx(%s)\n",dev->name);42244225if (skb == NULL) {4226printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", dev->name);4227dev->stats.rx_dropped++;4228return;4229}42304231memcpy(skb_put(skb, size), buf, size);42324233skb->protocol = hdlc_type_trans(skb, dev);42344235dev->stats.rx_packets++;4236dev->stats.rx_bytes += size;42374238netif_rx(skb);4239}42404241static const struct net_device_ops hdlcdev_ops = {4242.ndo_open = hdlcdev_open,4243.ndo_stop = hdlcdev_close,4244.ndo_change_mtu = hdlc_change_mtu,4245.ndo_start_xmit = hdlc_start_xmit,4246.ndo_do_ioctl = hdlcdev_ioctl,4247.ndo_tx_timeout = hdlcdev_tx_timeout,4248};42494250/**4251* called by device driver when adding device instance4252* do generic HDLC initialization4253*4254* info pointer to device instance information4255*4256* returns 0 if success, otherwise error code4257*/4258static int hdlcdev_init(MGSLPC_INFO *info)4259{4260int rc;4261struct net_device *dev;4262hdlc_device *hdlc;42634264/* allocate and initialize network and HDLC layer objects */42654266if (!(dev = alloc_hdlcdev(info))) {4267printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__);4268return -ENOMEM;4269}42704271/* for network layer reporting purposes only */4272dev->base_addr = info->io_base;4273dev->irq = info->irq_level;42744275/* network layer callbacks and settings */4276dev->netdev_ops = &hdlcdev_ops;4277dev->watchdog_timeo = 10 * HZ;4278dev->tx_queue_len = 50;42794280/* generic HDLC layer callbacks and settings */4281hdlc = dev_to_hdlc(dev);4282hdlc->attach = hdlcdev_attach;4283hdlc->xmit = hdlcdev_xmit;42844285/* register objects with HDLC layer */4286if ((rc = register_hdlc_device(dev))) {4287printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);4288free_netdev(dev);4289return rc;4290}42914292info->netdev = dev;4293return 0;4294}42954296/**4297* called by device driver when removing device instance4298* do generic HDLC cleanup4299*4300* info pointer to device instance information4301*/4302static void hdlcdev_exit(MGSLPC_INFO *info)4303{4304unregister_hdlc_device(info->netdev);4305free_netdev(info->netdev);4306info->netdev = NULL;4307}43084309#endif /* CONFIG_HDLC */4310431143124313