patch-2.1.104 linux/drivers/char/cyclades.c
Next file: linux/drivers/char/epca.c
Previous file: linux/drivers/char/c-qcam.c
Back to the patch index
Back to the overall index
- Lines: 1806
- Date:
Wed Jun 3 11:04:16 1998
- Orig file:
v2.1.103/linux/drivers/char/cyclades.c
- Orig date:
Thu May 14 19:47:39 1998
diff -u --recursive --new-file v2.1.103/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c
@@ -1,9 +1,7 @@
#define BLOCKMOVE
-#define NEW_INTR_FLOW
#define Z_WAKE
-#define NEW_PCI
static char rcsid[] =
-"$Revision: 2.2.1.1 $$Date: 1998/03/19 16:43:12 $";
+"$Revision: 2.2.1.3 $$Date: 1998/06/01 12:09:10 $";
/*
* linux/drivers/char/cyclades.c
@@ -33,6 +31,13 @@
* void cleanup_module(void);
*
* $Log: cyclades.c,v $
+ * Revision 2.2.1.3 1998/06/01 12:09:10 ivan
+ * General code review in order to comply with 2.1 kernel standards;
+ * data loss prevention for slow devices revisited (cy_wait_until_sent
+ * was created);
+ * removed conditional compilation for new/old PCI structure support
+ * (now the driver only supports the new PCI structure).
+ *
* Revision 2.2.1.1 1998/03/19 16:43:12 ivan
* added conditional compilation for new/old PCI structure support;
* removed kernel series (2.0.x / 2.1.x) conditional compilation.
@@ -40,7 +45,7 @@
* Revision 2.1.1.3 1998/03/16 18:01:12 ivan
* cleaned up the data loss fix;
* fixed XON/XOFF handling once more (Cyclades-Z);
- * general revision in the driver routines;
+ * general review of the driver routines;
* introduction of a mechanism to prevent data loss with slow
* printers, by forcing a delay before closing the port.
*
@@ -482,14 +487,15 @@
#define ZE_V1 2
#define SERIAL_PARANOIA_CHECK
-#undef SERIAL_DEBUG_OPEN
-#undef SERIAL_DEBUG_THROTTLE
-#undef SERIAL_DEBUG_OTHER
-#undef SERIAL_DEBUG_IO
-#undef SERIAL_DEBUG_COUNT
-#undef SERIAL_DEBUG_DTR
-#undef CYCLOM_16Y_HACK
-#undef CYCLOM_ENABLE_MONITORING
+#undef CY_DEBUG_OPEN
+#undef CY_DEBUG_THROTTLE
+#undef CY_DEBUG_OTHER
+#undef CY_DEBUG_IO
+#undef CY_DEBUG_COUNT
+#undef CY_DEBUG_DTR
+#undef CY_DEBUG_WAIT_UNTIL_SENT
+#undef CY_16Y_HACK
+#undef CY_ENABLE_MONITORING
#undef CY_PCI_DEBUG
#if 0
@@ -519,40 +525,38 @@
(cy_readl(&buf_ctrl->tx_bufsize) - 1))
#endif
+/*
+ * Include section
+ */
+#include <linux/config.h>
#include <linux/module.h>
-
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/timer.h>
+#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/serial.h>
-#include <linux/interrupt.h>
+#include <linux/major.h>
#include <linux/string.h>
#include <linux/fcntl.h>
#include <linux/ptrace.h>
#include <linux/cyclades.h>
-#include <linux/delay.h>
-#include <linux/major.h>
#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/delay.h>
#include <asm/system.h>
#include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
#include <asm/bitops.h>
-#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#ifndef NEW_PCI
-#include <linux/bios32.h>
-#endif
#include <linux/pci.h>
-
#include <linux/version.h>
-#include <asm/uaccess.h>
-#include <linux/init.h>
#define cy_put_user put_user
@@ -585,19 +589,16 @@
#define STD_COM_FLAGS (0)
-#define SERIAL_TYPE_NORMAL 1
-#define SERIAL_TYPE_CALLOUT 2
-
static DECLARE_TASK_QUEUE(tq_cyclades);
static struct tty_driver cy_serial_driver, cy_callout_driver;
+static int serial_refcount;
static volatile int cy_irq_triggered;
static volatile int cy_triggered;
static int cy_wild_int_mask;
static volatile ucchar *intr_base_addr;
-
/* This is the address lookup table. The driver will probe for
Cyclom-Y/ISA boards at all addresses in here. If you want the
driver to probe addresses at a different address, add it to
@@ -632,8 +633,6 @@
static int cy_next_channel = 0; /* next minor available */
-static int serial_refcount;
-
static struct tty_struct *serial_table[NR_PORTS];
static struct termios *serial_termios[NR_PORTS];
static struct termios *serial_termios_locked[NR_PORTS];
@@ -641,8 +640,7 @@
/* This is the per-irq data structure,
it maps an irq to the corresponding card */
-static struct cyclades_card *IRQ_cards[16];
-
+static struct cyclades_card *IRQ_cards[NR_IRQS];
/*
* tmp_buf is used as a temporary buffer by serial_write. We need to
@@ -654,7 +652,7 @@
* memory if large numbers of serial ports are open. This buffer is
* allocated when the first cy_open occurs.
*/
-static unsigned char *tmp_buf = 0;
+static unsigned char *tmp_buf;
static struct semaphore tmp_buf_sem = MUTEX;
/*
@@ -799,41 +797,6 @@
return 0;
} /* serial_paranoia_check */
-
-/* The following diagnostic routines allow the driver to spew
- information on the screen, even (especially!) during interrupts.
- */
-static void
-SP(char *data){
- unsigned long flags;
- save_flags(flags); cli();
- console_print(data);
- restore_flags(flags);
-}/* SP */
-
-static void
-CP(char data){
- unsigned long flags;
- char scrn[2];
- save_flags(flags); cli();
- scrn[0] = data;
- scrn[1] = '\0';
- console_print(scrn);
- restore_flags(flags);
-}/* CP */
-
-static void CP4(int data)
- { (data<10)? CP(data+'0'): CP(data+'A'-10); }/* CP4 */
-static void CP8(int data)
- { CP4((data>>4) & 0x0f); CP4( data & 0x0f); }/* CP8 */
-#if 0
-static void CP16(int data)
- { CP8((data>>8) & 0xff); CP8(data & 0xff); }/* CP16 */
-static void CP32(long data)
- { CP16((data>>16) & 0xffff); CP16(data & 0xffff); }/* CP32 */
-#endif
-
-
/*
* This routine is used by the interrupt handler to schedule
* processing in the software interrupt portion of the driver
@@ -1125,11 +1088,6 @@
if(cy_readb(intr_base_addr+(CySVRR<<index)) != 0) {
save_xir = (u_char) cy_readb(intr_base_addr+(CyTIR<<index));
save_car = cy_readb(intr_base_addr+(CyCAR<<index));
- if ((save_xir & 0x3) != 0){
- SP("channel ");
- CP8(save_xir);
- SP(" requesting unexpected interrupt\n");
- }
cy_writeb((u_long)intr_base_addr+(CyCAR<<index), (save_xir & 0x3));
cy_writeb((u_long)intr_base_addr+(CySRER<<index),
cy_readb(intr_base_addr+(CySRER<<index)) & ~CyTxMpty);
@@ -1286,7 +1244,7 @@
/* load # chars available from the chip */
char_count = cy_readb(base_addr+(CyRDCR<<index));
-#ifdef CYCLOM_ENABLE_MONITORING
+#ifdef CY_ENABLE_MONITORING
++info->mon.int_count;
info->mon.char_count += char_count;
if (char_count > info->mon.char_max)
@@ -1301,7 +1259,7 @@
data = cy_readb(base_addr+(CyRDSR<<index));
*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
*tty->flip.char_buf_ptr++ = data;
-#ifdef CYCLOM_16Y_HACK
+#ifdef CY_16Y_HACK
udelay(10L);
#endif
}
@@ -1387,11 +1345,9 @@
info->x_break = 0;
}
-#ifdef NEW_INTR_FLOW
if (!info->xmit_cnt){
cy_writeb((u_long)base_addr+(CySRER<<index),
cy_readb(base_addr+(CySRER<<index)) & ~CyTxMpty);
- cy_sched_event(info, Cy_EVENT_SHUTDOWN_WAKEUP);
goto txdone;
}
if (info->xmit_buf == 0){
@@ -1404,28 +1360,10 @@
cy_readb(base_addr+(CySRER<<index)) & ~CyTxMpty);
goto txdone;
}
-#endif
while (char_count-- > 0){
-#ifdef NEW_INTR_FLOW
if (!info->xmit_cnt){
goto txdone;
}
-#else
- if (!info->xmit_cnt){
- cy_writeb((u_long)base_addr+(CySRER<<index),
- cy_readb(base_addr+(CySRER<<index)) & ~CyTxMpty);
- goto txdone;
- }
- if (info->xmit_buf == 0){
- cy_writeb((u_long)base_addr+(CySRER<<index),
- cy_readb(base_addr+(CySRER<<index)) & ~CyTxMpty);
- goto txdone;
- }
- if (info->tty->stopped || info->tty->hw_stopped){
- cy_writeb((u_long)base_addr+(CySRER<<index),
- cy_readb(base_addr+(CySRER<<index)) & ~CyTxMpty);
- }
-#endif
/* Because the Embedded Transmit Commands have
been enabled, we must check to see if the
escape character, NULL, is being sent. If it
@@ -1725,14 +1663,12 @@
if ((fw_ver > 241 ?
((u_long)param) :
cy_readl(&ch_ctrl[channel].rs_status)) & C_RS_DCD) {
- /* SP("Open Wakeup\n"); */
cy_sched_event(info,
Cy_EVENT_OPEN_WAKEUP);
}else if(!((info->flags
& ASYNC_CALLOUT_ACTIVE)
&&(info->flags
& ASYNC_CALLOUT_NOHUP))){
- /* SP("Hangup\n"); */
cy_sched_event(info,
Cy_EVENT_HANGUP);
}
@@ -1744,7 +1680,6 @@
if( cy_readl(&ch_ctrl[channel].rs_status) & C_RS_DCD){
/* cy_start isn't used because...
HW flow is handled by the board */
- /* SP("Write Wakeup\n"); */
cy_sched_event(info,
Cy_EVENT_WRITE_WAKEUP);
}
@@ -1752,7 +1687,6 @@
if(!(cy_readl(&ch_ctrl[channel].rs_status) & C_RS_CTS)){
/* cy_stop isn't used because
HW flow is handled by the board */
- /* SP("Write stop\n"); */
}
}
}
@@ -1796,7 +1730,7 @@
info->last_active = jiffies;
info->jiffies[1] = jiffies;
-#ifdef CYCLOM_ENABLE_MONITORING
+#ifdef CY_ENABLE_MONITORING
info->mon.int_count++;
info->mon.char_count += char_count;
if (char_count > info->mon.char_max)
@@ -1806,7 +1740,6 @@
if( tty == 0){
/* flush received characters */
rx_get = (rx_get + char_count) & (rx_bufsize - 1);
- /* SP("-"); */
info->rflush_count++;
}else{
#ifdef BLOCKMOVE
@@ -1986,7 +1919,7 @@
base_addr = (unsigned char*)
(cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
printk("cyc startup card %d, chip %d, channel %d, base_addr %lx\n",
card, chip, channel, (long)base_addr);/**/
#endif
@@ -2004,7 +1937,7 @@
cy_writeb((ulong)base_addr+(CyMSVR1<<index), CyRTS);
cy_writeb((ulong)base_addr+(CyMSVR2<<index), CyDTR);
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
printk("cyc:startup raising DTR\n");
printk(" status: 0x%x, 0x%x\n",
cy_readb(base_addr+(CyMSVR1<<index)),
@@ -2040,7 +1973,7 @@
board_ctrl = &zfw_ctrl->board_ctrl;
ch_ctrl = zfw_ctrl->ch_ctrl;
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
printk("cyc startup Z card %d, channel %d, base_addr %lx\n",
card, channel, (long)base_addr);/**/
#endif
@@ -2068,7 +2001,7 @@
if (retval != 0){
printk("cyc:startup(2) retval was %x\n", retval);
}
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
printk("cyc:startup raising Z DTR\n");
#endif
@@ -2082,7 +2015,7 @@
}
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
printk(" cyc startup done\n");
#endif
return 0;
@@ -2142,7 +2075,7 @@
(cy_card[card].base_addr
+ (cy_chip_offset[chip]<<index));
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
printk("cyc shutdown Y card %d, chip %d, channel %d, base_addr %lx\n",
card, chip, channel, (long)base_addr);
#endif
@@ -2159,7 +2092,7 @@
if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
cy_writeb((u_long)base_addr+(CyMSVR1<<index), ~CyRTS);
cy_writeb((u_long)base_addr+(CyMSVR2<<index), ~CyDTR);
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
printk("cyc shutdown dropping DTR\n");
printk(" status: 0x%x, 0x%x\n",
cy_readb(base_addr+(CyMSVR1<<index)),
@@ -2183,7 +2116,7 @@
int retval;
base_addr = (unsigned char*) (cy_card[card].base_addr);
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
printk("cyc shutdown Z card %d, channel %d, base_addr %lx\n",
card, channel, (long)base_addr);
#endif
@@ -2217,7 +2150,7 @@
if (retval != 0){
printk("cyc:shutdown retval (2) was %x\n", retval);
}
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
printk("cyc:shutdown dropping Z DTR\n");
#endif
}
@@ -2230,7 +2163,7 @@
restore_flags(flags);
}
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
printk(" cyc shutdown done\n");
#endif
return;
@@ -2262,11 +2195,7 @@
if (info->flags & ASYNC_CLOSING) {
interruptible_sleep_on(&info->close_wait);
}
- if (info->flags & ASYNC_HUP_NOTIFY){
- return -EAGAIN;
- }else{
- return -ERESTARTSYS;
- }
+ return ((info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
}
/*
@@ -2313,7 +2242,7 @@
*/
retval = 0;
add_wait_queue(&info->open_wait, &wait);
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
printk("cyc block_til_ready before block: ttyC%d, count = %d\n",
info->line, info->count);/**/
#endif
@@ -2321,7 +2250,7 @@
if (!tty_hung_up_p(filp))
info->count--;
restore_flags(flags);
-#ifdef SERIAL_DEBUG_COUNT
+#ifdef CY_DEBUG_COUNT
printk("cyc block_til_ready: (%d): decrementing count to %d\n",
current->pid, info->count);
#endif
@@ -2338,11 +2267,12 @@
while (1) {
save_flags(flags); cli();
- if (!(info->flags & ASYNC_CALLOUT_ACTIVE)){
+ if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
+ (tty->termios->c_cflag & CBAUD)){
cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
cy_writeb((u_long)base_addr+(CyMSVR1<<index), CyRTS);
cy_writeb((u_long)base_addr+(CyMSVR2<<index), CyDTR);
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
printk("cyc:block_til_ready raising DTR\n");
printk(" status: 0x%x, 0x%x\n",
cy_readb(base_addr+(CyMSVR1<<index)),
@@ -2353,11 +2283,8 @@
current->state = TASK_INTERRUPTIBLE;
if (tty_hung_up_p(filp)
|| !(info->flags & ASYNC_INITIALIZED) ){
- if (info->flags & ASYNC_HUP_NOTIFY) {
- retval = -EAGAIN;
- }else{
- retval = -ERESTARTSYS;
- }
+ return ((info->flags & ASYNC_HUP_NOTIFY) ?
+ -EAGAIN : -ERESTARTSYS);
break;
}
save_flags(flags); cli();
@@ -2374,7 +2301,7 @@
retval = -ERESTARTSYS;
break;
}
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
printk("cyc block_til_ready blocking: ttyC%d, count = %d\n",
info->line, info->count);/**/
#endif
@@ -2408,18 +2335,15 @@
if (retval != 0){
printk("cyc:block_til_ready retval was %x\n", retval);
}
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
printk("cyc:block_til_ready raising Z DTR\n");
#endif
current->state = TASK_INTERRUPTIBLE;
if (tty_hung_up_p(filp)
|| !(info->flags & ASYNC_INITIALIZED) ){
- if (info->flags & ASYNC_HUP_NOTIFY) {
- retval = -EAGAIN;
- }else{
- retval = -ERESTARTSYS;
- }
+ return ((info->flags & ASYNC_HUP_NOTIFY) ?
+ -EAGAIN : -ERESTARTSYS);
break;
}
if (!(info->flags & ASYNC_CALLOUT_ACTIVE)
@@ -2432,7 +2356,7 @@
retval = -ERESTARTSYS;
break;
}
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
printk("cyc block_til_ready blocking: ttyC%d, count = %d\n",
info->line, info->count);/**/
#endif
@@ -2443,13 +2367,13 @@
remove_wait_queue(&info->open_wait, &wait);
if (!tty_hung_up_p(filp)){
info->count++;
-#ifdef SERIAL_DEBUG_COUNT
+#ifdef CY_DEBUG_COUNT
printk("cyc:block_til_ready (%d): incrementing count to %d\n",
current->pid, info->count);
#endif
}
info->blocked_open--;
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
printk("cyc:block_til_ready after blocking: ttyC%d, count = %d\n",
info->line, info->count);/**/
#endif
@@ -2464,11 +2388,12 @@
* This routine is called whenever a serial port is opened. It
* performs the serial-specific initialization for the tty structure.
*/
-int
+static int
cy_open(struct tty_struct *tty, struct file * filp)
{
struct cyclades_port *info;
int retval, line;
+ unsigned long page;
line = MINOR(tty->device) - tty->driver.minor_start;
if ((line < 0) || (NR_PORTS <= line)){
@@ -2491,46 +2416,50 @@
(ZFIRM_HLT==cy_readl(&((struct FIRM_ID *)
((cy_card[info->card]).base_addr+ID_ADDRESS))->signature)))
{
- printk ("Cyclades-Z Error: you need an external power supply for this number of ports.\n\rFirmware halted.\r\n");
+ printk ("cyc:Cyclades-Z Error: you need an external power supply for this number of ports.\n\rFirmware halted.\r\n");
} else {
- printk("Cyclades-Z firmware not yet loaded\n");
+ printk("cyc:Cyclades-Z firmware not yet loaded\n");
}
return -ENODEV;
}
}
-#ifdef SERIAL_DEBUG_OTHER
+#ifdef CY_DEBUG_OTHER
printk("cyc:cy_open ttyC%d\n", info->line); /* */
#endif
if (serial_paranoia_check(info, tty->device, "cy_open")){
return -ENODEV;
}
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
printk("cyc:cy_open ttyC%d, count = %d\n",
info->line, info->count);/**/
#endif
info->count++;
-#ifdef SERIAL_DEBUG_COUNT
+#ifdef CY_DEBUG_COUNT
printk("cyc:cy_open (%d): incrementing count to %d\n",
current->pid, info->count);
#endif
tty->driver_data = info;
info->tty = tty;
- /* Some drivers have (incorrect/incomplete) code to test
- against a race condition. Should add good code here!!! */
if (!tmp_buf) {
- tmp_buf = (unsigned char *) get_free_page(GFP_KERNEL);
- if (!tmp_buf){
- return -ENOMEM;
- }
+ page = get_free_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+ if (tmp_buf)
+ free_page(page);
+ else
+ tmp_buf = (unsigned char *) page;
}
- if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
- if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
- *tty->termios = info->normal_termios;
- else
- *tty->termios = info->callout_termios;
+ /*
+ * If the port is the middle of closing, bail out now
+ */
+ if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) {
+ if (info->flags & ASYNC_CLOSING)
+ interruptible_sleep_on(&info->close_wait);
+ return ((info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
}
+
/*
* Start up serial port
*/
@@ -2543,17 +2472,24 @@
retval = block_til_ready(tty, filp, info);
if (retval) {
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
printk("cyc:cy_open returning after block_til_ready with %d\n",
retval);
#endif
return retval;
}
+ if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
+ if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
+ *tty->termios = info->normal_termios;
+ else
+ *tty->termios = info->callout_termios;
+ }
+
info->session = current->session;
info->pgrp = current->pgrp;
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
printk(" cyc:cy_open done\n");/**/
#endif
@@ -2562,6 +2498,76 @@
/*
+ * cy_wait_until_sent() --- wait until the transmitter is empty
+ */
+static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+ struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
+ unsigned char *base_addr;
+ int card,chip,channel,index;
+ unsigned long orig_jiffies, char_time;
+
+ if (serial_paranoia_check(info, tty->device, "cy_wait_until_sent"))
+ return;
+
+ orig_jiffies = jiffies;
+ /*
+ * Set the check interval to be 1/5 of the estimated time to
+ * send a single character, and make it at least 1. The check
+ * interval should also be less than the timeout.
+ *
+ * Note: we have to use pretty tight timings here to satisfy
+ * the NIST-PCTS.
+ */
+ char_time = (info->timeout - HZ/50) / info->xmit_fifo_size;
+ char_time = char_time / 5;
+ if (char_time == 0)
+ char_time = 1;
+ if (timeout < 0)
+ timeout = 0;
+ if (timeout)
+ char_time = MIN(char_time, timeout);
+#ifdef CY_DEBUG_WAIT_UNTIL_SENT
+ printk("In cy_wait_until_sent(%d) check=%lu...", timeout, char_time);
+ printk("jiff=%lu...", jiffies);
+#endif
+ card = info->card;
+ channel = (info->line) - (cy_card[card].first_line);
+ if (!IS_CYC_Z(cy_card[card])) {
+ chip = channel>>2;
+ channel &= 0x03;
+ index = cy_card[card].bus_index;
+ base_addr = (unsigned char *)
+ (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
+ while (cy_readb(base_addr+(CySRER<<index)) & CyTxMpty) {
+#ifdef CY_DEBUG_WAIT_UNTIL_SENT
+ printk("Not clean (jiff=%lu)...", jiffies);
+#endif
+ current->state = TASK_INTERRUPTIBLE;
+ current->counter = 0; /* make us low-priority */
+ current->timeout = jiffies + char_time;
+ schedule();
+ if (signal_pending(current))
+ break;
+ if (timeout && ((orig_jiffies + timeout) < jiffies))
+ break;
+ }
+ current->state = TASK_RUNNING;
+ } else {
+ // Nothing to do!
+ }
+ /* Run one more char cycle */
+ current->state = TASK_INTERRUPTIBLE;
+ current->counter = 0; /* make us low-priority */
+ current->timeout = jiffies + (char_time * 5);
+ schedule();
+ current->state = TASK_RUNNING;
+#ifdef CY_DEBUG_WAIT_UNTIL_SENT
+ printk("Clean (jiff=%lu)...done\n", jiffies);
+#endif
+}
+
+/*
* This routine is called when a particular tty device is closed.
*/
static void
@@ -2570,7 +2576,7 @@
struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
unsigned long flags;
-#ifdef SERIAL_DEBUG_OTHER
+#ifdef CY_DEBUG_OTHER
printk("cyc:cy_close ttyC%d\n", info->line);
#endif
@@ -2578,7 +2584,7 @@
|| serial_paranoia_check(info, tty->device, "cy_close")){
return;
}
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
printk("cyc:cy_close ttyC%d, count = %d\n", info->line, info->count);
#endif
@@ -2586,6 +2592,7 @@
/* If the TTY is being hung up, nothing to do */
if (tty_hung_up_p(filp)) {
+ MOD_DEC_USE_COUNT;
restore_flags(flags);
return;
}
@@ -2602,18 +2609,18 @@
"info->count is %d\n", info->count);
info->count = 1;
}
-#ifdef SERIAL_DEBUG_COUNT
+#ifdef CY_DEBUG_COUNT
printk("cyc:cy_close at (%d): decrementing count to %d\n",
current->pid, info->count - 1);
#endif
if (--info->count < 0) {
-#ifdef SERIAL_DEBUG_COUNT
+#ifdef CY_DEBUG_COUNT
printk("cyc:cyc_close setting count to 0\n");
#endif
info->count = 0;
}
if (info->count) {
- MOD_DEC_USE_COUNT;
+ MOD_DEC_USE_COUNT;
restore_flags(flags);
return;
}
@@ -2632,28 +2639,25 @@
* the line discipline to only process XON/XOFF characters.
*/
tty->closing = 1;
- if (info->closing_wait2 != 0) { /* The port's being forced to wait,
- independent on the port settings */
- tty_wait_until_sent(tty, info->closing_wait2*HZ);
- } else {
- if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
- tty_wait_until_sent(tty, info->closing_wait*HZ);
+ if (info->closing_wait != CY_CLOSING_WAIT_NONE) {
+ tty_wait_until_sent(tty, info->closing_wait);
}
- /* Waiting for on-board buffers to be empty before closing the port */
if (!IS_CYC_Z(cy_card[info->card])) {
-#ifdef NEW_INTR_FLOW
unsigned char *base_addr = (unsigned char *)
cy_card[info->card].base_addr;
int index = cy_card[info->card].bus_index;
-
- if (cy_readb(base_addr+(CySRER<<index)) & CyTxMpty) {
- /* Interrupts are enabled, so go to sleep */
- interruptible_sleep_on(&info->shutdown_wait);
+ /* Stop accepting input */
+ cy_writeb((u_long)base_addr+(CySRER<<index),
+ cy_readb(base_addr+(CySRER<<index)) & ~CyRxData);
+ if (info->flags & ASYNC_INITIALIZED) {
+ /* Waiting for on-board buffers to be empty before closing
+ the port */
+ cy_wait_until_sent(tty, info->timeout);
}
-#endif
} else {
#ifdef Z_WAKE
+ /* Waiting for on-board buffers to be empty before closing the port */
unsigned char *base_addr = (unsigned char *)
cy_card[info->card].base_addr;
struct FIRM_ID *firm_id = (struct FIRM_ID *) (base_addr + ID_ADDRESS);
@@ -2693,7 +2697,7 @@
ASYNC_CLOSING);
wake_up_interruptible(&info->close_wait);
-#ifdef SERIAL_DEBUG_OTHER
+#ifdef CY_DEBUG_OTHER
printk(" cyc:cy_close done\n");
#endif
@@ -2722,9 +2726,9 @@
{
struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
unsigned long flags;
- int c, total = 0;
+ int c, ret = 0;
-#ifdef SERIAL_DEBUG_IO
+#ifdef CY_DEBUG_IO
printk("cyc:cy_write ttyC%d\n", info->line); /* */
#endif
@@ -2736,42 +2740,57 @@
return 0;
}
- if (from_user)
- down(&tmp_buf_sem);
save_flags(flags);
- while (1) {
- cli();
- c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
- SERIAL_XMIT_SIZE - info->xmit_head));
- if (c <= 0)
- break;
- if (from_user) {
- copy_from_user(tmp_buf, buf, c);
- c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
- SERIAL_XMIT_SIZE - info->xmit_head));
- memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
- } else
- memcpy(info->xmit_buf + info->xmit_head, buf, c);
- info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
- info->xmit_cnt += c;
- restore_flags(flags);
- buf += c;
- count -= c;
- total += c;
-#if 0
- SP("CW");
- CP16(c);
- SP(" ");
-#endif
- }
- if (from_user)
+ if (from_user) {
+ down(&tmp_buf_sem);
+ while (1) {
+ c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+ SERIAL_XMIT_SIZE - info->xmit_head));
+ if (c <= 0)
+ break;
+
+ c -= copy_from_user(tmp_buf, buf, c);
+ if (!c) {
+ if (!ret) {
+ ret = -EFAULT;
+ }
+ break;
+ }
+ cli();
+ c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+ SERIAL_XMIT_SIZE - info->xmit_head));
+ memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
+ info->xmit_head = ((info->xmit_head + c) & (SERIAL_XMIT_SIZE-1));
+ info->xmit_cnt += c;
+ restore_flags(flags);
+ buf += c;
+ count -= c;
+ ret += c;
+ }
up(&tmp_buf_sem);
+ } else {
+ while (1) {
+ cli();
+ c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+ SERIAL_XMIT_SIZE - info->xmit_head));
+ if (c <= 0) {
+ restore_flags(flags);
+ break;
+ }
+ memcpy(info->xmit_buf + info->xmit_head, buf, c);
+ info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+ info->xmit_cnt += c;
+ restore_flags(flags);
+ buf += c;
+ count -= c;
+ ret += c;
+ }
+ }
if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
start_xmit(info);
}
- restore_flags(flags);
- return total;
+ return ret;
} /* cy_write */
@@ -2788,7 +2807,7 @@
struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
unsigned long flags;
-#ifdef SERIAL_DEBUG_IO
+#ifdef CY_DEBUG_IO
printk("cyc:cy_put_char ttyC%d\n", info->line);
#endif
@@ -2808,9 +2827,6 @@
info->xmit_head &= SERIAL_XMIT_SIZE - 1;
info->xmit_cnt++;
restore_flags(flags);
-#if 0
- SP("+");
-#endif
} /* cy_put_char */
@@ -2826,7 +2842,7 @@
unsigned char *base_addr;
int card,chip,channel,index;
-#ifdef SERIAL_DEBUG_IO
+#ifdef CY_DEBUG_IO
printk("cyc:cy_flush_chars ttyC%d\n", info->line); /* */
#endif
@@ -2871,7 +2887,7 @@
struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
int ret;
-#ifdef SERIAL_DEBUG_IO
+#ifdef CY_DEBUG_IO
printk("cyc:cy_write_room ttyC%d\n", info->line); /* */
#endif
@@ -2897,7 +2913,7 @@
channel = (info->line) - (cy_card[card].first_line);
if (!IS_CYC_Z(cy_card[card])) {
-#ifdef SERIAL_DEBUG_IO
+#ifdef CY_DEBUG_IO
printk("cyc:cy_chars_in_buffer ttyC%d %d\n",
info->line, info->xmit_cnt); /* */
#endif
@@ -2923,7 +2939,7 @@
char_count = tx_put - tx_get;
else
char_count = tx_put - tx_get + tx_bufsize;
-#ifdef SERIAL_DEBUG_IO
+#ifdef CY_DEBUG_IO
printk("cyc:cy_chars_in_buffer ttyC%d %d\n",
info->line, info->xmit_cnt + char_count); /* */
#endif
@@ -2951,6 +2967,7 @@
int card,chip,channel,index;
unsigned cflag, iflag;
unsigned short chip_number;
+ int baud;
int i;
@@ -2972,47 +2989,21 @@
index = cy_card[card].bus_index;
/* baud rate */
- i = cflag & CBAUD;
-
- if (i & CBAUDEX) {
- if (i == B57600)
- i = 16;
-#ifdef B76800
- else if(i == B76800)
- i = 17;
-#endif
- else if(i == B115200)
- i = 18;
- else if(i == B230400 && (info->chip_rev >= CD1400_REV_J)) {
- /* It is a CD1400 rev. J or later */
- i = 20;
+ baud = tty_get_baud_rate(info->tty);
+ if (baud > CD1400_MAX_SPEED) {
+ baud = CD1400_MAX_SPEED;
+ }
+ /* find the baud index */
+ for (i = 0; i < 20; i++) {
+ if (baud == baud_table[i]) {
+ break;
}
- else
- info->tty->termios->c_cflag &= ~CBAUDEX;
}
+ if (i == 20) {
+ i = 19; /* CD1400_MAX_SPEED */
+ }
+
- if (i == 15) {
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- i += 1;
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- i += 3;
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST){
- switch(info->baud) {
- case 57600:
- i += 1; break;
-#ifdef B76800
- case 76800:
- i += 2; break;
-#endif
- case 115200:
- i += 3; break;
- case 230400:
- i += 5; break;
- default:
- break;
- }
- }
- }
if(info->chip_rev >= CD1400_REV_J) {
/* It is a CD1400 rev. J or later */
info->tbpr = baud_bpr_60[i]; /* Tx BPR */
@@ -3026,7 +3017,7 @@
info->rco = baud_co_25[i]; /* Rx CO */
}
if (baud_table[i] == 134) {
- info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2;
+ info->timeout = (info->xmit_fifo_size*HZ*15/269) + 2;
/* get it right for 134.5 baud */
} else if (baud_table[i]) {
info->timeout = (info->xmit_fifo_size*HZ*15/baud_table[i]) + 2;
@@ -3168,7 +3159,7 @@
} else {
cy_writeb((u_long)base_addr+(CyMSVR2<<index), ~CyDTR);
}
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
printk("cyc:set_line_char dropping DTR\n");
printk(" status: 0x%x,
0x%x\n", cy_readb(base_addr+(CyMSVR1<<index)),
@@ -3180,7 +3171,7 @@
} else {
cy_writeb((u_long)base_addr+(CyMSVR2<<index), CyDTR);
}
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
printk("cyc:set_line_char raising DTR\n");
printk(" status: 0x%x, 0x%x\n",
cy_readb(base_addr+(CyMSVR1<<index)),
@@ -3214,49 +3205,17 @@
buf_ctrl = &zfw_ctrl->buf_ctrl[channel];
/* baud rate */
- switch(i = cflag & CBAUD){
- /*
- case B0: cy_writel(&ch_ctrl->comm_baud , 0); break;
- */
- case B50: cy_writel(&ch_ctrl->comm_baud , 50); break;
- case B75: cy_writel(&ch_ctrl->comm_baud , 75); break;
- case B110: cy_writel(&ch_ctrl->comm_baud , 110); break;
- case B134: cy_writel(&ch_ctrl->comm_baud , 134); break;
- case B150: cy_writel(&ch_ctrl->comm_baud , 150); break;
- case B200: cy_writel(&ch_ctrl->comm_baud , 200); break;
- case B300: cy_writel(&ch_ctrl->comm_baud , 300); break;
- case B600: cy_writel(&ch_ctrl->comm_baud , 600); break;
- case B1200: cy_writel(&ch_ctrl->comm_baud , 1200); break;
- case B1800: cy_writel(&ch_ctrl->comm_baud , 1800); break;
- case B2400: cy_writel(&ch_ctrl->comm_baud , 2400); break;
- case B4800: cy_writel(&ch_ctrl->comm_baud , 4800); break;
- case B9600: cy_writel(&ch_ctrl->comm_baud , 9600); break;
- case B19200: cy_writel(&ch_ctrl->comm_baud , 19200); break;
- case B38400:
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI){
- cy_writel(&ch_ctrl->comm_baud , 57600);
- }else if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI){
- cy_writel(&ch_ctrl->comm_baud , 115200);
- }else if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST){
- cy_writel(&ch_ctrl->comm_baud , info->baud);
- }else{
- cy_writel(&ch_ctrl->comm_baud , 38400);
- }
- break;
- case B57600: cy_writel(&ch_ctrl->comm_baud , 57600); break;
-#ifdef B76800
- case B76800: cy_writel(&ch_ctrl->comm_baud , 76800); break;
-#endif
- case B115200: cy_writel(&ch_ctrl->comm_baud , 115200); break;
- case B230400: cy_writel(&ch_ctrl->comm_baud , 230400); break;
- case B460800: cy_writel(&ch_ctrl->comm_baud , 460800); break;
+ baud = tty_get_baud_rate(info->tty);
+ if (baud > CD1400_MAX_SPEED) {
+ baud = CD1400_MAX_SPEED;
}
+ cy_writel(&ch_ctrl->comm_baud , baud);
- if ((i = cy_readl(&ch_ctrl->comm_baud)) == 134) {
+ if (baud == 134) {
info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2;
/* get it right for 134.5 baud */
- } else if (i) {
- info->timeout = (info->xmit_fifo_size*HZ*15/i) + 2;
+ } else if (baud) {
+ info->timeout = (info->xmit_fifo_size*HZ*15/baud) + 2;
/* this needs to be propagated into the card info */
} else {
info->timeout = 0;
@@ -3318,16 +3277,16 @@
cy_readl(&ch_ctrl->sw_flow) & ~C_FL_OXX);
}
- if(i == 0){ /* baud rate is zero, turn off line */
+ if(baud == 0){ /* baud rate is zero, turn off line */
cy_writel(&ch_ctrl->rs_control,
cy_readl(&ch_ctrl->rs_control) & ~C_RS_DTR);
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
printk("cyc:set_line_char dropping Z DTR\n");
#endif
}else{
cy_writel(&ch_ctrl->rs_control,
cy_readl(&ch_ctrl->rs_control) | C_RS_DTR);
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
printk("cyc:set_line_char raising Z DTR\n");
#endif
}
@@ -3343,6 +3302,21 @@
}
}
+ /*
+ * Set up the tty->alt_speed kludge
+ */
+ if (info->tty) {
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+ info->tty->alt_speed = 57600;
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+ info->tty->alt_speed = 115200;
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+ info->tty->alt_speed = 230400;
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+ info->tty->alt_speed = 460800;
+ }
+
+
} /* set_line_char */
@@ -3377,9 +3351,8 @@
struct serial_struct new_serial;
struct cyclades_port old_info;
- if (!new_info)
- return -EFAULT;
- copy_from_user(&new_serial,new_info,sizeof(new_serial));
+ if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
+ return -EFAULT;
old_info = *info;
if (!capable(CAP_SYS_ADMIN)) {
@@ -3405,7 +3378,6 @@
(new_serial.flags & ASYNC_FLAGS));
info->close_delay = new_serial.close_delay * HZ/100;
info->closing_wait = new_serial.closing_wait * HZ/100;
-
check_and_exit:
if (info->flags & ASYNC_INITIALIZED){
@@ -3486,8 +3458,7 @@
}
}
- cy_put_user(result,(unsigned long *) value);
- return 0;
+ return cy_put_user(result,(unsigned long *) value);
} /* get_modem_info */
@@ -3535,7 +3506,7 @@
} else {
cy_writeb((u_long)base_addr+(CyMSVR2<<index), CyDTR);
}
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
printk("cyc:set_modem_info raising DTR\n");
printk(" status: 0x%x, 0x%x\n",
cy_readb(base_addr+(CyMSVR1<<index)),
@@ -3564,7 +3535,7 @@
} else {
cy_writeb((u_long)base_addr+(CyMSVR2<<index), ~CyDTR);
}
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
printk("cyc:set_modem_info dropping DTR\n");
printk(" status: 0x%x, 0x%x\n",
cy_readb(base_addr+(CyMSVR1<<index)),
@@ -3601,7 +3572,7 @@
} else {
cy_writeb((u_long)base_addr+(CyMSVR2<<index), CyDTR);
}
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
printk("cyc:set_modem_info raising DTR\n");
printk(" status: 0x%x, 0x%x\n",
cy_readb(base_addr+(CyMSVR1<<index)),
@@ -3617,7 +3588,7 @@
cy_writeb((u_long)base_addr+(CyMSVR2<<index), ~CyDTR);
}
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
printk("cyc:set_modem_info dropping DTR\n");
printk(" status: 0x%x, 0x%x\n",
cy_readb(base_addr+(CyMSVR1<<index)),
@@ -3649,7 +3620,7 @@
if (arg & TIOCM_DTR){
cy_writel(&ch_ctrl[channel].rs_control,
cy_readl(&ch_ctrl[channel].rs_control) | C_RS_DTR);
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
printk("cyc:set_modem_info raising Z DTR\n");
#endif
}
@@ -3662,7 +3633,7 @@
if (arg & TIOCM_DTR){
cy_writel(&ch_ctrl[channel].rs_control,
cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_DTR);
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
printk("cyc:set_modem_info clearing Z DTR\n");
#endif
}
@@ -3678,13 +3649,13 @@
if (arg & TIOCM_DTR){
cy_writel(&ch_ctrl[channel].rs_control,
cy_readl(&ch_ctrl[channel].rs_control) | C_RS_DTR);
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
printk("cyc:set_modem_info raising Z DTR\n");
#endif
}else{
cy_writel(&ch_ctrl[channel].rs_control,
cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_DTR);
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
printk("cyc:set_modem_info clearing Z DTR\n");
#endif
}
@@ -3705,7 +3676,6 @@
return 0;
} /* set_modem_info */
-
static void
send_break( struct cyclades_port * info, int duration)
{
@@ -3737,7 +3707,6 @@
}
} /* send_break */
-
static int
get_mon_info(struct cyclades_port * info, struct cyclades_monitor * mon)
{
@@ -3796,11 +3765,11 @@
+ (cy_chip_offset[chip]<<index));
tmp = cy_readb(base_addr+(CyCOR3<<index)) & CyREC_FIFO;
- cy_put_user(tmp,value);
+ return cy_put_user(tmp,value);
} else {
// Nothing to do!
+ return 0;
}
- return 0;
}/* get_threshold */
@@ -3815,8 +3784,7 @@
static int
get_default_threshold(struct cyclades_port * info, unsigned long *value)
{
- cy_put_user(info->default_threshold,value);
- return 0;
+ return cy_put_user(info->default_threshold,value);
}/* get_default_threshold */
@@ -3862,11 +3830,11 @@
+ (cy_chip_offset[chip]<<index));
tmp = cy_readb(base_addr+(CyRTPR<<index));
- cy_put_user(tmp,value);
+ return cy_put_user(tmp,value);
} else {
// Nothing to do!
+ return 0;
}
- return 0;
}/* get_timeout */
@@ -3881,8 +3849,7 @@
static int
get_default_timeout(struct cyclades_port * info, unsigned long *value)
{
- cy_put_user(info->default_timeout,value);
- return 0;
+ return cy_put_user(info->default_timeout,value);
}/* get_default_timeout */
/*
@@ -3894,68 +3861,40 @@
cy_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
- int error;
struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
int ret_val = 0;
-#ifdef SERIAL_DEBUG_OTHER
+ if (serial_paranoia_check(info, tty->device, "cy_ioctl"))
+ return -ENODEV;
+
+#ifdef CY_DEBUG_OTHER
printk("cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n",
info->line, cmd, arg); /* */
#endif
switch (cmd) {
case CYGETMON:
- error = verify_area(VERIFY_WRITE, (void *) arg
- ,sizeof(struct cyclades_monitor));
- if (error){
- ret_val = error;
- break;
- }
ret_val = get_mon_info(info, (struct cyclades_monitor *)arg);
break;
case CYGETTHRESH:
- error = verify_area(VERIFY_WRITE, (void *) arg
- ,sizeof(unsigned long));
- if (error){
- ret_val = error;
- break;
- }
ret_val = get_threshold(info, (unsigned long *)arg);
break;
case CYSETTHRESH:
ret_val = set_threshold(info, (unsigned long)arg);
break;
case CYGETDEFTHRESH:
- error = verify_area(VERIFY_WRITE, (void *) arg
- ,sizeof(unsigned long));
- if (error){
- ret_val = error;
- break;
- }
ret_val = get_default_threshold(info, (unsigned long *)arg);
break;
case CYSETDEFTHRESH:
ret_val = set_default_threshold(info, (unsigned long)arg);
break;
case CYGETTIMEOUT:
- error = verify_area(VERIFY_WRITE, (void *) arg
- ,sizeof(unsigned long));
- if (error){
- ret_val = error;
- break;
- }
ret_val = get_timeout(info, (unsigned long *)arg);
break;
case CYSETTIMEOUT:
ret_val = set_timeout(info, (unsigned long)arg);
break;
case CYGETDEFTIMEOUT:
- error = verify_area(VERIFY_WRITE, (void *) arg
- ,sizeof(unsigned long));
- if (error){
- ret_val = error;
- break;
- }
ret_val = get_default_timeout(info, (unsigned long *)arg);
break;
case CYSETDEFTIMEOUT:
@@ -3976,14 +3915,10 @@
ret_val = info->rtsdtr_inv;
break;
case CYGETCARDINFO:
- error = verify_area(VERIFY_WRITE, (void *) arg
- ,sizeof(struct cyclades_card));
- if (error){
- ret_val = error;
- break;
- }
- copy_to_user((void *)arg, (void *)&cy_card[info->card],
- sizeof (struct cyclades_card));
+ if (copy_to_user((void *)arg, (void *)&cy_card[info->card],
+ sizeof (struct cyclades_card))) {
+ ret_val = -EFAULT;
+ }
ret_val = 0;
break;
case CYGETCD1400VER:
@@ -3994,91 +3929,46 @@
ret_val = 0;
break;
case CYSETWAIT:
- info->closing_wait2 = (unsigned short)arg;
+ info->closing_wait = (unsigned short)arg * HZ/100;
ret_val = 0;
break;
case CYGETWAIT:
- ret_val = info->closing_wait2;
+ ret_val = info->closing_wait / (HZ/100);
break;
- case TCSBRK: /* SVID version: non-zero arg --> no break */
- ret_val = tty_check_change(tty);
- if (ret_val)
- return ret_val;
- tty_wait_until_sent(tty,0);
- if (!arg)
- send_break(info, HZ/4); /* 1/4 second */
- break;
- case TCSBRKP: /* support for POSIX tcsendbreak() */
- ret_val = tty_check_change(tty);
- if (ret_val)
- return ret_val;
- tty_wait_until_sent(tty,0);
- send_break(info, arg ? arg*(HZ/10) : HZ/4);
+ case TCSBRK: /* SVID version: non-zero arg --> no break */
+ ret_val = tty_check_change(tty);
+ if (ret_val)
+ return ret_val;
+ tty_wait_until_sent(tty,0);
+ if (!arg)
+ send_break(info, HZ/4); /* 1/4 second */
+ break;
+ case TCSBRKP: /* support for POSIX tcsendbreak() */
+ ret_val = tty_check_change(tty);
+ if (ret_val)
+ return ret_val;
+ tty_wait_until_sent(tty,0);
+ send_break(info, arg ? arg*(HZ/10) : HZ/4);
+ break;
+ case TIOCMGET:
+ ret_val = get_modem_info(info, (unsigned int *) arg);
break;
case TIOCMBIS:
case TIOCMBIC:
case TIOCMSET:
ret_val = set_modem_info(info, cmd, (unsigned int *) arg);
break;
-
-/* The following commands are incompletely implemented!!! */
- case TIOCGSOFTCAR:
- error = verify_area(VERIFY_WRITE, (void *) arg
- ,sizeof(unsigned int *));
- if (error){
- ret_val = error;
- break;
- }
- cy_put_user(C_CLOCAL(tty) ? 1 : 0,
- (unsigned long *) arg);
- break;
- case TIOCSSOFTCAR:
- error = verify_area(VERIFY_READ, (void *) arg
- ,sizeof(unsigned long *));
- if (error) {
- ret_val = error;
- break;
- }
-
- arg = cy_get_user((unsigned long *) arg);
- tty->termios->c_cflag =
- ((tty->termios->c_cflag & ~CLOCAL) |
- (arg ? CLOCAL : 0));
- break;
- case TIOCMGET:
- error = verify_area(VERIFY_WRITE, (void *) arg
- ,sizeof(unsigned int *));
- if (error){
- ret_val = error;
- break;
- }
- ret_val = get_modem_info(info, (unsigned int *) arg);
- break;
case TIOCGSERIAL:
- error = verify_area(VERIFY_WRITE, (void *) arg
- ,sizeof(struct serial_struct));
- if (error){
- ret_val = error;
- break;
- }
- ret_val = get_serial_info(info,
- (struct serial_struct *) arg);
+ ret_val = get_serial_info(info, (struct serial_struct *) arg);
break;
case TIOCSSERIAL:
- error = verify_area(VERIFY_READ, (void *) arg
- ,sizeof(struct serial_struct));
- if (error){
- ret_val = error;
- break;
- }
- ret_val = set_serial_info(info,
- (struct serial_struct *) arg);
+ ret_val = set_serial_info(info, (struct serial_struct *) arg);
break;
default:
ret_val = -ENOIOCTLCMD;
}
-#ifdef SERIAL_DEBUG_OTHER
+#ifdef CY_DEBUG_OTHER
printk(" cyc:cy_ioctl done\n");
#endif
@@ -4097,7 +3987,7 @@
{
struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-#ifdef SERIAL_DEBUG_OTHER
+#ifdef CY_DEBUG_OTHER
printk("cyc:cy_set_termios ttyC%d\n", info->line);
#endif
@@ -4141,7 +4031,7 @@
unsigned char *base_addr;
int card,chip,channel,index;
-#ifdef SERIAL_DEBUG_THROTTLE
+#ifdef CY_DEBUG_THROTTLE
char buf[64];
printk("cyc:throttle %s: %d....ttyC%d\n",
@@ -4197,7 +4087,7 @@
unsigned char *base_addr;
int card,chip,channel,index;
-#ifdef SERIAL_DEBUG_THROTTLE
+#ifdef CY_DEBUG_THROTTLE
char buf[64];
printk("cyc:unthrottle %s: %d....ttyC%d\n",
@@ -4255,7 +4145,7 @@
int chip,channel,index;
unsigned long flags;
-#ifdef SERIAL_DEBUG_OTHER
+#ifdef CY_DEBUG_OTHER
printk("cyc:cy_stop ttyC%d\n", info->line); /* */
#endif
@@ -4295,7 +4185,7 @@
int chip,channel,index;
unsigned long flags;
-#ifdef SERIAL_DEBUG_OTHER
+#ifdef CY_DEBUG_OTHER
printk("cyc:cy_start ttyC%d\n", info->line); /* */
#endif
@@ -4333,7 +4223,7 @@
int card, channel;
unsigned long flags;
-#ifdef SERIAL_DEBUG_IO
+#ifdef CY_DEBUG_IO
printk("cyc:cy_flush_buffer ttyC%d\n", info->line); /* */
#endif
@@ -4377,7 +4267,7 @@
{
struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
-#ifdef SERIAL_DEBUG_OTHER
+#ifdef CY_DEBUG_OTHER
printk("cyc:cy_hangup ttyC%d\n", info->line); /* */
#endif
@@ -4388,7 +4278,7 @@
shutdown(info);
info->event = 0;
info->count = 0;
-#ifdef SERIAL_DEBUG_COUNT
+#ifdef CY_DEBUG_COUNT
printk("cyc:cy_hangup (%d): setting count to 0\n", current->pid);
#endif
info->tty = 0;
@@ -4422,7 +4312,7 @@
for(chip_number=0; chip_number<CyMAX_CHIPS_PER_CARD; chip_number++){
base_addr = true_base_addr
+ (cy_chip_offset[chip_number]<<index);
- udelay(1000L);
+ mdelay(1);
if(cy_readb(base_addr+(CyCCR<<index)) != 0x00){
/*************
printk(" chip #%d at %#6lx is never idle (CCR != 0)\n",
@@ -4448,7 +4338,7 @@
}
cy_writeb((u_long)base_addr+(CyCCR<<index), CyCHIP_RESET);
- udelay(1000L);
+ mdelay(1);
if(cy_readb(base_addr+(CyGFRCR<<index)) == 0x00){
/*
@@ -4593,88 +4483,45 @@
{
#ifdef CONFIG_PCI
-#ifdef NEW_PCI
struct pci_dev *pdev = NULL;
unsigned char cyy_rev_id;
-#else
- unsigned char cyy_bus, cyy_dev_fn, cyy_rev_id;
-#endif
unsigned long pci_intr_ctrl;
- unsigned char cy_pci_irq;
+ unsigned char cy_pci_irq = 0;
uclong cy_pci_addr0, cy_pci_addr1, cy_pci_addr2;
unsigned short i,j,cy_pci_nchan;
unsigned short device_id,dev_index = 0;
-#ifndef NEW_PCI
- unsigned short board_index = 0;
-#endif
uclong mailbox;
uclong Ze_addr0[NR_CARDS], Ze_addr2[NR_CARDS], ZeIndex = 0;
-#ifdef NEW_PCI
if(pci_present() == 0) { /* PCI bus not present */
-#else
- if(pcibios_present() == 0) { /* PCI bus not present */
-#endif
return(0);
}
for (i = 0; i < NR_CARDS; i++) {
/* look for a Cyclades card by vendor and device id */
while((device_id = cy_pci_dev_id[dev_index]) != 0) {
-#ifdef NEW_PCI
if((pdev = pci_find_device(PCI_VENDOR_ID_CYCLADES,
device_id, pdev)) == NULL) {
dev_index++; /* try next device id */
} else {
break; /* found a board */
}
-#else
- if(pcibios_find_device(PCI_VENDOR_ID_CYCLADES,
- device_id,board_index,
- &cyy_bus, &cyy_dev_fn) != 0) {
- dev_index++; /* try next device id */
- board_index = 0;
- } else {
- board_index++;
- break; /* found a board */
- }
-#endif
}
if (device_id == 0)
break;
/* read PCI configuration area */
-#ifdef NEW_PCI
cy_pci_irq = pdev->irq;
cy_pci_addr0 = pdev->base_address[0];
cy_pci_addr1 = pdev->base_address[1];
cy_pci_addr2 = pdev->base_address[2];
pci_read_config_byte(pdev, PCI_REVISION_ID, &cyy_rev_id);
-#else
- pcibios_read_config_byte(cyy_bus, cyy_dev_fn,
- PCI_INTERRUPT_LINE, &cy_pci_irq);
- pcibios_read_config_dword(cyy_bus, cyy_dev_fn,
- PCI_BASE_ADDRESS_0,
- (unsigned int *) &cy_pci_addr0);
- pcibios_read_config_dword(cyy_bus, cyy_dev_fn,
- PCI_BASE_ADDRESS_1,
- (unsigned int *) &cy_pci_addr1);
- pcibios_read_config_dword(cyy_bus, cyy_dev_fn,
- PCI_BASE_ADDRESS_2,
- (unsigned int *) &cy_pci_addr2);
- pcibios_read_config_byte(cyy_bus, cyy_dev_fn,
- PCI_REVISION_ID, &cyy_rev_id);
-#endif
if ((device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo)
|| (device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi)){
#ifdef CY_PCI_DEBUG
printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ",
-#ifdef NEW_PCI
pdev->bus->number, pdev->devfn);
-#else
- cyy_bus, cyy_dev_fn);
-#endif
printk("rev_id=%d) IRQ%d\n",
cyy_rev_id, (int)cy_pci_irq);
printk("Cyclom-Y/PCI:found winaddr=0x%lx ioaddr=0x%lx\n",
@@ -4686,11 +4533,7 @@
#if defined(__alpha__)
if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */
printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ",
-#ifdef NEW_PCI
pdev->bus->number, pdev->devfn);
-#else
- cyy_bus, cyy_dev_fn);
-#endif
printk("rev_id=%d) IRQ%d\n",
cyy_rev_id, (int)cy_pci_irq);
printk("Cyclom-Y/PCI:found winaddr=0x%lx ioaddr=0x%lx\n",
@@ -4775,11 +4618,7 @@
}else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo){
/* print message */
printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ",
-#ifdef NEW_PCI
pdev->bus->number, pdev->devfn);
-#else
- cyy_bus, cyy_dev_fn);
-#endif
printk("rev_id=%d) IRQ%d\n",
cyy_rev_id, (int)cy_pci_irq);
printk("Cyclades-Z/PCI: found winaddr=0x%lx ctladdr=0x%lx\n",
@@ -4789,11 +4628,7 @@
}else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi){
#ifdef CY_PCI_DEBUG
printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ",
-#ifdef NEW_PCI
pdev->bus->number, pdev->devfn);
-#else
- cyy_bus, cyy_dev_fn);
-#endif
printk("rev_id=%d) IRQ%d\n",
cyy_rev_id, (int)cy_pci_irq);
printk("Cyclades-Z/PCI: found winaddr=0x%lx ctladdr=0x%lx\n",
@@ -5077,6 +4912,7 @@
memset(&cy_serial_driver, 0, sizeof(struct tty_driver));
cy_serial_driver.magic = TTY_DRIVER_MAGIC;
+ cy_serial_driver.name = "cyclades";
cy_serial_driver.name = "ttyC";
cy_serial_driver.major = CYCLADES_MAJOR;
cy_serial_driver.minor_start = 0;
@@ -5106,6 +4942,7 @@
cy_serial_driver.stop = cy_stop;
cy_serial_driver.start = cy_start;
cy_serial_driver.hangup = cy_hangup;
+ cy_serial_driver.wait_until_sent = cy_wait_until_sent;
/*
* The callout device is just like normal device except for
@@ -5115,6 +4952,9 @@
cy_callout_driver.name = "cub";
cy_callout_driver.major = CYCLADESAUX_MAJOR;
cy_callout_driver.subtype = SERIAL_TYPE_CALLOUT;
+ cy_callout_driver.read_proc = 0;
+ cy_callout_driver.proc_entry = 0;
+
if (tty_register_driver(&cy_serial_driver))
panic("Couldn't register Cyclades serial driver\n");
@@ -5123,7 +4963,7 @@
init_bh(CYCLADES_BH, do_cyclades_bh);
- for (i = 0; i < 16; i++) {
+ for (i = 0; i < NR_IRQS; i++) {
IRQ_cards[i] = 0;
}
@@ -5199,11 +5039,10 @@
info->rco = 0;
info->close_delay = 5*HZ/10;
info->closing_wait = CLOSING_WAIT_DELAY;
- info->closing_wait2 = 0;
info->x_char = 0;
info->event = 0;
info->count = 0;
-#ifdef SERIAL_DEBUG_COUNT
+#ifdef CY_DEBUG_COUNT
// printk("cyc:cy_init(1) setting Z count to 0\n");
#endif
info->blocked_open = 0;
@@ -5250,7 +5089,6 @@
info->cor5 = 0;
info->close_delay = 5*HZ/10;
info->closing_wait = CLOSING_WAIT_DELAY;
- info->closing_wait2 = 0;
chip_number = (port - cinfo->first_line) / 4;
if ((info->chip_rev = cy_readb(cinfo->base_addr +
(cy_chip_offset[chip_number]<<index) +
@@ -5273,7 +5111,7 @@
info->x_char = 0;
info->event = 0;
info->count = 0;
-#ifdef SERIAL_DEBUG_COUNT
+#ifdef CY_DEBUG_COUNT
// printk("cyc:cy_init(2) setting Y count to 0\n");
#endif
info->blocked_open = 0;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov