X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fchar%2Fsynclink_gt.c;h=792c79c315e00292abc21e7febea957c171506c0;hb=88032b322a38b37335c8cb2e3473a45c81d280eb;hp=2f07b085536b8879b67ece97348a1126074e2a6d;hpb=a4b47ab9464a8200528fad3101668abdd7379cf9;p=pandora-kernel.git diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 2f07b085536b..792c79c315e0 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -1,5 +1,5 @@ /* - * $Id: synclink_gt.c,v 4.25 2006/02/06 21:20:33 paulkf Exp $ + * $Id: synclink_gt.c,v 4.36 2006/08/28 20:47:14 paulkf Exp $ * * Device driver for Microgate SyncLink GT serial adapters. * @@ -83,20 +83,22 @@ #include "linux/synclink.h" -#ifdef CONFIG_HDLC_MODULE -#define CONFIG_HDLC 1 +#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_GT_MODULE)) +#define SYNCLINK_GENERIC_HDLC 1 +#else +#define SYNCLINK_GENERIC_HDLC 0 #endif /* * module identification */ static char *driver_name = "SyncLink GT"; -static char *driver_version = "$Revision: 4.25 $"; +static char *driver_version = "$Revision: 4.36 $"; static char *tty_driver_name = "synclink_gt"; static char *tty_dev_prefix = "ttySLG"; MODULE_LICENSE("GPL"); #define MGSL_MAGIC 0x5401 -#define MAX_DEVICES 12 +#define MAX_DEVICES 32 static struct pci_device_id pci_table[] = { {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, @@ -149,7 +151,7 @@ static struct tty_driver *serial_driver; static int open(struct tty_struct *tty, struct file * filp); static void close(struct tty_struct *tty, struct file * filp); static void hangup(struct tty_struct *tty); -static void set_termios(struct tty_struct *tty, struct termios *old_termios); +static void set_termios(struct tty_struct *tty, struct ktermios *old_termios); static int write(struct tty_struct *tty, const unsigned char *buf, int count); static void put_char(struct tty_struct *tty, unsigned char ch); @@ -171,7 +173,7 @@ static void set_break(struct tty_struct *tty, int break_state); /* * generic HDLC support and callbacks */ -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC #define dev_to_port(D) (dev_to_hdlc(D)->priv) static void hdlcdev_tx_done(struct slgt_info *info); static void hdlcdev_rx(struct slgt_info *info, char *buf, int size); @@ -359,7 +361,7 @@ struct slgt_info { int netcount; int dosyncppp; spinlock_t netlock; -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC struct net_device *netdev; #endif @@ -461,7 +463,7 @@ static int adapter_test(struct slgt_info *info); static void reset_adapter(struct slgt_info *info); static void reset_port(struct slgt_info *info); static void async_mode(struct slgt_info *info); -static void hdlc_mode(struct slgt_info *info); +static void sync_mode(struct slgt_info *info); static void rx_stop(struct slgt_info *info); static void rx_start(struct slgt_info *info); @@ -485,13 +487,13 @@ static void enable_loopback(struct slgt_info *info); static void set_rate(struct slgt_info *info, u32 data_rate); static int bh_action(struct slgt_info *info); -static void bh_handler(void* context); +static void bh_handler(struct work_struct *work); static void bh_transmit(struct slgt_info *info); static void isr_serial(struct slgt_info *info); static void isr_rdma(struct slgt_info *info); static void isr_txeom(struct slgt_info *info, unsigned short status); static void isr_tdma(struct slgt_info *info); -static irqreturn_t slgt_interrupt(int irq, void *dev_id, struct pt_regs * regs); +static irqreturn_t slgt_interrupt(int irq, void *dev_id); static int alloc_dma_bufs(struct slgt_info *info); static void free_dma_bufs(struct slgt_info *info); @@ -814,7 +816,7 @@ static void hangup(struct tty_struct *tty) wake_up_interruptible(&info->open_wait); } -static void set_termios(struct tty_struct *tty, struct termios *old_termios) +static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct slgt_info *info = tty->driver_data; unsigned long flags; @@ -881,7 +883,9 @@ static int write(struct tty_struct *tty, if (!count) goto cleanup; - if (info->params.mode == MGSL_MODE_RAW) { + if (info->params.mode == MGSL_MODE_RAW || + info->params.mode == MGSL_MODE_MONOSYNC || + info->params.mode == MGSL_MODE_BISYNC) { unsigned int bufs_needed = (count/DMABUFSIZE); unsigned int bufs_free = free_tbuf_count(info); if (count % DMABUFSIZE) @@ -1352,7 +1356,7 @@ static void set_break(struct tty_struct *tty, int break_state) spin_unlock_irqrestore(&info->lock,flags); } -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC /** * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.) @@ -1876,9 +1880,9 @@ static int bh_action(struct slgt_info *info) /* * perform bottom half processing */ -static void bh_handler(void* context) +static void bh_handler(struct work_struct *work) { - struct slgt_info *info = context; + struct slgt_info *info = container_of(work, struct slgt_info, task); int action; if (!info) @@ -1897,6 +1901,8 @@ static void bh_handler(void* context) while(rx_get_frame(info)); break; case MGSL_MODE_RAW: + case MGSL_MODE_MONOSYNC: + case MGSL_MODE_BISYNC: while(rx_get_buf(info)); break; } @@ -1998,7 +2004,7 @@ static void dcd_change(struct slgt_info *info) } else { info->input_signal_events.dcd_down++; } -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC if (info->netcount) { if (info->signals & SerialSignal_DCD) netif_carrier_on(info->netdev); @@ -2176,7 +2182,7 @@ static void isr_txeom(struct slgt_info *info, unsigned short status) set_signals(info); } -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC if (info->netcount) hdlcdev_tx_done(info); else @@ -2213,9 +2219,8 @@ static void isr_gpio(struct slgt_info *info, unsigned int changed, unsigned int * * irq interrupt number * dev_id device ID supplied during interrupt registration - * regs interrupted processor context */ -static irqreturn_t slgt_interrupt(int irq, void *dev_id, struct pt_regs * regs) +static irqreturn_t slgt_interrupt(int irq, void *dev_id) { struct slgt_info *info; unsigned int gsr; @@ -2362,10 +2367,9 @@ static void program_hw(struct slgt_info *info) rx_stop(info); tx_stop(info); - if (info->params.mode == MGSL_MODE_HDLC || - info->params.mode == MGSL_MODE_RAW || + if (info->params.mode != MGSL_MODE_ASYNC || info->netcount) - hdlc_mode(info); + sync_mode(info); else async_mode(info); @@ -2564,6 +2568,10 @@ static int rx_enable(struct slgt_info *info, int enable) if (enable) { if (!info->rx_enabled) rx_start(info); + else if (enable == 2) { + /* force hunt mode (write 1 to RCR[3]) */ + wr_reg16(info, RCR, rd_reg16(info, RCR) | BIT3); + } } else { if (info->rx_enabled) rx_stop(info); @@ -3300,7 +3308,7 @@ static void add_device(struct slgt_info *info) devstr, info->device_name, info->phys_reg_addr, info->irq_level, info->max_frame_size); -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC hdlcdev_init(info); #endif } @@ -3320,7 +3328,7 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev } else { memset(info, 0, sizeof(struct slgt_info)); info->magic = MGSL_MAGIC; - INIT_WORK(&info->task, bh_handler, info); + INIT_WORK(&info->task, bh_handler); info->max_frame_size = 4096; info->raw_rx_size = DMABUFSIZE; info->close_delay = 5*HZ/10; @@ -3434,7 +3442,7 @@ static void __devexit remove_one(struct pci_dev *dev) { } -static struct tty_operations ops = { +static const struct tty_operations ops = { .open = open, .close = close, .write = write, @@ -3482,7 +3490,7 @@ static void slgt_cleanup(void) /* release devices */ info = slgt_device_list; while(info) { -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC hdlcdev_exit(info); #endif free_dma_bufs(info); @@ -3516,6 +3524,7 @@ static int __init slgt_init(void) if (!slgt_device_list) { printk("%s no devices found\n",driver_name); + pci_unregister_driver(&pci_driver); return -ENODEV; } @@ -3537,6 +3546,8 @@ static int __init slgt_init(void) serial_driver->init_termios = tty_std_termios; serial_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver->init_termios.c_ispeed = 9600; + serial_driver->init_termios.c_ospeed = 9600; serial_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(serial_driver, &ops); if ((rc = tty_register_driver(serial_driver)) < 0) { @@ -3748,7 +3759,7 @@ static void tx_start(struct slgt_info *info) { if (!info->tx_enabled) { wr_reg16(info, TCR, - (unsigned short)(rd_reg16(info, TCR) | BIT1)); + (unsigned short)((rd_reg16(info, TCR) | BIT1) & ~BIT2)); info->tx_enabled = TRUE; } @@ -3775,13 +3786,18 @@ static void tx_start(struct slgt_info *info) tdma_reset(info); /* set 1st descriptor address */ wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc); - if (info->params.mode == MGSL_MODE_RAW) + switch(info->params.mode) { + case MGSL_MODE_RAW: + case MGSL_MODE_MONOSYNC: + case MGSL_MODE_BISYNC: wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */ - else + break; + default: wr_reg32(info, TDCSR, BIT0); /* DMA enable */ + } } - if (info->params.mode != MGSL_MODE_RAW) { + if (info->params.mode == MGSL_MODE_HDLC) { info->tx_timer.expires = jiffies + msecs_to_jiffies(5000); add_timer(&info->tx_timer); } @@ -3814,7 +3830,6 @@ static void tx_stop(struct slgt_info *info) /* reset and disable transmitter */ val = rd_reg16(info, TCR) & ~BIT1; /* clear enable bit */ wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */ - wr_reg16(info, TCR, val); /* clear reset */ slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER); @@ -3982,7 +3997,7 @@ static void async_mode(struct slgt_info *info) enable_loopback(info); } -static void hdlc_mode(struct slgt_info *info) +static void sync_mode(struct slgt_info *info) { unsigned short val; @@ -3992,7 +4007,7 @@ static void hdlc_mode(struct slgt_info *info) /* TCR (tx control) * - * 15..13 mode, 000=HDLC 001=raw sync + * 15..13 mode, 000=HDLC 001=raw 010=async 011=monosync 100=bisync * 12..10 encoding * 09 CRC enable * 08 CRC32 @@ -4006,8 +4021,11 @@ static void hdlc_mode(struct slgt_info *info) */ val = 0; - if (info->params.mode == MGSL_MODE_RAW) - val |= BIT13; + switch(info->params.mode) { + case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break; + case MGSL_MODE_BISYNC: val |= BIT15; break; + case MGSL_MODE_RAW: val |= BIT13; break; + } if (info->if_mode & MGSL_INTERFACE_RTS_EN) val |= BIT7; @@ -4058,7 +4076,7 @@ static void hdlc_mode(struct slgt_info *info) /* RCR (rx control) * - * 15..13 mode, 000=HDLC 001=raw sync + * 15..13 mode, 000=HDLC 001=raw 010=async 011=monosync 100=bisync * 12..10 encoding * 09 CRC enable * 08 CRC32 @@ -4069,8 +4087,11 @@ static void hdlc_mode(struct slgt_info *info) */ val = 0; - if (info->params.mode == MGSL_MODE_RAW) - val |= BIT13; + switch(info->params.mode) { + case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break; + case MGSL_MODE_BISYNC: val |= BIT15; break; + case MGSL_MODE_RAW: val |= BIT13; break; + } switch(info->params.encoding) { @@ -4309,10 +4330,15 @@ static void free_rbufs(struct slgt_info *info, unsigned int i, unsigned int last while(!done) { /* reset current buffer for reuse */ info->rbufs[i].status = 0; - if (info->params.mode == MGSL_MODE_RAW) + switch(info->params.mode) { + case MGSL_MODE_RAW: + case MGSL_MODE_MONOSYNC: + case MGSL_MODE_BISYNC: set_desc_count(info->rbufs[i], info->raw_rx_size); - else + break; + default: set_desc_count(info->rbufs[i], DMABUFSIZE); + } if (i == last) done = 1; @@ -4412,7 +4438,7 @@ check_again: framesize = 0; } -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC if (framesize == 0) { struct net_device_stats *stats = hdlc_stats(info->netdev); stats->rx_errors++; @@ -4455,7 +4481,7 @@ check_again: framesize++; } -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC if (info->netcount) hdlcdev_rx(info,info->tmp_rbuf, framesize); else @@ -4477,13 +4503,24 @@ cleanup: static int rx_get_buf(struct slgt_info *info) { unsigned int i = info->rbuf_current; + unsigned int count; if (!desc_complete(info->rbufs[i])) return 0; - DBGDATA(info, info->rbufs[i].buf, desc_count(info->rbufs[i]), "rx"); - DBGINFO(("rx_get_buf size=%d\n", desc_count(info->rbufs[i]))); - ldisc_receive_buf(info->tty, info->rbufs[i].buf, - info->flag_buf, desc_count(info->rbufs[i])); + count = desc_count(info->rbufs[i]); + switch(info->params.mode) { + case MGSL_MODE_MONOSYNC: + case MGSL_MODE_BISYNC: + /* ignore residue in byte synchronous modes */ + if (desc_residue(info->rbufs[i])) + count--; + break; + } + DBGDATA(info, info->rbufs[i].buf, count, "rx"); + DBGINFO(("rx_get_buf size=%d\n", count)); + if (count) + ldisc_receive_buf(info->tty, info->rbufs[i].buf, + info->flag_buf, count); free_rbufs(info, i, i); return 1; } @@ -4549,8 +4586,13 @@ static void tx_load(struct slgt_info *info, const char *buf, unsigned int size) size -= count; buf += count; - if (!size && info->params.mode != MGSL_MODE_RAW) - set_desc_eof(*d, 1); /* HDLC: set EOF of last desc */ + /* + * set EOF bit for last buffer of HDLC frame or + * for every buffer in raw mode + */ + if ((!size && info->params.mode == MGSL_MODE_HDLC) || + info->params.mode == MGSL_MODE_RAW) + set_desc_eof(*d, 1); else set_desc_eof(*d, 0); @@ -4742,7 +4784,7 @@ static void tx_timeout(unsigned long context) info->tx_count = 0; spin_unlock_irqrestore(&info->lock,flags); -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC if (info->netcount) hdlcdev_tx_done(info); else @@ -4762,6 +4804,6 @@ static void rx_timeout(unsigned long context) spin_lock_irqsave(&info->lock, flags); info->pending_bh |= BH_RECEIVE; spin_unlock_irqrestore(&info->lock, flags); - bh_handler(info); + bh_handler(&info->task); }