Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
[safe/jmp/linux-2.6] / drivers / char / cyclades.c
index cf2874a..9824b41 100644 (file)
@@ -79,6 +79,7 @@
 #include <linux/bitops.h>
 #include <linux/firmware.h>
 #include <linux/device.h>
+#include <linux/slab.h>
 
 #include <linux/io.h>
 #include <linux/uaccess.h>
@@ -158,13 +159,11 @@ static unsigned int cy_isa_addresses[] = {
 
 #define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses)
 
-#ifdef MODULE
 static long maddr[NR_CARDS];
 static int irq[NR_CARDS];
 
 module_param_array(maddr, long, NULL, 0);
 module_param_array(irq, int, NULL, 0);
-#endif
 
 #endif                         /* CONFIG_ISA */
 
@@ -598,12 +597,6 @@ static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
        save_car = readb(base_addr + (CyCAR << index));
        cy_writeb(base_addr + (CyCAR << index), save_xir);
 
-       /* validate the port# (as configured and open) */
-       if (channel + chip * 4 >= cinfo->nports) {
-               cy_writeb(base_addr + (CySRER << index),
-                         readb(base_addr + (CySRER << index)) & ~CyTxRdy);
-               goto end;
-       }
        info = &cinfo->ports[channel + chip * 4];
        tty = tty_port_tty_get(&info->port);
        if (tty == NULL) {
@@ -729,7 +722,7 @@ static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
                if (mdm_change & CyRI)
                        info->icount.rng++;
 
-               wake_up_interruptible(&info->delta_msr_wait);
+               wake_up_interruptible(&info->port.delta_msr_wait);
        }
 
        if ((mdm_change & CyDCD) && (info->port.flags & ASYNC_CHECK_CD)) {
@@ -1197,7 +1190,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
                        break;
                }
                if (delta_count)
-                       wake_up_interruptible(&info->delta_msr_wait);
+                       wake_up_interruptible(&info->port.delta_msr_wait);
                if (special_count)
                        tty_schedule_flip(tty);
                tty_kref_put(tty);
@@ -1464,7 +1457,7 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
                spin_lock_irqsave(&card->card_lock, flags);
 
                /* Clear delta_msr_wait queue to avoid mem leaks. */
-               wake_up_interruptible(&info->delta_msr_wait);
+               wake_up_interruptible(&info->port.delta_msr_wait);
 
                if (info->port.xmit_buf) {
                        unsigned char *temp;
@@ -1750,24 +1743,15 @@ static void cy_flush_buffer(struct tty_struct *tty)
 }                              /* cy_flush_buffer */
 
 
-/*
- * This routine is called when a particular tty device is closed.
- */
-static void cy_close(struct tty_struct *tty, struct file *filp)
+static void cy_do_close(struct tty_port *port)
 {
-       struct cyclades_port *info = tty->driver_data;
+       struct cyclades_port *info = container_of(port, struct cyclades_port,
+                                                               port);
        struct cyclades_card *card;
        unsigned long flags;
        int channel;
 
-       if (!info || serial_paranoia_check(info, tty->name, "cy_close"))
-               return;
-
        card = info->card;
-
-       if (!tty_port_close_start(&info->port, tty, filp))
-               return;
-
        channel = info->line - card->first_line;
        spin_lock_irqsave(&card->card_lock, flags);
 
@@ -1779,7 +1763,7 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
                        /* Waiting for on-board buffers to be empty before
                           closing the port */
                        spin_unlock_irqrestore(&card->card_lock, flags);
-                       cy_wait_until_sent(tty, info->timeout);
+                       cy_wait_until_sent(port->tty, info->timeout);
                        spin_lock_irqsave(&card->card_lock, flags);
                }
        } else {
@@ -1801,14 +1785,19 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
                }
 #endif
        }
-
        spin_unlock_irqrestore(&card->card_lock, flags);
-       cy_shutdown(info, tty);
-       cy_flush_buffer(tty);
-
-       tty_port_tty_set(&info->port, NULL);
+       cy_shutdown(info, port->tty);
+}
 
-       tty_port_close_end(&info->port, tty);
+/*
+ * This routine is called when a particular tty device is closed.
+ */
+static void cy_close(struct tty_struct *tty, struct file *filp)
+{
+       struct cyclades_port *info = tty->driver_data;
+       if (!info || serial_paranoia_check(info, tty->name, "cy_close"))
+               return;
+       tty_port_close(&info->port, tty, filp);
 }                              /* cy_close */
 
 /* This routine gets called when tty_write has put something into
@@ -2057,6 +2046,8 @@ static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty)
        channel = info->line - card->first_line;
 
        if (!cy_is_Z(card)) {
+               u32 cflags;
+
                /* baud rate */
                baud = tty_get_baud_rate(tty);
                if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
@@ -2198,37 +2189,18 @@ static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty)
                        (info->default_timeout ? info->default_timeout : 0x02));
                /* 10ms rx timeout */
 
