8253xtty.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:70k
- /* -*- linux-c -*- */
- /* $Id: 8253xtty.c,v 1.23 2002/02/10 22:17:25 martillo Exp $
- * sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC.
- *
- * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
- *
- * Modified by Francois Wautier 2000 (fw@auroratech.com)
- *
- * Extended extensively by Joachim Martillo 2001 (Telford002@aol.com)
- * to provide synchronous/asynchronous TTY/Callout/character/network device
- * capabilities.
- *
- * Modifications and extensions
- * Copyright (C) 2001 By Joachim Martillo, Telford Tools, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
- /* Standard in kernel modules */
- #define DEFINE_VARIABLE
- #include <linux/module.h> /* Specifically, a module */
- #include <asm/io.h>
- #include <linux/timer.h>
- #include <linux/interrupt.h>
- #include <linux/tty.h>
- #include <linux/tty_flip.h>
- #include <linux/mm.h>
- #include <linux/version.h>
- #include <asm/uaccess.h>
- #include <linux/pci.h>
- #include "8253xctl.h"
- #include "sp502.h"
- DECLARE_TASK_QUEUE(tq_8253x_serial); /* this just initializes a list head called */
- /* tq_8253x_serial*/
- struct tty_driver sab8253x_serial_driver, sab8253x_callout_driver, sync_sab8253x_serial_driver;
- int sab8253x_refcount;
- /* Trace things on serial device, useful for console debugging: */
- #undef SERIAL_LOG_DEVICE
- #ifdef SERIAL_LOG_DEVICE
- static void dprint_init(int tty);
- #endif
- static void sab8253x_change_speed(struct sab_port *port);
- static struct tty_struct **sab8253x_tableASY = 0; /* make dynamic */
- static struct tty_struct **sab8253x_tableCUA = 0; /* make dynamic */
- static struct tty_struct **sab8253x_tableSYN = 0; /* make dynamic */
- static struct termios **sab8253x_termios = 0 ;
- static struct termios **sab8253x_termios_locked = 0;
- #ifdef MODULE
- #undef XCONFIG_SERIAL_CONSOLE /* leaving out CONFIG_SERIAL_CONSOLE for now */
- #endif
- #ifdef XCONFIG_SERIAL_CONSOLE /* not really implemented yet */
- extern int serial_console;
- struct console sab8253x_console;
- int sab8253x_console_init(void);
- #endif
- #ifndef MIN
- #define MIN(a,b) ((a) < (b) ? (a) : (b))
- #endif
- char sab8253x_serial_version[16];
- static void sab8253x_flush_to_ldisc(void *private_)
- {
- struct tty_struct *tty = (struct tty_struct *) private_;
- unsigned char *cp;
- char *fp;
- int count;
- struct sab_port *port;
- struct sk_buff *skb;
-
- if(tty)
- {
- port = (struct sab_port *)tty->driver_data; /* probably a silly check */
- }
- else
- {
- return;
- }
-
- if(!port)
- {
- return;
- }
-
- if (test_bit(TTY_DONT_FLIP, &tty->flags))
- {
- queue_task(&tty->flip.tqueue, &tq_timer);
- return;
- }
- /* note that a hangup may have occurred -- perhaps should check for that */
- port->DoingInterrupt = 1;
- while(port->sab8253xc_rcvbuflist && (skb_queue_len(port->sab8253xc_rcvbuflist) > 0))
- {
- skb = skb_dequeue(port->sab8253xc_rcvbuflist);
- count = skb->data_len;
- cp = skb->data;
- fp = skb->data + (count/2);
- (*tty->ldisc.receive_buf)(tty, cp, fp, count/2);
- dev_kfree_skb_any(skb);
- }
- port->DoingInterrupt = 0;
- }
- /* only used asynchronously */
- static void inline sab8253x_tec_wait(struct sab_port *port)
- {
- int count = port->tec_timeout;
-
- while((READB(port, star) & SAB82532_STAR_TEC) && --count)
- {
- udelay(1);
- }
- }
- void sab8253x_start_tx(struct sab_port *port)
- {
- unsigned long flags;
- register int count;
- register int total;
- register int offset;
- char temporary[32];
- register unsigned int slopspace;
- register int sendsize;
- unsigned int totaltransmit;
- unsigned fifospace;
- unsigned loadedcount;
- struct tty_struct *tty = port->tty;
-
- fifospace = port->xmit_fifo_size;
- loadedcount = 0;
-
- if(port->sabnext2.transmit == NULL)
- {
- return;
- }
-
- save_flags(flags);
- cli();
-
-
- while(count = port->sabnext2.transmit->Count, (count & OWNER) == OWN_SAB)
- {
- count &= ~OWN_SAB; /* OWN_SAB is really 0 but cannot guarantee in the future */
-
- if(port->sabnext2.transmit->HostVaddr)
- {
- total = (port->sabnext2.transmit->HostVaddr->tail -
- port->sabnext2.transmit->HostVaddr->data); /* packet size */
- }
- else
- {
- total = 0; /* the data is only in the crc/trailer */
- }
-
- if(tty && (tty->stopped || tty->hw_stopped))
- { /* works for frame that only has a trailer (crc) */
- port->interrupt_mask1 |= SAB82532_IMR1_XPR;
- WRITEB(port, imr1, port->interrupt_mask1);
- restore_flags(flags); /* can't send */
- return;
- }
-
- offset = (total - count); /* offset to data still to send */
-
- port->interrupt_mask1 &= ~(SAB82532_IMR1_ALLS);
- WRITEB(port, imr1, port->interrupt_mask1);
- port->all_sent = 0;
-
-
- if(READB(port,star) & SAB82532_STAR_XFW)
- {
- if(count <= fifospace)
- {
- port->xmit_cnt = count;
- slopspace = 0;
- sendsize = 0;
- if(port->sabnext2.transmit->sendcrc)
- /* obviously should not happen for async but might use for
- priority transmission */
- {
- slopspace = fifospace - count;
- }
- if(slopspace)
- {
- if(count)
- {
- memcpy(temporary, &port->sabnext2.transmit->HostVaddr->data[offset],
- count);
- }
- sendsize = MIN(slopspace, (4 - port->sabnext2.transmit->crcindex));
- /* how many bytes to send */
- memcpy(&temporary[count],
- &((unsigned char*)(&port->sabnext2.transmit->crc))
- [port->sabnext2.transmit->crcindex],
- sendsize);
- port->sabnext2.transmit->crcindex += sendsize;
- if(port->sabnext2.transmit->crcindex >= 4)
- {
- port->sabnext2.transmit->sendcrc = 0;
- }
- port->xmit_buf = temporary;
- }
- else
- {
- port->xmit_buf = /* set up wrifefifo variables */
- &port->sabnext2.transmit->HostVaddr->data[offset];
- }
- port->xmit_cnt += sendsize;
- count = 0;
- }
- else
- {
- count -= fifospace;
- port->xmit_cnt = fifospace;
- port->xmit_buf = /* set up wrifefifo variables */
- &port->sabnext2.transmit->HostVaddr->data[offset];
-
- }
- port->xmit_tail= 0;
- loadedcount = port->xmit_cnt;
- (*port->writefifo)(port);
- totaltransmit = Sab8253xCountTransmitDescriptors(port);
- if((sab8253xt_listsize - totaltransmit) > 2)
- {
- sab8253x_sched_event(port, SAB8253X_EVENT_WRITE_WAKEUP);
- }
-
- if((sab8253xt_listsize - totaltransmit) > (sab8253xt_listsize/2))
- {
- port->buffergreedy = 0;
- }
- else
- {
- port->buffergreedy = 1;
- }
-
- port->xmit_buf = NULL; /* this var is used to indicate whether to call kfree */
-
- fifospace -= loadedcount;
-
- if ((count <= 0) && (port->sabnext2.transmit->sendcrc == 0))
- {
- port->sabnext2.transmit->Count = OWN_DRIVER;
- #ifdef FREEININTERRUPT /* treat this routine as if taking place in interrupt */
- if(port->sabnext2.transmit->HostVaddr)
- {
- skb_unlink(port->sabnext2.transmit->HostVaddr);
- dev_kfree_skb_any(port->sabnext2.transmit->HostVaddr);
- port->sabnext2.transmit->HostVaddr = 0; /* no skb */
- }
- port->sabnext2.transmit->crcindex = 0; /* no single byte */
- #endif
- port->sabnext2.transmit = port->sabnext2.transmit->VNext;
- if((port->sabnext2.transmit->Count & OWNER) == OWN_SAB)
- {
- if(fifospace > 0)
- {
- continue; /* the only place where this code really loops */
- }
- if(fifospace < 0)
- {
- printk(KERN_ALERT "sab8253x: bad math in interrupt handler.n");
- }
- port->interrupt_mask1 &= ~(SAB82532_IMR1_XPR);
- WRITEB(port, imr1, port->interrupt_mask1);
- }
- else
- {
- port->interrupt_mask1 |= SAB82532_IMR1_XPR;
- WRITEB(port, imr1, port->interrupt_mask1);
- }
- sab8253x_cec_wait(port);
- /* Issue a Transmit Frame command. */
- WRITEB(port, cmdr, SAB82532_CMDR_XF);
- /* This could be optimized to load from next skbuff */
- /* SAB82532_CMDR_XF is the same as SAB82532_CMDR_XTF */
- restore_flags(flags);
- return;
- }
- sab8253x_cec_wait(port);
- /* Issue a Transmit Frame command. */
- WRITEB(port, cmdr, SAB82532_CMDR_XF); /* same as SAB82532_CMDR_XTF */
- port->sabnext2.transmit->Count = (count|OWN_SAB);
- }
- port->interrupt_mask1 &= ~(SAB82532_IMR1_XPR);
- WRITEB(port, imr1, port->interrupt_mask1);
- restore_flags(flags);
- return;
- }
- /* The While loop only exits via return*/
- /* we get here by skipping the loop */
- port->interrupt_mask1 |= SAB82532_IMR1_XPR;
- WRITEB(port, imr1, port->interrupt_mask1);
- restore_flags(flags);
- return;
- }
- /*
- * ------------------------------------------------------------
- * sab8253x_stop() and sab8253x_start()
- *
- * This routines are called before setting or resetting tty->stopped.
- * They enable or disable transmitter interrupts, as necessary.
- * ------------------------------------------------------------
- */
- static void sab8253x_stop(struct tty_struct *tty)
- {
- struct sab_port *port = (struct sab_port *)tty->driver_data;
- unsigned long flags;
-
- if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_stop"))
- {
- return;
- }
-
- save_flags(flags);
- cli(); /* maybe should turn off ALLS as well
- but the stop flags are checked
- so ALLS is probably harmless
- and I have seen too much evil
- associated with that interrupt*/
- port->interrupt_mask1 |= SAB82532_IMR1_XPR;
- WRITEB(port, imr1, port->interrupt_mask1);
- restore_flags(flags);
- }
- static void sab8253x_start(struct tty_struct *tty)
- {
- struct sab_port *port = (struct sab_port *)tty->driver_data;
-
-
- if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_start"))
- {
- return;
- }
-
- sab8253x_start_tx(port);
- }
- /*
- * This routine is used by the interrupt handler to schedule
- * processing in the software interrupt portion of the driver.
- */
- /* no obvious changes for sync tty */
- static void sab8253x_receive_chars(struct sab_port *port,
- union sab8253x_irq_status *stat)
- {
- struct tty_struct *tty = port->tty;
- unsigned char buf[32];
- unsigned char reordered[32];
- unsigned char status;
- int free_fifo = 0;
- int i, count = 0;
- struct sk_buff *skb;
-
- /* Read number of BYTES (Character + Status) available. */
- if (stat->images[ISR0_IDX] & SAB82532_ISR0_RPF)
- {
- count = port->recv_fifo_size;
- free_fifo++;
- }
-
- if (stat->images[ISR0_IDX] & SAB82532_ISR0_TCD)
- {
- count = READB(port,rbcl) & (port->recv_fifo_size - 1);
- free_fifo++;
- }
-
- /* Issue a FIFO read command in case we where idle. */
- if (stat->sreg.isr0 & SAB82532_ISR0_TIME)
- {
- sab8253x_cec_wait(port);
- WRITEB(port, cmdr, SAB82532_CMDR_RFRD);
- }
-
- if (stat->images[ISR0_IDX] & SAB82532_ISR0_RFO)
- { /* FIFO overflow */
- free_fifo++;
- }
-
- /* Read the FIFO. */
- (*port->readfifo)(port, buf, count);
-
- /* Issue Receive Message Complete command. */
- if (free_fifo)
- {
- sab8253x_cec_wait(port);
- WRITEB(port, cmdr, SAB82532_CMDR_RMC);
- }
-
- #ifdef CONSOLE_SUPPORT
- if (port->is_console)
- {
- wake_up(&keypress_wait);
- }
- #endif
- if (!tty)
- {
- return;
- }
-
- if(!count)
- {
- return;
- }
-
- for(i = 0; i < count; i += 2)
- {
- reordered[i/2] = buf[i];
- status = buf[i+1];
- if (status & SAB82532_RSTAT_PE)
- {
- status = TTY_PARITY;
- port->icount.parity++;
- }
- else if (status & SAB82532_RSTAT_FE)
- {
- status = TTY_FRAME;
- port->icount.frame++;
- }
- else
- {
- status = TTY_NORMAL;
- }
- reordered[(count+i)/2] = status;
- }
-
- if(port->active2.receive == NULL)
- {
- return;
- }
-
- memcpy(port->active2.receive->HostVaddr->tail, reordered, count);
- port->active2.receive->HostVaddr->tail += count;
- port->active2.receive->HostVaddr->data_len = count;
- port->active2.receive->HostVaddr->len = count;
- if(skb = dev_alloc_skb(port->recv_fifo_size), skb == NULL) /* use dev_alloc_skb because at int
- there is header space but so what*/
- {
- port->icount.buf_overrun++;
- port->active2.receive->HostVaddr->tail = port->active2.receive->HostVaddr->data; /* clear the buffer */
- port->active2.receive->Count = (port->recv_fifo_size|OWN_SAB);
- port->active2.receive->HostVaddr->data_len = 0;
- port->active2.receive->HostVaddr->len = 0;
- }
- else
- {
- skb_unlink(port->active2.receive->HostVaddr);
- skb_queue_tail(port->sab8253xc_rcvbuflist, port->active2.receive->HostVaddr);
- skb_queue_head(port->sab8253xbuflist, skb);
- port->active2.receive->HostVaddr = skb;
- port->active2.receive->Count = (port->recv_fifo_size|OWN_SAB);
- }
- queue_task(&tty->flip.tqueue, &tq_timer);
- }
- static void sab8253x_transmit_chars(struct sab_port *port,
- union sab8253x_irq_status *stat)
- {
-
- if (stat->sreg.isr1 & SAB82532_ISR1_ALLS) /* got an all sent int? */
- {
- port->interrupt_mask1 |= SAB82532_IMR1_ALLS;
- WRITEB(port, imr1, port->interrupt_mask1);
- port->all_sent = 1; /* not much else to do */
- } /* a very weird chip -- this int only indicates this int */
-
- sab8253x_start_tx(port);
- }
- static void sab8253x_check_status(struct sab_port *port,
- union sab8253x_irq_status *stat)
- {
- struct tty_struct *tty = port->tty;
- int modem_change = 0;
- mctlsig_t *sig;
- struct sk_buff *skb;
-
- if (!tty)
- {
- return;
- }
-
- if(port->active2.receive == NULL)
- {
- goto check_modem;
- }
-
- if (stat->images[ISR1_IDX] & SAB82532_ISR1_BRK)
- {
- #ifdef XCONFIG_SERIAL_CONSOLE
- if (port->is_console)
- {
- batten_down_hatches(info); /* need to add this function */
- return;
- }
- #endif
-
- port->active2.receive->HostVaddr->tail[0] = 0;
- port->active2.receive->HostVaddr->tail[1] = TTY_PARITY;
- port->active2.receive->HostVaddr->tail += 2;
- port->active2.receive->HostVaddr->data_len = 2;
- port->active2.receive->HostVaddr->len = 2;
-
- if(skb = dev_alloc_skb(port->recv_fifo_size), skb == NULL)
- {
- port->icount.buf_overrun++;
- port->active2.receive->HostVaddr->tail = port->active2.receive->HostVaddr->data;
- /* clear the buffer */
- port->active2.receive->Count = (port->recv_fifo_size|OWN_SAB);
- port->active2.receive->HostVaddr->data_len = 0;
- port->active2.receive->HostVaddr->len = 0;
- }
- else
- {
- skb_unlink(port->active2.receive->HostVaddr);
- skb_queue_tail(port->sab8253xc_rcvbuflist, port->active2.receive->HostVaddr);
- skb_queue_head(port->sab8253xbuflist, skb);
- port->active2.receive->HostVaddr = skb;
- port->active2.receive->Count = (port->recv_fifo_size|OWN_SAB);
- }
- queue_task(&tty->flip.tqueue, &tq_timer);
- port->icount.brk++;
- }
-
- if (stat->images[ISR0_IDX] & SAB82532_ISR0_RFO)
- {
- port->active2.receive->HostVaddr->tail[0] = 0;
- port->active2.receive->HostVaddr->tail[1] = TTY_PARITY;
- port->active2.receive->HostVaddr->tail += 2;
- port->active2.receive->HostVaddr->data_len = 2;
- port->active2.receive->HostVaddr->len = 2;
- if(skb = dev_alloc_skb(port->recv_fifo_size), skb == NULL)
- {
- port->icount.buf_overrun++;
- port->active2.receive->HostVaddr->tail = port->active2.receive->HostVaddr->data;
- /* clear the buffer */
- port->active2.receive->Count = (port->recv_fifo_size|OWN_SAB);
- port->active2.receive->HostVaddr->data_len = 0;
- port->active2.receive->HostVaddr->len = 0;
- }
- else
- {
- skb_unlink(port->active2.receive->HostVaddr);
- skb_queue_tail(port->sab8253xc_rcvbuflist, port->active2.receive->HostVaddr);
- skb_queue_head(port->sab8253xbuflist, skb);
- port->active2.receive->HostVaddr = skb;
- port->active2.receive->Count = (port->recv_fifo_size|OWN_SAB);
- }
- queue_task(&tty->flip.tqueue, &tq_timer);
- port->icount.overrun++;
- }
-
- check_modem:
- /* Checking DCD */
- sig = &port->dcd;
- if (stat->images[sig->irq] & sig->irqmask)
- {
- sig->val = ISON(port,dcd);
- port->icount.dcd++;
- modem_change++;
- }
- /* Checking CTS */
- sig = &port->cts;
- if (stat->images[sig->irq] & sig->irqmask)
- {
- sig->val = ISON(port,cts);
- port->icount.cts++;
- modem_change++;
- }
- /* Checking DSR */
- sig = &port->dsr;
- if (stat->images[sig->irq] & sig->irqmask)
- {
- sig->val = ISON(port,dsr);
- port->icount.dsr++;
- modem_change++;
- }
- if (modem_change)
- {
- wake_up_interruptible(&port->delta_msr_wait); /* incase kernel proc level was waiting on modem change */
- }
-
- sig = &port->dcd;
- if ((port->flags & FLAG8253X_CHECK_CD) &&
- (stat->images[sig->irq] & sig->irqmask))
- {
-
- if (sig->val)
- {
- wake_up_interruptible(&port->open_wait); /* in case waiting in block_til_ready */
- }
- else if (!((port->flags & FLAG8253X_CALLOUT_ACTIVE) &&
- (port->flags & FLAG8253X_CALLOUT_NOHUP)))
- {
-
- MOD_INC_USE_COUNT; /* in case a close is already in progress
- don't want structures to vanish during
- late processing of hangup */
- if (schedule_task(&port->tqueue_hangup) == 0)
- {
- MOD_DEC_USE_COUNT; /* task schedule failed */
- }
- }
- }
-
- sig = &port->cts;
- if (port->flags & FLAG8253X_CTS_FLOW)
- {
- if (port->tty->hw_stopped)
- {
- if (sig->val)
- {
-
- port->tty->hw_stopped = 0;
- sab8253x_sched_event(port, SAB8253X_EVENT_WRITE_WAKEUP);
- sab8253x_start_tx(port);
- }
- }
- else
- {
- if (!(sig->val))
- {
- port->tty->hw_stopped = 1;
- }
- }
- }
- }
- /*
- * This routine is used to handle the "bottom half" processing for the
- * serial driver, known also the "software interrupt" processing.
- * This processing is done at the kernel interrupt level, after the
- * sab8253x_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This
- * is where time-consuming activities which can not be done in the
- * interrupt driver proper are done; the interrupt driver schedules
- * them using sab8253x_sched_event(), and they get done here.
- */
- /* The following routine is installed */
- /* in the bottom half -- just search */
- /* for the init_bh() call */
- /* The logic: sab8253x_sched_event() */
- /* enqueues the tqueue port entry on */
- /* the tq_8253x_serial task list -- */
- /* whenever the bottom half is run */
- /* sab8253x_do_softint is invoked for */
- /* every port that has invoked the bottom */
- /* half via sab8253x_sched_event(). */
- /* currently only a write wakeevent */
- /* wakeup is scheduled -- to tell the */
- /* tty driver to send more chars */
- /* down to the serial driver.*/
- static void sab8253x_do_serial_bh(void)
- {
- run_task_queue(&tq_8253x_serial);
- }
- /* I believe the reason for the */
- /* bottom half processing below is */
- /* the length of time needed to transfer */
- /* characters to the TTY driver. */
- static void sab8253x_do_softint(void *private_)
- {
- struct sab_port *port = (struct sab_port *)private_;
- struct tty_struct *tty;
-
- tty = port->tty;
- if (!tty)
- {
- return;
- }
-
- port->DoingInterrupt = 1;
- if (test_and_clear_bit(SAB8253X_EVENT_WRITE_WAKEUP, &port->event))
- {
- if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
- tty->ldisc.write_wakeup)
- (tty->ldisc.write_wakeup)(tty);
- wake_up_interruptible(&tty->write_wait); /* in case tty driver waiting on write */
- }
- port->DoingInterrupt = 0;
- }
- /*
- * This routine is called from the scheduler tqueue when the interrupt
- * routine has signalled that a hangup has occurred. The path of
- * hangup processing is:
- *
- * serial interrupt routine -> (scheduler tqueue) ->
- * do_serial_hangup() -> tty->hangup() -> sab8253x_hangup()
- *
- */
- /* This logic takes place at kernel */
- /* process context through the scheduler*/
- /* schedule_task(tqueue_hangup) */
- /* takes place in the interrupt handler*/
- static void sab8253x_do_serial_hangup(void *private_)
- {
- struct sab_port *port = (struct sab_port *) private_;
- struct tty_struct *tty;
-
- tty = port->tty;
- if (tty)
- {
- tty_hangup(tty);
- }
- MOD_DEC_USE_COUNT; /* in case busy waiting to unload module */
- }
- static void
- sab8253x_init_line(struct sab_port *port)
- {
- unsigned char stat;
- if(port->chip->c_cim)
- {
- if(port->chip->c_cim->ci_type == CIM_SP502)
- {
- aura_sp502_program(port, SP502_OFF_MODE);
- }
- }
-
- /*
- * Wait for any commands or immediate characters
- */
- sab8253x_cec_wait(port);
- sab8253x_tec_wait(port);
-
- /*
- * Clear the FIFO buffers.
- */
-
- WRITEB(port, cmdr, SAB82532_CMDR_RRES);
- sab8253x_cec_wait(port);
- WRITEB(port, cmdr, SAB82532_CMDR_XRES);
-
-
- /*
- * Clear the interrupt registers.
- */
- stat = READB(port, isr0);
- stat = READB(port, isr1);
-
- /*
- * Now, initialize the UART
- */
- WRITEB(port, ccr0, 0); /* power-down */
- WRITEB(port, ccr0,
- SAB82532_CCR0_MCE | SAB82532_CCR0_SC_NRZ | SAB82532_CCR0_SM_ASYNC);
- WRITEB(port, ccr1,
- SAB82532_CCR1_ODS | SAB82532_CCR1_BCR | 7);
- WRITEB(port, ccr2,
- SAB82532_CCR2_BDF | SAB82532_CCR2_SSEL | SAB82532_CCR2_TOE);
- WRITEB(port, ccr3, 0);
- WRITEB(port, ccr4,
- SAB82532_CCR4_MCK4 | SAB82532_CCR4_EBRG);
- WRITEB(port, mode,
- SAB82532_MODE_RTS | SAB82532_MODE_FCTS | SAB82532_MODE_RAC);
- WRITEB(port, rfc,
- SAB82532_RFC_DPS | SAB82532_RFC_RFDF);
- switch (port->recv_fifo_size)
- {
- case 1:
- SET_REG_BIT(port,rfc,SAB82532_RFC_RFTH_1);
- break;
- case 4:
- SET_REG_BIT(port,rfc,SAB82532_RFC_RFTH_4);
- break;
- case 16:
- SET_REG_BIT(port,rfc,SAB82532_RFC_RFTH_16);
- break;
- default:
- port->recv_fifo_size = 32;
- case 32:
- SET_REG_BIT(port,rfc,SAB82532_RFC_RFTH_32);
- break;
- }
- /* power-up */
- SET_REG_BIT(port, ccr0, SAB82532_CCR0_PU);
- if(port->chip->c_cim)
- {
- if(port->chip->c_cim->ci_type == CIM_SP502)
- {
- aura_sp502_program(port, port->sigmode);
- }
- }
- }
- static int sab8253x_startup(struct sab_port *port)
- {
- unsigned long flags;
-
- int retval = 0;
-
- save_flags(flags); cli();
-
- if (port->flags & FLAG8253X_INITIALIZED)
- {
- goto errout;
- }
-
- port->msgbufindex = 0;
- port->xmit_buf = NULL;
- port->buffergreedy = 0;
-
- if (!port->regs)
- {
- if (port->tty)
- {
- set_bit(TTY_IO_ERROR, &port->tty->flags);
- }
- retval = -ENODEV;
- goto errout;
- }
-
- /*
- * Initialize the Hardware
- */
- sab8253x_init_line(port);
-
- if (port->tty->termios->c_cflag & CBAUD)
- {
- /* Activate RTS */
- RAISE(port,rts);
-
- /* Activate DTR */
- RAISE(port,dtr);
- }
-
- /*
- * Initialize the modem signals values
- */
- port->dcd.val=ISON(port,dcd);
- port->cts.val=ISON(port,cts);
- port->dsr.val=ISON(port,dsr);
-
- /*
- * Finally, enable interrupts
- */
-
- port->interrupt_mask0 = SAB82532_IMR0_PERR | SAB82532_IMR0_FERR |
- SAB82532_IMR0_PLLA;
- WRITEB(port, imr0, port->interrupt_mask0);
- port->interrupt_mask1 = SAB82532_IMR1_BRKT | SAB82532_IMR1_XOFF |
- SAB82532_IMR1_TIN | SAB82532_IMR1_XON |
- SAB82532_IMR1_XPR;
- WRITEB(port, imr1, port->interrupt_mask1);
- port->all_sent = 1;
-
- if (port->tty)
- {
- clear_bit(TTY_IO_ERROR, &port->tty->flags);
- }
- port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-
- /*
- * and set the speed of the serial port
- */
- sab8253x_change_speed(port);
-
- port->flags |= FLAG8253X_INITIALIZED;
- port->receive_chars = sab8253x_receive_chars;
- port->transmit_chars = sab8253x_transmit_chars;
- port->check_status = sab8253x_check_status;
- port->receive_test = (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME |
- SAB82532_ISR0_RFO | SAB82532_ISR0_RPF);
- port->transmit_test = (SAB82532_ISR1_ALLS | SAB82532_ISR1_XPR);
- port->check_status_test = SAB82532_ISR1_BRK;
-
- restore_flags(flags);
- return 0;
-
- errout:
- restore_flags(flags);
- return retval;
- }
- /*
- * This routine will shutdown a serial port; interrupts are disabled, and
- * DTR is dropped if the hangup on close termio flag is on.
- */
- static void sab8253x_shutdown(struct sab_port *port)
- {
- unsigned long flags;
-
- if (!(port->flags & FLAG8253X_INITIALIZED))
- {
- return;
- }
-
- save_flags(flags);
- cli(); /* Disable interrupts */
-
- /*
- * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
- * here so the queue might never be waken up
- */
- wake_up_interruptible(&port->delta_msr_wait); /* shutting down port modem status is pointless */
-
- if (port->xmit_buf)
- {
- port->xmit_buf = NULL;
- }
-
- #ifdef XCONFIG_SERIAL_CONSOLE
- if (port->is_console)
- {
- port->interrupt_mask0 =
- SAB82532_IMR0_PERR | SAB82532_IMR0_FERR |
- /*SAB82532_IMR0_TIME |*/
- SAB82532_IMR0_PLLA | SAB82532_IMR0_CDSC;
- WRITEB(port,imr0,port->interrupt_mask0);
- port->interrupt_mask1 =
- SAB82532_IMR1_BRKT | SAB82532_IMR1_ALLS |
- SAB82532_IMR1_XOFF | SAB82532_IMR1_TIN |
- SAB82532_IMR1_CSC | SAB82532_IMR1_XON |
- SAB82532_IMR1_XPR;
- WRITEB(port,imr1,port->interrupt_mask1);
- if (port->tty)
- {
- set_bit(TTY_IO_ERROR, &port->tty->flags);
- }
- port->flags &= ~FLAG8253X_INITIALIZED;
- restore_flags(flags);
- return;
- }
- #endif
-
- /* Disable Interrupts */
-
- port->interrupt_mask0 = 0xff;
- WRITEB(port, imr0, port->interrupt_mask0);
- port->interrupt_mask1 = 0xff;
- WRITEB(port, imr1, port->interrupt_mask1);
-
- if (!port->tty || (port->tty->termios->c_cflag & HUPCL))
- {
- LOWER(port,rts);
- LOWER(port,dtr);
- }
-
- /* Disable break condition */
- CLEAR_REG_BIT(port,dafo,SAB82532_DAFO_XBRK);
-
- /* Disable Receiver */
- CLEAR_REG_BIT(port,mode,SAB82532_MODE_RAC);
-
- /* Power Down */
- CLEAR_REG_BIT(port,ccr0,SAB82532_CCR0_PU);
-
- if (port->tty)
- {
- set_bit(TTY_IO_ERROR, &port->tty->flags);
- }
-
- port->flags &= ~FLAG8253X_INITIALIZED;
- restore_flags(flags);
- }
- /*
- * This routine is called to set the UART divisor registers to match
- * the specified baud rate for a serial port.
- */
- static void sab8253x_change_speed(struct sab_port *port)
- {
- unsigned long flags,baud;
- tcflag_t cflag;
- u8 dafo,ccr2=0,ccr4=0,ebrg=0,mode;
- int i, bits;
- #ifdef DEBUGGING
- printk("Change speed! ");
- #endif
- if (!port->tty || !port->tty->termios)
- {
- #ifdef DEBUGGING
- printk("NOT!n");
- #endif
- return;
- }
-
- #ifdef DEBUGGING
- printk(" for real.n");
- #endif
-
- cflag = port->tty->termios->c_cflag;
-
- /* Byte size and parity */
- switch (cflag & CSIZE)
- {
- case CS5:
- dafo = SAB82532_DAFO_CHL5;
- bits = 7;
- break;
- case CS6:
- dafo = SAB82532_DAFO_CHL6;
- bits = 8;
- break;
- case CS7:
- dafo = SAB82532_DAFO_CHL7;
- bits = 9;
- break;
- default:
- case CS8:
- dafo = SAB82532_DAFO_CHL8;
- bits = 10;
- break;
- }
-
- if (cflag & CSTOPB)
- {
- dafo |= SAB82532_DAFO_STOP;
- bits++;
- }
-
- if (cflag & PARENB)
- {
- dafo |= SAB82532_DAFO_PARE;
- bits++;
- }
-
- if (cflag & PARODD)
- {
- #ifdef CMSPAR
- if (cflag & CMSPAR)
- dafo |= SAB82532_DAFO_PAR_MARK;
- else
- #endif
- dafo |= SAB82532_DAFO_PAR_ODD;
- }
- else
- {
- #ifdef CMSPAR
- if (cflag & CMSPAR)
- dafo |= SAB82532_DAFO_PAR_SPACE;
- else
- #endif
- dafo |= SAB82532_DAFO_PAR_EVEN;
- }
-
- /* Determine EBRG values based on the "encoded"baud rate */
- i = cflag & CBAUD;
- switch(i)
- {
- case B0:
- baud=0;
- break;
- case B50:
- baud=100;
- break;
- case B75:
- baud=150;
- break;
- case B110:
- baud=220;
- break;
- case B134:
- baud=269;
- break;
- case B150:
- baud=300;
- break;
- case B200:
- baud=400;
- break;
- case B300:
- baud=600;
- break;
- case B600:
- baud=1200;
- break;
- case B1200:
- baud=2400;
- break;
- case B1800:
- baud=3600;
- break;
- case B2400:
- baud=4800;
- break;
- case B4800:
- baud=9600;
- break;
- case B9600:
- baud=19200;
- break;
- case B19200:
- baud=38400;
- break;
- case B38400:
- if(port->custspeed)
- {
- baud=port->custspeed<<1;
- }
- else
- {
- baud=76800;
- }
- break;
- case B57600:
- baud=115200;
- break;
- #ifdef SKIPTHIS
- case B76800:
- baud=153600;
- break;
- case B153600:
- baud=307200;
- break;
- #endif
- case B230400:
- baud=460800;
- break;
- case B460800:
- baud=921600;
- break;
- case B115200:
- default:
- baud=230400;
- break;
- }
-
- if(!sab8253x_baud(port,baud,&ebrg,&ccr2,&ccr4,&(port->baud)))
- {
- printk("Aurora Warning. baudrate %ld could not be set! Using 115200",baud);
- baud=230400;
- sab8253x_baud(port,baud,&ebrg,&ccr2,&ccr4,&(port->baud));
- }
-
- if (port->baud)
- port->timeout = (port->xmit_fifo_size * HZ * bits) / port->baud;
- else
- port->timeout = 0;
- port->timeout += HZ / 50; /* Add .02 seconds of slop */
-
- /* CTS flow control flags */
- if (cflag & CRTSCTS)
- port->flags |= FLAG8253X_CTS_FLOW;
- else
- port->flags &= ~(FLAG8253X_CTS_FLOW);
-
- if (cflag & CLOCAL)
- port->flags &= ~(FLAG8253X_CHECK_CD);
- else
- port->flags |= FLAG8253X_CHECK_CD;
- if (port->tty)
- port->tty->hw_stopped = 0;
-
- /*
- * Set up parity check flag
- * XXX: not implemented, yet.
- */
- #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
- /*
- * Characters to ignore
- * XXX: not implemented, yet.
- */
-
- /*
- * !!! ignore all characters if CREAD is not set
- * XXX: not implemented, yet.
- */
- if ((cflag & CREAD) == 0)
- port->ignore_status_mask |= SAB82532_ISR0_RPF |
- /* SAB82532_ISR0_TIME |*/
- SAB82532_ISR0_TCD ;
-
- save_flags(flags);
- cli();
- sab8253x_cec_wait(port);
- sab8253x_tec_wait(port);
- WRITEB(port,dafo,dafo);
- WRITEB(port,bgr,ebrg);
- ccr2 |= READB(port,ccr2) & ~(0xc0);
- WRITEB(port,ccr2,ccr2);
- ccr4 |= READB(port,ccr4) & ~(SAB82532_CCR4_EBRG);
- WRITEB(port,ccr4,ccr4);
-
- if (port->flags & FLAG8253X_CTS_FLOW)
- {
- mode = READB(port,mode) & ~(SAB82532_MODE_RTS);
- mode |= SAB82532_MODE_FRTS;
- mode &= ~(SAB82532_MODE_FCTS);
- }
- else
- {
- mode = READB(port,mode) & ~(SAB82532_MODE_FRTS);
- mode |= SAB82532_MODE_RTS;
- mode |= SAB82532_MODE_FCTS;
- }
- WRITEB(port,mode,mode);
- mode |= SAB82532_MODE_RAC;
- WRITEB(port,mode,mode);
- restore_flags(flags);
- }
- static void sab8253x_flush_chars(struct tty_struct *tty)
- {
- struct sab_port *port = (struct sab_port *)tty->driver_data;
-
- if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_flush_chars"))
- {
- return;
- }
-
- if ((Sab8253xCountTransmit(port) <= 0) || tty->stopped || tty->hw_stopped)
- {
- return;
- }
-
- sab8253x_start_tx(port);
- }
- static int sab8253x_write(struct tty_struct * tty, int from_user,
- const unsigned char *buf, int count)
- {
- struct sab_port *port = (struct sab_port *)tty->driver_data;
- struct sk_buff *skb = NULL;
- int truelength = 0;
- int do_queue = 1;
-
- if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_write"))
- {
- return 0;
- }
-
- if(count == 0)
- {
- return 0;
- }
-
- if(port->active2.transmit == NULL)
- {
- return 0;
- }
-
- if((port->active2.transmit->Count & OWNER) == OWN_SAB)
- {
- sab8253x_start_tx(port);
- return 0;
- }
-
- #ifndef FREEININTERRUPT
- skb = port->active2.transmit->HostVaddr; /* current slot value */
-
- if(port->buffergreedy == 0) /* are we avoiding buffer free's */
- { /* no */
- if((skb != NULL) || /* not OWN_SAB from above */
- (port->active2.transmit->crcindex != 0))
- {
- register RING_DESCRIPTOR *freeme;
-
- freeme = port->active2.transmit;
- do
- {
- if((freeme->crcindex == 0) && (freeme->HostVaddr == NULL))
- {
- break;
- }
- if(freeme->HostVaddr)
- {
- skb_unlink((struct sk_buff*)freeme->HostVaddr);
- dev_kfree_skb_any((struct sk_buff*)freeme->HostVaddr);
- freeme->HostVaddr = NULL;
- }
- freeme->sendcrc = 0;
- freeme->crcindex = 0;
- freeme = (RING_DESCRIPTOR*) freeme->VNext;
- }
- while((freeme->Count & OWNER) != OWN_SAB);
- }
- skb = NULL; /* buffer was freed */
- }
-
- if(skb != NULL) /* potentially useful */
- {
- truelength = (skb->end - skb->head);
- if(truelength >= count)
- {
- skb->data = skb->head; /* this buffer is already queued */
- skb->tail = skb->head;
- do_queue = 0;
- }
- else
- {
- skb_unlink(skb);
- dev_kfree_skb_any(skb);
- skb = NULL;
- port->active2.transmit->HostVaddr = NULL;
- }
- }
- /* in all cases the following is allowed */
- port->active2.transmit->sendcrc = 0;
- port->active2.transmit->crcindex = 0;
- #endif
-
- if(skb == NULL)
- {
- if(port->DoingInterrupt)
- {
- skb = alloc_skb(count, GFP_ATOMIC);
- }
- else
- {
- skb = alloc_skb(count, GFP_KERNEL);
- }
- }
-
- if(skb == NULL)
- {
- printk(KERN_ALERT "sab8253xt: no skbuffs available.n");
- return 0;
- }
- if(from_user)
- {
- copy_from_user(skb->data, buf, count);
- }
- else
- {
- memcpy(skb->data, buf, count);
- }
- skb->tail = (skb->data + count);
- skb->data_len = count;
- skb->len = count;
-
- if(do_queue)
- {
- skb_queue_head(port->sab8253xbuflist, skb);
- }
-
- port->active2.transmit->HostVaddr = skb;
- port->active2.transmit->sendcrc = 0;
- port->active2.transmit->crcindex = 0;
- port->active2.transmit->Count = (OWN_SAB|count);
- port->active2.transmit = port->active2.transmit->VNext;
-
- sab8253x_start_tx(port);
- return count;
- }
- static int sab8253x_write_room(struct tty_struct *tty)
- {
- struct sab_port *port = (struct sab_port *)tty->driver_data;
-
- if(sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_write_room"))
- {
- return 0;
- }
-
- if(port->active2.transmit == NULL)
- {
- return 0;
- }
-
- if((port->active2.transmit->Count & OWNER) == OWN_SAB)
- {
- return 0;
- }
- return ((sab8253xt_rbufsize) * /* really should not send buffs bigger than 32 I guess */
- (sab8253xt_listsize -
- Sab8253xCountTransmitDescriptors(port)));
- }
- static int sab8253x_chars_in_buffer(struct tty_struct *tty)
- {
- struct sab_port *port = (struct sab_port *)tty->driver_data;
-
- if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_chars_in_bufferS"))
- {
- return 0;
- }
-
- return Sab8253xCountTransmit(port);
- }
- /*
- * This function is used to send a high-priority XON/XOFF character to
- * the device
- */
- static void sab8253x_send_xchar(struct tty_struct *tty, char ch)
- {
- struct sab_port *port = (struct sab_port *)tty->driver_data;
- unsigned long flags;
-
- if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_send_xchar"))
- {
- return;
- }
-
- save_flags(flags);
- cli();
- sab8253x_tec_wait(port);
- WRITEB(port, tic, ch);
- restore_flags(flags);
- }
- /*
- * ------------------------------------------------------------
- * sab8253x_throttle()
- *
- * This routine is called by the upper-layer tty layer to signal that
- * incoming characters should be throttled.
- * ------------------------------------------------------------
- */
- static void sab8253x_throttle(struct tty_struct * tty)
- {
- struct sab_port *port = (struct sab_port *)tty->driver_data;
-
- if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_throttle"))
- {
- return;
- }
-
- if (I_IXOFF(tty))
- {
- sab8253x_send_xchar(tty, STOP_CHAR(tty));
- }
- }
- static void sab8253x_unthrottle(struct tty_struct * tty)
- {
- struct sab_port *port = (struct sab_port *)tty->driver_data;
-
- if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_unthrottle"))
- {
- return;
- }
-
- if (I_IXOFF(tty))
- {
- if (port->x_char)
- {
- port->x_char = 0;
- }
- else
- {
- sab8253x_send_xchar(tty, START_CHAR(tty));
- }
- }
- }
- /*
- * ------------------------------------------------------------
- * sab8253x_ioctl() and friends
- * ------------------------------------------------------------
- */
- static int sab8253x_get_serial_info(struct sab_port *port,
- struct serial_struct *retinfo)
- {
- struct serial_struct tmp;
-
- if (!retinfo)
- {
- return -EFAULT;
- }
- memset(&tmp, 0, sizeof(tmp));
- tmp.type = port->type;
- tmp.line = port->line;
- tmp.port = (unsigned long)port->regs;
- tmp.irq = port->irq;
- tmp.flags = port->flags;
- tmp.xmit_fifo_size = port->xmit_fifo_size;
- tmp.baud_base = 0;
- tmp.close_delay = port->close_delay;
- tmp.closing_wait = port->closing_wait;
- tmp.custom_divisor = port->custom_divisor;
- tmp.hub6 = 0;
- if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
- {
- return -EFAULT;
- }
- return 0;
- }
- static int sab8253x_set_serial_info(struct sab_port *port,
- struct serial_struct *new_info)
- {
- return 0;
- }
- /*
- * get_lsr_info - get line status register info
- *
- * Purpose: Let user call ioctl() to get info when the UART physically
- * is emptied. On bus types like RS485, the transmitter must
- * release the bus after transmitting. This must be done when
- * the transmit shift register is empty, not be done when the
- * transmit holding register is empty. This functionality
- * allows an RS485 driver to be written in user space.
- */
- static int sab8253x_get_lsr_info(struct sab_port * port, unsigned int *value)
- {
- unsigned int result;
-
- result = (((Sab8253xCountTransmit(port) <= 0) && port->all_sent) ? TIOCSER_TEMT : 0);
- return put_user(result, value);
- }
- static int sab8253x_get_modem_info(struct sab_port * port, unsigned int *value)
- {
- unsigned int result;
-
- /* Using the cached values !! After all when changed int occurs
- and the cache is updated */
- result=
- ((port->dtr.val) ? TIOCM_DTR : 0)
- | ((port->rts.val) ? TIOCM_RTS : 0)
- | ((port->cts.val) ? TIOCM_CTS : 0)
- | ((port->dsr.val) ? TIOCM_DSR : 0)
- | ((port->dcd.val) ? TIOCM_CAR : 0);
-
- return put_user(result,value);
- }
- static int sab8253x_set_modem_info(struct sab_port * port, unsigned int cmd,
- unsigned int *value)
- {
- int error;
- unsigned int arg;
- unsigned long flags;
-
- error = get_user(arg, value);
- if (error)
- {
- return error;
- }
-
- save_flags(flags);
- cli();
- switch (cmd)
- {
- case TIOCMBIS:
- if (arg & TIOCM_RTS)
- {
- RAISE(port, rts);
- }
- if (arg & TIOCM_DTR)
- {
- RAISE(port, dtr);
- }
- break;
- case TIOCMBIC:
- if (arg & TIOCM_RTS)
- {
- LOWER(port,rts);
- }
- if (arg & TIOCM_DTR)
- {
- LOWER(port,dtr);
- }
- break;
- case TIOCMSET:
- if (arg & TIOCM_RTS)
- {
- RAISE(port, rts);
- }
- else
- {
- LOWER(port,rts);
- }
- if (arg & TIOCM_DTR)
- {
- RAISE(port, dtr);
- }
- else
- {
- LOWER(port,dtr);
- }
- break;
- default:
- restore_flags(flags);
- return -EINVAL;
- }
- restore_flags(flags);
- return 0;
- }
- /*
- * This routine sends a break character out the serial port.
- */
- static void sab8253x_break(struct tty_struct *tty, int break_state)
- {
- struct sab_port *port = (struct sab_port *)tty->driver_data;
- unsigned long flags;
-
- if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_break"))
- {
- return;
- }
-
- if (!port->regs)
- {
- return;
- }
-
- save_flags(flags);
- cli();
- if (break_state == -1)
- {
- SET_REG_BIT(port,dafo,SAB82532_DAFO_XBRK);
- }
- else
- {
- CLEAR_REG_BIT(port,dafo,SAB82532_DAFO_XBRK);
- }
- restore_flags(flags);
- }
- static int sab8253x_ioctl(struct tty_struct *tty, struct file * file,
- unsigned int cmd, unsigned long arg)
- {
- int error;
- unsigned int wordindex;
- unsigned short *wordptr;
- struct sab_port *port = (struct sab_port *)tty->driver_data;
- struct async_icount cprev, cnow; /* kernel counter temps */
- struct serial_icounter_struct *p_cuser; /* user space */
- SAB_BOARD *bptr;
- unsigned long flags;
-
- if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_ioctl"))
- {
- return -ENODEV;
- }
-
- if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
- (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) &&
- (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT) &&
- (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT))
- {
- if (tty->flags & (1 << TTY_IO_ERROR))
- {
- return -EIO;
- }
- }
-
- switch (cmd)
- {
- case ATIS_IOCSPARAMS:
- copy_from_user(&port->ccontrol, (struct channelcontrol*)arg , sizeof(struct channelcontrol));
- break;
- case ATIS_IOCGPARAMS:
- copy_to_user((struct channelcontrol*) arg, &port->ccontrol, sizeof(struct channelcontrol));
- break;
-
- case ATIS_IOCSSPEED:
- copy_from_user(&port->custspeed, (unsigned long*)arg , sizeof(unsigned long));
- break;
- case ATIS_IOCGSPEED:
- copy_to_user((unsigned long*) arg, &port->custspeed, sizeof(unsigned long));
- break;
-
- case ATIS_IOCSSEP9050:
- bptr = port->board;
- if(bptr->b_type == BD_WANMCS)
- {
- return -EINVAL;
- }
- copy_from_user((unsigned char*) bptr->b_eprom, (unsigned char*) arg , sizeof(struct sep9050));
-
- wordptr = (unsigned short*) bptr->b_eprom;
- plx9050_eprom_cmd(&((PLX9050*)(bptr->virtbaseaddress0))->ctrl,
- NM93_WENCMD, NM93_WENADDR, 0);
- for(wordindex = 0; wordindex < EPROM9050_SIZE; ++wordindex)
- {
- plx9050_eprom_cmd(&((PLX9050*)(bptr->virtbaseaddress0))->ctrl,
- NM93_WRITECMD,
- wordindex, wordptr[wordindex]);
- }
- plx9050_eprom_cmd(&((PLX9050*)(bptr->virtbaseaddress0))->ctrl,
- NM93_WDSCMD, NM93_WDSADDR, 0);
- break;
- case ATIS_IOCGSEP9050:
- bptr = port->board;
- if(bptr->b_type == BD_WANMCS)
- {
- return -EINVAL;
- }
- if (!plx9050_eprom_read(&((PLX9050*)(bptr->virtbaseaddress0))->ctrl,
- (unsigned short*) bptr->b_eprom,
- (unsigned char) 0, EPROM9050_SIZE))
- {
- printk(KERN_ALERT "auraXX20n: Could not read serial eprom.n");
- return -EIO;
- }
- copy_to_user((unsigned char*) arg, (unsigned char*) bptr->b_eprom, sizeof(struct sep9050));
- break;
-
- case TIOCGSOFTCAR:
- return put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg);
-
- case TIOCSSOFTCAR:
- error = get_user(arg, (unsigned int *) arg);
- if (error)
- {
- return error;
- }
- tty->termios->c_cflag =
- ((tty->termios->c_cflag & ~CLOCAL) |
- (arg ? CLOCAL : 0));
- return 0;
- case TIOCMGET:
- return sab8253x_get_modem_info(port, (unsigned int *) arg);
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- return sab8253x_set_modem_info(port, cmd, (unsigned int *) arg);
- case TIOCGSERIAL:
- return sab8253x_get_serial_info(port,
- (struct serial_struct *) arg);
- case TIOCSSERIAL:
- return sab8253x_set_serial_info(port,
- (struct serial_struct *) arg);
-
- case TIOCSERGETLSR: /* Get line status register */
- return sab8253x_get_lsr_info(port, (unsigned int *) arg);
-
- case TIOCSERGSTRUCT:
- if (copy_to_user((struct sab_port *) arg,
- port, sizeof(struct sab_port)))
- return -EFAULT;
- return 0;
-
- /*
- * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
- * - mask passed in arg for lines of interest
- * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
- * Caller should use TIOCGICOUNT to see which one it was
- */
- case TIOCMIWAIT:
- save_flags(flags);
- cli();
- /* note the counters on entry */
- cprev = port->icount;
- restore_flags(flags);
- while (1)
- {
- interruptible_sleep_on(&port->delta_msr_wait); /* waits for a modem signal change */
- /* see if a signal did it */
- if (signal_pending(current))
- {
- return -ERESTARTSYS;
- }
- save_flags(flags);
- cli();
- cnow = port->icount; /* atomic copy */
- restore_flags(flags);
- if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
- cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
- {
- return -EIO; /* no change => error */
- }
- if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
- ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
- ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
- {
- return 0;
- }
- }
- cprev = cnow;
- }
- /* NOTREACHED */
- break;
-
- /*
- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
- * Return: write counters to the user passed counter struct
- * NB: both 1->0 and 0->1 transitions are counted except for
- * RI where only 0->1 is counted.
- */
- case TIOCGICOUNT:
- save_flags(flags);
- cli();
- cnow = port->icount;
- restore_flags(flags);
- p_cuser = (struct serial_icounter_struct *) arg;
- error = put_user(cnow.cts, &p_cuser->cts);
- if (error)
- {
- return error;
- }
- error = put_user(cnow.dsr, &p_cuser->dsr);
- if (error)
- {
- return error;
- }
- error = put_user(cnow.rng, &p_cuser->rng);
- if (error)
- {
- return error;
- }
- error = put_user(cnow.dcd, &p_cuser->dcd);
- if (error)
- {
- return error;
- }
- return 0;
-
- case ATIS_IOCSSIGMODE:
- if(port->chip->c_cim)
- {
- if(port->chip->c_cim->ci_type == CIM_SP502)
- {
- copy_from_user(&port->sigmode, (unsigned int*)arg , sizeof(unsigned int));
- return 0;
- }
- }
- return -EINVAL;
- case ATIS_IOCGSIGMODE:
- if(port->chip->c_cim)
- {
- if(port->chip->c_cim->ci_type == CIM_SP502)
- {
- copy_to_user((unsigned int*) arg, &port->sigmode, sizeof(unsigned int));
- return 0;
- }
- }
- return -EINVAL;
- default:
- return -ENOIOCTLCMD;
- }
- return 0;
- }
- static void sab8253x_set_termios(struct tty_struct *tty,
- struct termios *old_termios)
- {
- struct sab_port *port = (struct sab_port *)tty->driver_data;
-
- if((tty->termios->c_cflag == old_termios->c_cflag) &&
- (RELEVANT_IFLAG(tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag)))
- {
- return;
- }
- if(!port)
- {
- return;
- }
- sab8253x_change_speed(port);
-
- /* Handle transition to B0 status */
- if ((old_termios->c_cflag & CBAUD) &&
- !(tty->termios->c_cflag & CBAUD))
- {
- LOWER(port,rts);
- LOWER(port,dtr);
- }
-
- /* Handle transition away from B0 status */
- if (!(old_termios->c_cflag & CBAUD) &&
- (tty->termios->c_cflag & CBAUD))
- {
- RAISE(port, dtr);
- if (!tty->hw_stopped ||
- !(tty->termios->c_cflag & CRTSCTS))
- {
- RAISE(port, rts);
- }
- }
-
- /* Handle turning off CRTSCTS */
- if ((old_termios->c_cflag & CRTSCTS) &&
- !(tty->termios->c_cflag & CRTSCTS))
- {
- tty->hw_stopped = 0;
- sab8253x_start(tty);
- }
- }
- /*
- * ------------------------------------------------------------
- * sab8253x_close()
- *
- * This routine is called when the serial port gets closed. First, we
- * wait for the last remaining data to be sent. Then, we unlink its
- * async structure from the interrupt chain if necessary, and we free
- * that IRQ if nothing is left in the chain.
- * ------------------------------------------------------------
- */
- static void sab8253x_close(struct tty_struct *tty, struct file * filp)
- {
- struct sab_port *port = (struct sab_port *)tty->driver_data;
- unsigned long flags;
-
- MOD_DEC_USE_COUNT;
- if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_close"))
- {
- return;
- }
- if(port->open_type == OPEN_SYNC_NET)
- { /* port->tty field should already be NULL */
- /* port count was not incremented */
- return;
- }
-
- --(port->count); /* have a valid port */
- if (tty_hung_up_p(filp))
- {
-
- if(port->count == 0) /* shutdown took place in hangup context */
- {
- port->open_type = OPEN_NOT;
- }
- else if(port->count < 0)
- {
- printk(KERN_ALERT "XX20: port->count went negative.n");
- port->count = 0;
- port->open_type = OPEN_NOT;
- }
- return;
- }
-
- if (port->count < 0)
- {
- printk(KERN_ALERT "sab8253x_close: bad serial port count for ttys%d: %dn",
- port->line, port->count);
- port->count = 0;
- }
-
- if (port->count)
- {
- return;
- }
-
- port->flags |= FLAG8253X_CLOSING;
-
- /*
- * Save the termios structure, since this port may have
- * separate termios for callout and dialin.
- */
- if (port->flags & FLAG8253X_NORMAL_ACTIVE)
- {
- port->normal_termios = *tty->termios;
- }
- if (port->flags & FLAG8253X_CALLOUT_ACTIVE)
- {
- port->callout_termios = *tty->termios;
- }
- /*
- * Now we wait for the transmit buffer to clear; and we notify
- * the line discipline to only process XON/XOFF characters.
- */
- tty->closing = 1;
- if (port->closing_wait != SAB8253X_CLOSING_WAIT_NONE)
- {
- tty_wait_until_sent(tty, port->closing_wait); /* wait for drain */
- }
-
- /*
- * At this point we stop accepting input. To do this, we
- * disable the receive line status interrupts, and turn off
- * the receiver.
- */
-
- save_flags(flags);
- cli();
- port->interrupt_mask0 |= SAB82532_IMR0_TCD;
- WRITEB(port,imr0,port->interrupt_mask0);
-
- CLEAR_REG_BIT(port,mode,SAB82532_MODE_RAC); /* ??????? */
- restore_flags(flags);
-
- if (port->flags & FLAG8253X_INITIALIZED)
- {
- /*
- * Before we drop DTR, make sure the UART transmitter
- * has completely drained; this is especially
- * important if there is a transmit FIFO!
- */
- sab8253x_wait_until_sent(tty, port->timeout);
- }
- sab8253x_shutdown(port); /* no more ints on port */
- Sab8253xCleanUpTransceiveN(port); /* should be okay */
- if (tty->driver.flush_buffer)
- {
- tty->driver.flush_buffer(tty);
- }
- if (tty->ldisc.flush_buffer)
- {
- tty->ldisc.flush_buffer(tty);
- }
- tty->closing = 0;
- port->event = 0;
- port->tty = 0;
- if (port->blocked_open)
- {
- if (port->close_delay)
- {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(port->close_delay);
- }
- wake_up_interruptible(&port->open_wait); /* deal with open blocks */
- }
-
- if((port->flags & (FLAG8253X_CALLOUT_ACTIVE | FLAG8253X_NETWORK)) ==
- (FLAG8253X_CALLOUT_ACTIVE | FLAG8253X_NETWORK) &&
- port->dev)
- {
- port->flags &= ~(FLAG8253X_NORMAL_ACTIVE|FLAG8253X_CALLOUT_ACTIVE|
- FLAG8253X_CLOSING); /* leave network set */
- netif_carrier_off(port->dev);
- port->open_type = OPEN_SYNC_NET;
- sab8253x_startupN(port);
- }
- else
- {
- port->flags &= ~(FLAG8253X_NORMAL_ACTIVE|FLAG8253X_CALLOUT_ACTIVE|
- FLAG8253X_CLOSING);
- wake_up_interruptible(&port->close_wait);
- port->open_type = OPEN_NOT;
- }
- }
- /*
- * sab8253x_hangup() --- called by tty_hangup() when a hangup is signaled.
- */
- static void sab8253x_hangup(struct tty_struct *tty)
- {
- struct sab_port *port = (struct sab_port *)tty->driver_data;
-
- if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_hangup"))
- {
- return;
- }
-
- #ifdef XCONFIG_SERIAL_CONSOLE
- if (port->is_console)
- {
- return;
- }
- #endif
-
- sab8253x_flush_buffer(tty);
- if(port)
- {
- sab8253x_shutdown(port);
- Sab8253xCleanUpTransceiveN(port); /* this logic is a bit contorted
- Are we cleaning up the lists
- because we are waking up a
- blocked open? There is possibly
- an order problem here perhaps the
- open count should have increased in the
- int handler so that it could decrease here*/
- port->event = 0;
- port->flags &= ~(FLAG8253X_NORMAL_ACTIVE|FLAG8253X_CALLOUT_ACTIVE);
- port->tty = 0;
- wake_up_interruptible(&port->open_wait); /* deal with blocking open */
- }
- }
- /*
- * ------------------------------------------------------------
- * sab8253x_open() and friends
- * ------------------------------------------------------------
- */
- /*
- * This routine is called whenever a serial port is opened. It
- * enables interrupts for a serial port, linking in its async structure into
- * the IRQ chain. It also performs the serial-specific
- * initialization for the tty structure.
- */
- static int sab8253x_open(struct tty_struct *tty, struct file * filp)
- {
- struct sab_port *port;
- int retval, line;
- int counter;
- unsigned long flags;
-
- MOD_INC_USE_COUNT;
- line = MINOR(tty->device) - tty->driver.minor_start;
-
- for(counter = 0, port = AuraPortRoot;
- (counter < line) && (port != NULL);
- ++counter)
- {
- port = port->next;
- }
-
- if (!port)
- {
- printk(KERN_ALERT "sab8253x_open: can't find structure for line %dn",
- line);
- return -ENODEV;
- }
-
- save_flags(flags); /* Need to protect the port->tty field */
- cli();
-
- if(port->tty == NULL)
- {
- port->tty = tty; /* may be a standard tty waiting on a call out device */
- tty->flip.tqueue.routine = sab8253x_flush_to_ldisc;
- }
-
- tty->driver_data = port; /* but the tty devices are unique for each type of open */
-
- if(port->function == FUNCTION_NA)
- { /* port 2 on 1020s and 1520s */
- ++(port->count);
- restore_flags(flags);
- return -ENODEV;
- }
-
- /* Check whether or not the port is open in SYNC mode */
- if(port->open_type == OPEN_SYNC_NET)
- {
- if(port->dev && netif_carrier_ok(port->dev));
- {
- port->tty= NULL; /* Don't bother with open counting here
- but make sure the tty field is NULL*/
- restore_flags(flags);
- return -EBUSY;
- }
- sab8253x_flush_buffer(tty); /* don't restore flags here */
- sab8253x_shutdownN(port);
- }
- else if (port->open_type > OPEN_ASYNC) /* can't have a callout or async line
- * if already open in some sync mode */
- {
- ++(port->count);
- restore_flags(flags);
- return -EBUSY;
- }
- restore_flags(flags);
-
- if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_open"))
- {
- ++(port->count);
- return -ENODEV;
- }
-
- #ifdef DEBUG_OPEN
- printk("sab8253x_open %s%d, count = %dn", tty->driver.name, port->line,
- port->count);
- #endif
-
- /*
- * If the port is in the middle of closing, bail out now.
- */
- if (tty_hung_up_p(filp) ||
- (port->flags & FLAG8253X_CLOSING))
- {
-
- if (port->flags & FLAG8253X_CLOSING)
- {
- interruptible_sleep_on(&port->close_wait);
- }
- #ifdef SERIAL_DO_RESTART
- ++(port->count);
- return ((port->flags & FLAG8253X_HUP_NOTIFY) ?
- -EAGAIN : -ERESTARTSYS);
- #else
- ++(port->count);
- return -EAGAIN;
- #endif
- }
-
- if(Sab8253xSetUpLists(port))
- {
- ++(port->count);
- return -ENODEV;
- }
- if(Sab8253xInitDescriptors2(port, sab8253xt_listsize, sab8253xt_rbufsize))
- {
- ++(port->count);
- return -ENODEV;
- }
-
- retval = sab8253x_startup(port);
- if (retval)
- {
- ++(port->count);
- return retval;
- }
-
- retval = sab8253x_block_til_ready(tty, filp, port);
- ++(port->count);
- if (retval)
- {
- return retval;
- }
-
- port->tty = tty; /* may change here once through the block */
- /* because now the port belongs to an new tty */
- tty->flip.tqueue.routine = sab8253x_flush_to_ldisc; /* in case it was changed */
-
- if(Sab8253xSetUpLists(port))
- {
- return -ENODEV;
- }
- if(Sab8253xInitDescriptors2(port, sab8253xt_listsize, sab8253xt_rbufsize))
- {
- Sab8253xCleanUpTransceiveN(port); /* the network functions should be okay -- only difference */
- /* is the crc32 that is appended */
- return -ENODEV;
- }
-
- /*
- * Start up serial port
- */
- retval = sab8253x_startup(port); /* just in case closing the cu dev
- * shutdown the port (but left CD) */
- if (retval)
- {
- return retval;
- }
-
- if ((port->count == 1) && /* first open */
- (port->flags & FLAG8253X_SPLIT_TERMIOS))
- {
- if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
- {
- *tty->termios = port->normal_termios;
- }
- else
- {
- *tty->termios = port->callout_termios;
- }
- sab8253x_change_speed(port);
- }
-
-
- #ifdef XCONFIG_SERIAL_CONSOLE
- if (sab8253x_console.cflag && sab8253x_console.index == line)
- {
- tty->termios->c_cflag = sab8253x_console.cflag;
- sab8253x_console.cflag = 0;
- sab8253x_change_speed(port);
- }
- #endif
-
- port->session = current->session;
- port->pgrp = current->pgrp;
- port->open_type = OPEN_ASYNC;
- return 0;
- }
- static char *signaling[] =
- {
- "OFF ",
- "RS232",
- "RS422",
- "RS485",
- "RS449",
- "RS530",
- "V.35 "
- };
- static int sab8253x_read_proc(char *page, char **start, off_t off, int count,
- int *eof, void *data)
- {
- extern struct sab_port * AuraPortRoot;
- struct sab_port *port = AuraPortRoot;
- extern char *board_type[];
- off_t begin = 0;
- int len = 0;
- int portno;
- unsigned int typeno;
- extern int sab8253x_rebootflag;
-
- #ifdef FREEININTERRUPT
- len += sprintf(page, "serinfo:2.01I driver:%sn", sab8253x_serial_version);
- #else
- len += sprintf(page, "serinfo:2.01N driver:%sn", sab8253x_serial_version);
- #endif
- if(sab8253x_rebootflag)
- {
- len += sprintf(page+len,
- "WARNING: Found %d cards that required reprogramming. Reboot machine!.n",
- sab8253x_rebootflag);
- }
- len += sprintf(page+len, "TTY MAJOR = %d, CUA MAJOR = %d, STTY MAJOR = %d.n",
- sab8253x_serial_driver.major, sab8253x_callout_driver.major,
- sync_sab8253x_serial_driver.major);
- for (portno = 0; port != NULL; port = port->next, ++portno)
- {
- typeno = port->board->b_type;
- if(typeno > BD_8520P)
- {
- typeno = 0;
- }
- len += sprintf(page+len,
- "%d: port %d: %s: v%d: chip %d: ATI %s: bus %d: slot %d: %s: ",
- sab8253x_serial_driver.minor_start + portno,
- port->portno,
- (port->chip->chip_type == ESCC2) ? "sab82532" : "sab82538",
- port->type,
- port->chip->c_chipno,
- board_type[port->board->b_type],
- port->board->b_dev.bus->number,
- PCI_SLOT(port->board->b_dev.devfn),
- aura_functionality[((port->function > FUNCTION_UN) ? FUNCTION_UN : port->function)]);
- switch(port->open_type)
- {
- case OPEN_ASYNC:
- len += sprintf(page+len, "openA");
- break;
- case OPEN_SYNC:
- len += sprintf(page+len, "openS");
- break;
- case OPEN_SYNC_NET:
- len += sprintf(page+len, "openN");
- break;
- case OPEN_SYNC_CHAR:
- len += sprintf(page+len, "openC");
- break;
- case OPEN_NOT:
- len += sprintf(page+len, "close");
- break;
- default:
- len += sprintf(page+len, "open?");
- break;
- }
- if(port->chip->c_cim)
- {
- if(port->chip->c_cim->ci_type == CIM_SP502)
- {
- len += sprintf(page+len, ": %sn", signaling[port->sigmode]);
- }
- else
- {
- len += sprintf(page+len, ": NOPRGn");
- }
- }
- else
- {
- len += sprintf(page+len, ": NOPRGn");
- }
- if (len+begin > off+count)
- {
- goto done;
- }
- if (len+begin < off)
- {
- begin += len;
- len = 0;
- }
- }
- *eof = 1;
- done:
- if (off >= len+begin)
- {
- return 0;
- }
- *start = page + (off-begin);
- return ((count < begin+len-off) ? count : begin+len-off);
- }
- /*
- * ---------------------------------------------------------------------
- * sab8253x_init() and friends
- *
- * sab8253x_init() is called at boot-time to initialize the serial driver.
- * ---------------------------------------------------------------------
- */
- static void inline show_aurora_version(void)
- {
- char *revision = "$Revision: 1.23 $";
- char *version, *p;
-
- version = strchr(revision, ' ');
- strcpy(sab8253x_serial_version, ++version);
- p = strchr(sab8253x_serial_version, ' ');
- *p = '';
- printk("Aurora serial driver version %sn", sab8253x_serial_version);
- }
- #ifndef MODULE
- static int GetMinorStart(void)
- {
- struct tty_driver *ttydriver;
- int minor_start = 0;
- kdev_t device;
-
- device = MKDEV(TTY_MAJOR, minor_start);
- while(ttydriver = get_tty_driver(device), ttydriver != NULL)
- {
- minor_start += ttydriver->num;
- device = MKDEV(TTY_MAJOR, minor_start);
- }
- return minor_start;
-
- }
- #endif
- int finish_sab8253x_setup_ttydriver(void)
- {
- extern unsigned int NumSab8253xPorts;
-
- sab8253x_tableASY = (struct tty_struct **) kmalloc(NumSab8253xPorts*sizeof(struct tty_struct *), GFP_KERNEL);
- if(sab8253x_tableASY == NULL)
- {
- printk(KERN_ALERT "auraXX20: Could not allocate memory for sab8253x_tableASY.n");
- return -1;
- }
- memset(sab8253x_tableASY, 0, NumSab8253xPorts*sizeof(struct tty_struct *));
- sab8253x_tableCUA = (struct tty_struct **) kmalloc(NumSab8253xPorts*sizeof(struct tty_struct *), GFP_KERNEL);
- if(sab8253x_tableCUA == NULL)
- {
- printk(KERN_ALERT "auraXX20: Could not allocate memory for sab8253x_tableCUA.n");
- return -1;
- }
- memset(sab8253x_tableCUA, 0, NumSab8253xPorts*sizeof(struct tty_struct *));
- sab8253x_tableSYN = (struct tty_struct **) kmalloc(NumSab8253xPorts*sizeof(struct tty_struct *), GFP_KERNEL);
- if(sab8253x_tableSYN == NULL)
- {
- printk(KERN_ALERT "auraXX20: Could not allocate memory for sab8253x_tableSYN.n");
- return -1;
- }
- memset(sab8253x_tableSYN, 0, NumSab8253xPorts*sizeof(struct tty_struct *));
-
- sab8253x_termios = (struct termios **) kmalloc(NumSab8253xPorts*sizeof(struct termios *), GFP_KERNEL);
- if(sab8253x_termios == NULL)
- {
- printk(KERN_ALERT "auraXX20: Could not allocate memory for sab8253x_termios.n");
- return -1;
- }
- memset(sab8253x_termios, 0, NumSab8253xPorts*sizeof(struct termios *));
- sab8253x_termios_locked = (struct termios **) kmalloc(NumSab8253xPorts*sizeof(struct termios *), GFP_KERNEL);
- if(sab8253x_termios_locked == NULL)
- {
- printk(KERN_ALERT "auraXX20: Could not allocate memory for sab8253x_termios_locked.n");
- return -1;
- }
- memset(sab8253x_termios_locked, 0, NumSab8253xPorts*sizeof(struct termios *));
- sync_sab8253x_serial_driver.num = sab8253x_callout_driver.num = sab8253x_serial_driver.num = NumSab8253xPorts;
- sab8253x_serial_driver.table = sab8253x_tableASY;
- sab8253x_callout_driver.table = sab8253x_tableCUA;
- sync_sab8253x_serial_driver.table = sab8253x_tableSYN;
- sync_sab8253x_serial_driver.termios = sab8253x_callout_driver.termios = sab8253x_serial_driver.termios =
- sab8253x_termios;
- sync_sab8253x_serial_driver.termios_locked = sab8253x_callout_driver.termios_locked =
- sab8253x_serial_driver.termios_locked = sab8253x_termios_locked;
-
- if (tty_register_driver(&sab8253x_serial_driver) < 0)
- {
- printk(KERN_ALERT "auraXX20: Could not register serial driver.n");
- return -1;
- }
- if (tty_register_driver(&sab8253x_callout_driver) < 0)
- {
- printk(KERN_ALERT "auraXX20: Could not register call out device.n");
- return -1;
- }
- if (tty_register_driver(&sync_sab8253x_serial_driver) < 0)
- {
- printk(KERN_ALERT "auraXX20: Could not register sync serial device.n");
- return -1;
- }
- return 0;
-
- }
- void sab8253x_setup_ttydriver(void)
- {
- #ifdef MODULE
- extern int xx20_minorstart;
- #endif
- init_bh(AURORA_BH, sab8253x_do_serial_bh);
-
- show_aurora_version();
-
- /* Initialize the tty_driver structure */
-
- memset(&sab8253x_serial_driver, 0, sizeof(struct tty_driver));
- sab8253x_serial_driver.magic = TTY_DRIVER_MAGIC;
- sab8253x_serial_driver.driver_name = "auraserial";
- sab8253x_serial_driver.name = "ttyS";
- sab8253x_serial_driver.major = TTY_MAJOR;
- #ifdef MODULE
- sab8253x_serial_driver.minor_start = xx20_minorstart;
- #else
- sab8253x_serial_driver.minor_start = GetMinorStart();
- #endif
- sab8253x_serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
- sab8253x_serial_driver.subtype = SERIAL_TYPE_NORMAL;
- sab8253x_serial_driver.init_termios = tty_std_termios;
- sab8253x_serial_driver.init_termios.c_cflag =
- B9600 | CS8 | CREAD | HUPCL | CLOCAL;
- sab8253x_serial_driver.flags = TTY_DRIVER_REAL_RAW;
- sab8253x_serial_driver.refcount = &sab8253x_refcount;
-
- sab8253x_serial_driver.open = sab8253x_open;
- sab8253x_serial_driver.close = sab8253x_close;
- sab8253x_serial_driver.write = sab8253x_write;
- sab8253x_serial_driver.put_char = NULL; /*sab8253x_put_char is evil.*/
- sab8253x_serial_driver.flush_chars = sab8253x_flush_chars;
- sab8253x_serial_driver.write_room = sab8253x_write_room;
- sab8253x_serial_driver.chars_in_buffer = sab8253x_chars_in_buffer;
- sab8253x_serial_driver.flush_buffer = sab8253x_flush_buffer;
- sab8253x_serial_driver.ioctl = sab8253x_ioctl;
- sab8253x_serial_driver.throttle = sab8253x_throttle;
- sab8253x_serial_driver.unthrottle = sab8253x_unthrottle;
- sab8253x_serial_driver.send_xchar = sab8253x_send_xchar;
- sab8253x_serial_driver.set_termios = sab8253x_set_termios;
- sab8253x_serial_driver.stop = sab8253x_stop;
- sab8253x_serial_driver.start = sab8253x_start;
- sab8253x_serial_driver.hangup = sab8253x_hangup;
- sab8253x_serial_driver.break_ctl = sab8253x_break;
- sab8253x_serial_driver.wait_until_sent = sab8253x_wait_until_sent;
- sab8253x_serial_driver.read_proc = sab8253x_read_proc;
-
- /*
- * The callout device is just like normal device except for
- * major number and the subtype code.
- */
- sab8253x_callout_driver = sab8253x_serial_driver;
- sab8253x_callout_driver.name = "cua";
- sab8253x_callout_driver.major = TTYAUX_MAJOR;
- sab8253x_callout_driver.subtype = SERIAL_TYPE_CALLOUT;
- sab8253x_callout_driver.read_proc = 0;
- sab8253x_callout_driver.proc_entry = 0;
-
- sync_sab8253x_serial_driver = sab8253x_serial_driver;
- sync_sab8253x_serial_driver.name = "sttyS";
- sync_sab8253x_serial_driver.major = 0;
- sync_sab8253x_serial_driver.subtype = SERIAL_TYPE_SYNCTTY;
-
- sync_sab8253x_serial_driver.open = sab8253x_openS;
- sync_sab8253x_serial_driver.close = sab8253x_closeS;
- sync_sab8253x_serial_driver.write = sab8253x_writeS;
- sync_sab8253x_serial_driver.put_char = NULL; /*sab8253x_put_char logic is evil*/
- sync_sab8253x_serial_driver.flush_chars = sab8253x_flush_charsS;
- sync_sab8253x_serial_driver.write_room = sab8253x_write_room;
- sync_sab8253x_serial_driver.chars_in_buffer = sab8253x_chars_in_buffer;
- sync_sab8253x_serial_driver.flush_buffer = sab8253x_flush_buffer;
- sync_sab8253x_serial_driver.ioctl = sab8253x_ioctl;
- sync_sab8253x_serial_driver.throttle = sab8253x_throttleS;
- sync_sab8253x_serial_driver.unthrottle = sab8253x_unthrottleS;
- sync_sab8253x_serial_driver.send_xchar = sab8253x_send_xcharS;
- sync_sab8253x_serial_driver.set_termios = sab8253x_set_termiosS;
- sync_sab8253x_serial_driver.stop = sab8253x_stopS;
- sync_sab8253x_serial_driver.start = sab8253x_startS;
- sync_sab8253x_serial_driver.hangup = sab8253x_hangupS;
- sync_sab8253x_serial_driver.break_ctl = sab8253x_breakS;
- sync_sab8253x_serial_driver.wait_until_sent = sab8253x_wait_until_sent;
- sync_sab8253x_serial_driver.read_proc = 0;
- sync_sab8253x_serial_driver.proc_entry = 0;
- }
- void sab8253x_setup_ttyport(struct sab_port *p_port)
- {
- p_port->magic = SAB_MAGIC;
- p_port->custom_divisor = 16;
- p_port->close_delay = 5*HZ/10;
- p_port->closing_wait = 30*HZ;
- p_port->tec_timeout = SAB8253X_MAX_TEC_DELAY;
- p_port->cec_timeout = SAB8253X_MAX_CEC_DELAY;
- p_port->x_char = 0;
- p_port->event = 0;
- p_port->flags= FLAG8253X_BOOT_AUTOCONF | FLAG8253X_SKIP_TEST;
- p_port->blocked_open = 0;
-
- p_port->all_sent = 1; /* probably not needed */
-
- p_port->tqueue.sync = 0; /* for later */
- p_port->tqueue.routine = sab8253x_do_softint;
- p_port->tqueue.data = p_port;
- p_port->tqueue_hangup.sync = 0; /* for later */
- p_port->tqueue_hangup.routine = sab8253x_do_serial_hangup;
- p_port->tqueue_hangup.data = p_port;
- p_port->callout_termios = sab8253x_callout_driver.init_termios;
- p_port->normal_termios = sab8253x_serial_driver.init_termios; /* these are being shared */
- /* between asynchronous and */
- /* asynchronous ttys */
- init_waitqueue_head(&p_port->open_wait);
- init_waitqueue_head(&p_port->close_wait);
- init_waitqueue_head(&p_port->delta_msr_wait);
- init_waitqueue_head(&p_port->write_wait);
- init_waitqueue_head(&p_port->read_wait);
-
- p_port->count = 0; /* maybe not needed */
- p_port->icount.cts = p_port->icount.dsr =
- p_port->icount.rng = p_port->icount.dcd = 0;
- p_port->cts.val = p_port->dsr.val =
- p_port->dcd.val = 0;
- p_port->icount.rx = p_port->icount.tx = 0;
- p_port->icount.frame = p_port->icount.parity = 0;
- p_port->icount.overrun = p_port->icount.brk = 0;
-
- p_port->xmit_fifo_size = 32;
- p_port->recv_fifo_size = 32;
- p_port->xmit_buf = NULL;
- p_port->receive_chars = sab8253x_receive_chars;
- p_port->transmit_chars = sab8253x_transmit_chars;
- p_port->check_status = sab8253x_check_status;
- p_port->receive_test = (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME |
- SAB82532_ISR0_RFO | SAB82532_ISR0_RPF);
- p_port->transmit_test = (SAB82532_ISR1_ALLS | SAB82532_ISR1_XPR);
- p_port->check_status_test = SAB82532_ISR1_BRK;
-
- /* put in default sync control channel values
- * not needed for async -- I think these work
- * for bisync*/
- p_port->ccontrol.ccr0 = DEFAULT_CCR0;
- p_port->ccontrol.ccr1 = DEFAULT_CCR1;
- p_port->ccontrol.ccr2 = DEFAULT_CCR2;
- p_port->ccontrol.ccr3 = DEFAULT_CCR3;
- p_port->ccontrol.ccr4 = DEFAULT_CCR4;
- p_port->ccontrol.mode = DEFAULT_MODE;
- p_port->ccontrol.rlcr = DEFAULT_RLCR;
- }
- void sab8253x_cleanup_ttydriver(void)
- {
- unsigned long flags;
- int e1, e2;
-
- save_flags(flags);
- cli();
-
- if(sab8253x_tableASY)
- kfree(sab8253x_tableASY);
- if(sab8253x_tableCUA)
- kfree(sab8253x_tableCUA);
- if(sab8253x_tableSYN)
- kfree(sab8253x_tableSYN);
- if(sab8253x_termios)
- kfree(sab8253x_termios);
- if(sab8253x_termios_locked)
- kfree(sab8253x_termios_locked);
-
- remove_bh(AURORA_BH);
- if ((e1 = tty_unregister_driver(&sab8253x_serial_driver)))
- {
- printk("SERIAL: failed to unregister serial driver (%d)n",
- e1);
- }
- if ((e2 = tty_unregister_driver(&sab8253x_callout_driver)))
- {
- printk("SERIAL: failed to unregister callout driver (%d)n",
- e2);
- }
- if ((e2 = tty_unregister_driver(&sync_sab8253x_serial_driver)))
- {
- printk("SERIAL: failed to unregister callout driver (%d)n",
- e2);
- }
- restore_flags(flags);
- }
- /* THE CODE BELOW HAS NOT YET BEEN MODIFIED!!!! FW */
- #ifdef XCONFIG_SERIAL_CONSOLE
- static inline void
- sab8253x_console_putchar(struct sab8253x *info, char c)
- {
- unsigned long flags;
-
- save_flags(flags); cli();
- sab8253x_tec_wait(info);
- WRITEB(port,tic,c);
- restore_flags(flags);
- }
- static void
- sab8253x_console_write(struct console *con, const char *s, unsigned n)
- {
- struct sab8253x *info;
- int i;
-
- info = sab8253x_chain;
- for (i = con->index; i; i--) {
- info = info->next;
- if (!info)
- return;
- }
-
- for (i = 0; i < n; i++) {
- if (*s == 'n')
- sab8253x_console_putchar(info, 'r');
- sab8253x_console_putchar(info, *s++);
- }
- sab8253x_tec_wait(info);
- }
- static int
- sab8253x_console_wait_key(struct console *con)
- {
- sleep_on(&keypress_wait);
- return 0;
- }
- static kdev_t
- sab8253x_console_device(struct console *con)
- {
- return MKDEV(TTY_MAJOR, 64 + con->index);
- }
- static int
- sab8253x_console_setup(struct console *con, char *options)
- {
- struct sab8253x *info;
- unsigned int ebrg;
- tcflag_t cflag;
- unsigned char dafo;
- int i, bits;
- unsigned long flags;
-
- info = sab8253x_chain;
- for (i = con->index; i; i--)
- {
- info = info->next;
- if (!info)
- return -ENODEV;
- }
- info->is_console = 1;
-
- /*
- * Initialize the hardware
- */
- sab8253x_init_line(info);
-
- /*
- * Finally, enable interrupts
- */
- info->interrupt_mask0 = SAB82532_IMR0_PERR | SAB82532_IMR0_FERR |
- /*SAB82532_IMR0_TIME*/ | SAB82532_IMR0_PLLA/*| SAB82532_IMR0_CDSC*/;
- WRITEB(port,imr0,info->interrupt_mask0);
- info->interrupt_mask1 = SAB82532_IMR1_BRKT | SAB82532_IMR1_ALLS |
- SAB82532_IMR1_XOFF | SAB82532_IMR1_TIN |
- SAB82532_IMR1_CSC | SAB82532_IMR1_XON |
- SAB82532_IMR1_XPR;
- WRITEB(port,imr1,info->interrupt_mask1);
-
- printk("Console: ttyS%d (SAB82532)n", info->line);
-
- sunserial_console_termios(con);
- cflag = con->cflag;
-
- /* Byte size and parity */
- switch (cflag & CSIZE)
- {
- case CS5: dafo = SAB82532_DAFO_CHL5; bits = 7; break;
- case CS6: dafo = SAB82532_DAFO_CHL6; bits = 8; break;
- case CS7: dafo = SAB82532_DAFO_CHL7; bits = 9; break;
- case CS8: dafo = SAB82532_DAFO_CHL8; bits = 10; break;
- /* Never happens, but GCC is too dumb to figure it out */
- default: dafo = SAB82532_DAFO_CHL5; bits = 7; break;
- }
-
- if (cflag & CSTOPB)
- {
- dafo |= SAB82532_DAFO_STOP;
- bits++;
- }
-
- if (cflag & PARENB)
- {
- dafo |= SAB82532_DAFO_PARE;
- bits++;
- }
-
- if (cflag & PARODD)
- {
- #ifdef CMSPAR
- if (cflag & CMSPAR)
- dafo |= SAB82532_DAFO_PAR_MARK;
- else
- #endif
- dafo |= SAB82532_DAFO_PAR_ODD;
- }
- else
- {
- #ifdef CMSPAR
- if (cflag & CMSPAR)
- dafo |= SAB82532_DAFO_PAR_SPACE;
- else
- #endif
- dafo |= SAB82532_DAFO_PAR_EVEN;
- }
-
- /* Determine EBRG values based on baud rate */
- i = cflag & CBAUD;
- if (i & CBAUDEX)
- {
- i &= ~(CBAUDEX);
- if ((i < 1) || ((i + 15) >= NR_EBRG_VALUES))
- cflag &= ~CBAUDEX;
- else
- i += 15;
- }
- ebrg = ebrg_tabl[i].n;
- ebrg |= (ebrg_table[i].m << 6);
-
- info->baud = ebrg_table[i].baud;
- if (info->baud)
- info->timeout = (info->xmit_fifo_size * HZ * bits) / info->baud;
- else
- info->timeout = 0;
- info->timeout += HZ / 50; /* Add .02 seconds of slop */
-
- /* CTS flow control flags */
- if (cflag & CRTSCTS)
- info->flags |= FLAG8253X_CTS_FLOW;
- else
- info->flags &= ~(FLAG8253X_CTS_FLOW);
-
- if (cflag & CLOCAL)
- info->flags &= ~(FLAG8253X_CHECK_CD);
- else
- info->flags |= FLAG8253X_CHECK_CD;
-
- save_flags(flags); cli();
- sab8253x_cec_wait(info);
- sab8253x_tec_wait(info);
- WRITEB(port,dafo,dafo);
- WRITEB(port,bgr,ebrg & 0xff);
- info->regs->rw.ccr2 &= ~(0xc0);
- info->regs->rw.ccr2 |= (ebrg >> 2) & 0xc0;
- if (info->flags & FLAG8253X_CTS_FLOW)
- {
- info->regs->rw.mode &= ~(SAB82532_MODE_RTS);
- info->regs->rw.mode |= SAB82532_MODE_FRTS;
- info->regs->rw.mode &= ~(SAB82532_MODE_FCTS);
- }
- else
- {
- info->regs->rw.mode |= SAB82532_MODE_RTS;
- info->regs->rw.mode &= ~(SAB82532_MODE_FRTS);
- info->regs->rw.mode |= SAB82532_MODE_FCTS;
- }
- info->regs->rw.pvr &= ~(info->pvr_dtr_bit);
- info->regs->rw.mode |= SAB82532_MODE_RAC;
- restore_flags(flags);
-
- return 0;
- }
- static struct console sab8253x_console =
- {
- "ttyS",
- sab8253x_console_write,
- NULL,
- sab8253x_console_device,
- sab8253x_console_wait_key,
- NULL,
- sab8253x_console_setup,
- CON_PRINTBUFFER,
- -1,
- 0,
- NULL
- };
- int sab8253x_console_init(void)
- {
- extern int con_is_present(void);
- extern int su_console_registered;
-
- if (con_is_present() || su_console_registered)
- return 0;
-
- if (!sab8253x_chain)
- {
- prom_printf("sab8253x_console_setup: can't get SAB8253X chain");
- prom_halt();
- }
-
- sab8253x_console.index = serial_console - 1;
- register_console(&sab8253x_console);
- return 0;
- }
- #ifdef SERIAL_LOG_DEVICE
- static int serial_log_device = 0;
- static void
- dprint_init(int tty)
- {
- serial_console = tty + 1;
- sab8253x_console.index = tty;
- sab8253x_console_setup(&sab8253x_console, "");
- serial_console = 0;
- serial_log_device = tty + 1;
- }
- int
- dprintf(const char *fmt, ...)
- {
- static char buffer[4096];
- va_list args;
- int i;
-
- if (!serial_log_device)
- return 0;
-
- va_start(args, fmt);
- i = vsprintf(buffer, fmt, args);
- va_end(args);
- sab8253x_console.write(&sab8253x_console, buffer, i);
- return i;
- }
- #endif /* SERIAL_LOG_DEVICE */
- #endif /* XCONFIG_SERIAL_CONSOLE */