-               if (C_CLOCAL(tty)) {
-                       /* without modem intr */
-                       cyy_writeb(info, CySRER,
-                                       cyy_readb(info, CySRER) | CyMdmCh);
-                       /* act on 1->0 modem transitions */
-                       if ((cflag & CRTSCTS) && info->rflow) {
-                               cyy_writeb(info, CyMCOR1,
-                                         (CyCTS | rflow_thr[i]));
-                       } else {
-                               cyy_writeb(info, CyMCOR1,
-                                         CyCTS);
-                       }
-                       /* act on 0->1 modem transitions */
-                       cyy_writeb(info, CyMCOR2, CyCTS);
-               } else {
-                       /* without modem intr */
-                       cyy_writeb(info, CySRER,
-                                       cyy_readb(info, CySRER) | CyMdmCh);
-                       /* act on 1->0 modem transitions */
-                       if ((cflag & CRTSCTS) && info->rflow) {
-                               cyy_writeb(info, CyMCOR1,
-                                         (CyDSR | CyCTS | CyRI | CyDCD |
-                                          rflow_thr[i]));
-                       } else {
-                               cyy_writeb(info, CyMCOR1,
-                                               CyDSR | CyCTS | CyRI | CyDCD);
-                       }
-                       /* act on 0->1 modem transitions */
-                       cyy_writeb(info, CyMCOR2,
-                                       CyDSR | CyCTS | CyRI | CyDCD);
-               }
+               cflags = CyCTS;
+               if (!C_CLOCAL(tty))
+                       cflags |= CyDSR | CyRI | CyDCD;
+               /* without modem intr */
+               cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyMdmCh);
+               /* act on 1->0 modem transitions */
+               if ((cflag & CRTSCTS) && info->rflow)
+                       cyy_writeb(info, CyMCOR1, cflags | rflow_thr[i]);
+               else
+                       cyy_writeb(info, CyMCOR1, cflags);
+               /* act on 0->1 modem transitions */
+               cyy_writeb(info, CyMCOR2, cflags);
 
                if (i == 0)     /* baud rate is zero, turn off line */
                        cyy_change_rts_dtr(info, 0, TIOCM_DTR);
@@ -2809,7 +2781,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
                /* note the counters on entry */
                cnow = info->icount;
                spin_unlock_irqrestore(&info->card->card_lock, flags);
-               ret_val = wait_event_interruptible(info->delta_msr_wait,
+               ret_val = wait_event_interruptible(info->port.delta_msr_wait,
                                cy_cflags_changed(info, arg, &cnow));
                break;
 
@@ -3130,11 +3102,13 @@ static void cyz_dtr_rts(struct tty_port *port, int raise)
 static const struct tty_port_operations cyy_port_ops = {
        .carrier_raised = cyy_carrier_raised,
        .dtr_rts = cyy_dtr_rts,
+       .shutdown = cy_do_close,
 };
 
 static const struct tty_port_operations cyz_port_ops = {
        .carrier_raised = cyz_carrier_raised,
        .dtr_rts = cyz_dtr_rts,
+       .shutdown = cy_do_close,
 };
 
 /*
@@ -3172,7 +3146,6 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo)
                info->port.close_delay = 5 * HZ / 10;
                info->port.flags = STD_COM_FLAGS;
                init_completion(&info->shutdown_wait);
-               init_waitqueue_head(&info->delta_msr_wait);
 
                if (cy_is_Z(cinfo)) {
                        struct FIRM_ID *firm_id = cinfo->base_addr + ID_ADDRESS;
@@ -3336,13 +3309,10 @@ static int __init cy_detect_isa(void)
        unsigned short cy_isa_irq, nboard;
        void __iomem *cy_isa_address;
        unsigned short i, j, cy_isa_nchan;
-#ifdef MODULE
        int isparam = 0;
-#endif
 
        nboard = 0;
 
-#ifdef MODULE
        /* Check for module parameters */
        for (i = 0; i < NR_CARDS; i++) {
                if (maddr[i] || i) {
@@ -3352,7 +3322,6 @@ static int __init cy_detect_isa(void)
                if (!maddr[i])
                        break;
        }
-#endif
 
        /* scan the address table probing for Cyclom-Y/ISA boards */
        for (i = 0; i < NR_ISA_ADDRS; i++) {
@@ -3373,11 +3342,10 @@ static int __init cy_detect_isa(void)
                        iounmap(cy_isa_address);
                        continue;
                }
-#ifdef MODULE
-               if (isparam && irq[i])
+
+               if (isparam && i < NR_CARDS && irq[i])
                        cy_isa_irq = irq[i];
                else
-#endif
                        /* find out the board's irq by probing */
                        cy_isa_irq = detect_isa_irq(cy_isa_address);
                if (cy_isa_irq == 0) {
@@ -4228,3 +4196,4 @@ module_exit(cy_cleanup_module);
 MODULE_LICENSE("GPL");
 MODULE_VERSION(CY_VERSION);
 MODULE_ALIAS_CHARDEV_MAJOR(CYCLADES_MAJOR);
+MODULE_FIRMWARE("cyzfirm.bin");