*/
static irqreturn_t rs_interrupt_single(int irq, void *dev_id)
{
- struct async_struct *info = dev_id;
+ struct serial_state *info = dev_id;
if (!info->tty) {
printk(KERN_INFO "simrs_interrupt_single: info|tty=0 info=%p problem\n", info);
static int rs_put_char(struct tty_struct *tty, unsigned char ch)
{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
+ struct serial_state *info = tty->driver_data;
unsigned long flags;
if (!tty || !info->xmit.buf)
return 1;
}
-static void transmit_chars(struct async_struct *info, int *intr_done)
+static void transmit_chars(struct serial_state *info, int *intr_done)
{
int count;
unsigned long flags;
-
local_irq_save(flags);
if (info->x_char) {
console->write(console, &c, 1);
- info->state->icount.tx++;
+ info->icount.tx++;
info->x_char = 0;
goto out;
static void rs_flush_chars(struct tty_struct *tty)
{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
+ struct serial_state *info = tty->driver_data;
if (info->xmit.head == info->xmit.tail || tty->stopped || tty->hw_stopped ||
!info->xmit.buf)
static int rs_write(struct tty_struct * tty,
const unsigned char *buf, int count)
{
+ struct serial_state *info = tty->driver_data;
int c, ret = 0;
- struct async_struct *info = (struct async_struct *)tty->driver_data;
unsigned long flags;
if (!tty || !info->xmit.buf || !tmp_buf) return 0;
static int rs_write_room(struct tty_struct *tty)
{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
+ struct serial_state *info = tty->driver_data;
return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
}
static int rs_chars_in_buffer(struct tty_struct *tty)
{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
+ struct serial_state *info = tty->driver_data;
return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
}
static void rs_flush_buffer(struct tty_struct *tty)
{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
+ struct serial_state *info = tty->driver_data;
unsigned long flags;
local_irq_save(flags);
*/
static void rs_send_xchar(struct tty_struct *tty, char ch)
{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
+ struct serial_state *info = tty->driver_data;
info->x_char = ch;
if (ch) {
static void rs_unthrottle(struct tty_struct * tty)
{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
+ struct serial_state *info = tty->driver_data;
if (I_IXOFF(tty)) {
if (info->x_char)
* 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 shutdown(struct async_struct * info)
+static void shutdown(struct serial_state *info)
{
unsigned long flags;
- struct serial_state *state = info->state;
- if (!(state->flags & ASYNC_INITIALIZED))
+ if (!(info->flags & ASYNC_INITIALIZED))
return;
#ifdef SIMSERIAL_DEBUG
- printk("Shutting down serial port %d (irq %d)....", info->line,
- state->irq);
+ printk("Shutting down serial port %d (irq %d)...\n", info->line,
+ info->irq);
#endif
local_irq_save(flags);
{
- if (state->irq)
- free_irq(state->irq, info);
+ if (info->irq)
+ free_irq(info->irq, info);
if (info->xmit.buf) {
free_page((unsigned long) info->xmit.buf);
if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags);
- state->flags &= ~ASYNC_INITIALIZED;
+ info->flags &= ~ASYNC_INITIALIZED;
}
local_irq_restore(flags);
}
*/
static void rs_close(struct tty_struct *tty, struct file * filp)
{
- struct async_struct * info = (struct async_struct *)tty->driver_data;
- struct serial_state *state;
+ struct serial_state *info = tty->driver_data;
unsigned long flags;
- if (!info ) return;
-
- state = info->state;
+ if (!info)
+ return;
local_irq_save(flags);
if (tty_hung_up_p(filp)) {
return;
}
#ifdef SIMSERIAL_DEBUG
- printk("rs_close ttys%d, count = %d\n", info->line, state->count);
+ printk("rs_close ttys%d, count = %d\n", info->line, info->count);
#endif
- if ((tty->count == 1) && (state->count != 1)) {
+ if ((tty->count == 1) && (info->count != 1)) {
/*
* Uh, oh. tty->count is 1, which means that the tty
- * structure will be freed. state->count should always
+ * structure will be freed. info->count should always
* be one in these conditions. If it's greater than
* one, we've got real problems, since it means the
* serial port won't be shutdown.
*/
printk(KERN_ERR "rs_close: bad serial port count; tty->count is 1, "
- "state->count is %d\n", state->count);
- state->count = 1;
+ "info->count is %d\n", info->count);
+ info->count = 1;
}
- if (--state->count < 0) {
+ if (--info->count < 0) {
printk(KERN_ERR "rs_close: bad serial port count for ttys%d: %d\n",
- state->line, state->count);
- state->count = 0;
+ info->line, info->count);
+ info->count = 0;
}
- if (state->count) {
+ if (info->count) {
local_irq_restore(flags);
return;
}
- state->flags |= ASYNC_CLOSING;
+ info->flags |= ASYNC_CLOSING;
local_irq_restore(flags);
/*
tty_ldisc_flush(tty);
info->tty = NULL;
if (info->blocked_open) {
- if (state->close_delay)
- schedule_timeout_interruptible(state->close_delay);
+ if (info->close_delay)
+ schedule_timeout_interruptible(info->close_delay);
wake_up_interruptible(&info->open_wait);
}
- state->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
+ info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
wake_up_interruptible(&info->close_wait);
}
*/
static void rs_hangup(struct tty_struct *tty)
{
- struct async_struct * info = (struct async_struct *)tty->driver_data;
- struct serial_state *state = info->state;
+ struct serial_state *info = tty->driver_data;
#ifdef SIMSERIAL_DEBUG
printk("rs_hangup: called\n");
#endif
rs_flush_buffer(tty);
- if (state->flags & ASYNC_CLOSING)
+ if (info->flags & ASYNC_CLOSING)
return;
shutdown(info);
- state->count = 0;
- state->flags &= ~ASYNC_NORMAL_ACTIVE;
+ info->count = 0;
+ info->flags &= ~ASYNC_NORMAL_ACTIVE;
info->tty = NULL;
wake_up_interruptible(&info->open_wait);
}
-static int get_async_struct(int line, struct async_struct **ret_info)
-{
- struct async_struct *info;
- struct serial_state *sstate;
-
- sstate = rs_table + line;
- sstate->count++;
- if (sstate->info) {
- *ret_info = sstate->info;
- return 0;
- }
- info = kzalloc(sizeof(struct async_struct), GFP_KERNEL);
- if (!info) {
- sstate->count--;
- return -ENOMEM;
- }
- init_waitqueue_head(&info->open_wait);
- init_waitqueue_head(&info->close_wait);
- info->state = sstate;
- if (sstate->info) {
- kfree(info);
- *ret_info = sstate->info;
- return 0;
- }
- *ret_info = sstate->info = info;
- return 0;
-}
-
-static int
-startup(struct async_struct *info)
+static int startup(struct serial_state *state)
{
unsigned long flags;
int retval=0;
- struct serial_state *state= info->state;
unsigned long page;
page = get_zeroed_page(GFP_KERNEL);
}
if (!state->port || !state->type) {
- if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags);
+ if (state->tty)
+ set_bit(TTY_IO_ERROR, &state->tty->flags);
free_page(page);
goto errout;
}
- if (info->xmit.buf)
+ if (state->xmit.buf)
free_page(page);
else
- info->xmit.buf = (unsigned char *) page;
+ state->xmit.buf = (unsigned char *) page;
#ifdef SIMSERIAL_DEBUG
- printk("startup: ttys%d (irq %d)...", info->line, state->irq);
+ printk("startup: ttys%d (irq %d)...", state->line, state->irq);
#endif
/*
*/
if (state->irq) {
retval = request_irq(state->irq, rs_interrupt_single, 0,
- "simserial", info);
+ "simserial", state);
if (retval)
goto errout;
}
- if (info->tty) clear_bit(TTY_IO_ERROR, &info->tty->flags);
+ if (state->tty)
+ clear_bit(TTY_IO_ERROR, &state->tty->flags);
- info->xmit.head = info->xmit.tail = 0;
+ state->xmit.head = state->xmit.tail = 0;
#if 0
/*
/*
* Set up the tty->alt_speed kludge
*/
- if (info->tty) {
+ if (state->tty) {
if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- info->tty->alt_speed = 57600;
+ state->tty->alt_speed = 57600;
if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- info->tty->alt_speed = 115200;
+ state->tty->alt_speed = 115200;
if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
- info->tty->alt_speed = 230400;
+ state->tty->alt_speed = 230400;
if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
- info->tty->alt_speed = 460800;
+ state->tty->alt_speed = 460800;
}
state->flags |= ASYNC_INITIALIZED;
*/
static int rs_open(struct tty_struct *tty, struct file * filp)
{
- struct async_struct *info;
+ struct serial_state *info = rs_table + tty->index;
int retval;
unsigned long page;
- retval = get_async_struct(tty->index, &info);
- if (retval)
- return retval;
- tty->driver_data = info;
+ info->count++;
info->tty = tty;
+ tty->driver_data = info;
#ifdef SIMSERIAL_DEBUG
- printk("rs_open %s, count = %d\n", tty->name, info->state->count);
+ printk("rs_open %s, count = %d\n", tty->name, info->count);
#endif
- info->tty->low_latency = (info->state->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+ tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
if (!tmp_buf) {
page = get_zeroed_page(GFP_KERNEL);
/*
* If the port is the middle of closing, bail out now
*/
- if (tty_hung_up_p(filp) ||
- (info->state->flags & ASYNC_CLOSING)) {
- if (info->state->flags & ASYNC_CLOSING)
+ if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) {
+ if (info->flags & ASYNC_CLOSING)
interruptible_sleep_on(&info->close_wait);
#ifdef SERIAL_DO_RESTART
- return ((info->state->flags & ASYNC_HUP_NOTIFY) ?
+ return ((info->flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS);
#else
return -EAGAIN;
* Let's have a little bit of fun !
*/
for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
+ init_waitqueue_head(&state->open_wait);
+ init_waitqueue_head(&state->close_wait);
if (state->type == PORT_UNKNOWN) continue;
#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)
#define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
- tty->name, (info->state->flags), serial_driver->refcount,info->count,tty->count,s)
+ tty->name, (info->flags), serial_driver->refcount,info->count,tty->count,s)
#else
#define DBG_CNT(s)
#endif
static unsigned char current_ctl_bits;
-static void change_speed(struct async_struct *info, struct ktermios *old);
+static void change_speed(struct serial_state *info, struct ktermios *old);
static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
#define serial_isroot() (capable(CAP_SYS_ADMIN))
-static inline int serial_paranoia_check(struct async_struct *info,
+static inline int serial_paranoia_check(struct serial_state *info,
char *name, const char *routine)
{
#ifdef SERIAL_PARANOIA_CHECK
*/
static void rs_stop(struct tty_struct *tty)
{
- struct async_struct *info = tty->driver_data;
+ struct serial_state *info = tty->driver_data;
unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_stop"))
static void rs_start(struct tty_struct *tty)
{
- struct async_struct *info = tty->driver_data;
+ struct serial_state *info = tty->driver_data;
unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_start"))
* -----------------------------------------------------------------------
*/
-static void receive_chars(struct async_struct *info)
+static void receive_chars(struct serial_state *info)
{
int status;
int serdatr;
struct async_icount *icount;
int oe = 0;
- icount = &info->state->icount;
+ icount = &info->icount;
status = UART_LSR_DR; /* We obviously have a character! */
serdatr = custom.serdatr;
printk("handling break....");
#endif
flag = TTY_BREAK;
- if (info->state->flags & ASYNC_SAK)
+ if (info->flags & ASYNC_SAK)
do_SAK(tty);
} else if (status & UART_LSR_PE)
flag = TTY_PARITY;
return;
}
-static void transmit_chars(struct async_struct *info)
+static void transmit_chars(struct serial_state *info)
{
custom.intreq = IF_TBE;
mb();
if (info->x_char) {
custom.serdat = info->x_char | 0x100;
mb();
- info->state->icount.tx++;
+ info->icount.tx++;
info->x_char = 0;
return;
}
custom.serdat = info->xmit.buf[info->xmit.tail++] | 0x100;
mb();
info->xmit.tail = info->xmit.tail & (SERIAL_XMIT_SIZE-1);
- info->state->icount.tx++;
+ info->icount.tx++;
if (CIRC_CNT(info->xmit.head,
info->xmit.tail,
}
}
-static void check_modem_status(struct async_struct *info)
+static void check_modem_status(struct serial_state *info)
{
unsigned char status = ciab.pra & (SER_DCD | SER_CTS | SER_DSR);
unsigned char dstatus;
current_ctl_bits = status;
if (dstatus) {
- icount = &info->state->icount;
+ icount = &info->icount;
/* update input line counters */
if (dstatus & SER_DSR)
icount->dsr++;
if (dstatus & SER_DCD) {
icount->dcd++;
#ifdef CONFIG_HARD_PPS
- if ((info->state->flags & ASYNC_HARDPPS_CD) &&
+ if ((info->flags & ASYNC_HARDPPS_CD) &&
!(status & SER_DCD))
hardpps();
#endif
wake_up_interruptible(&info->delta_msr_wait);
}
- if ((info->state->flags & ASYNC_CHECK_CD) && (dstatus & SER_DCD)) {
+ if ((info->flags & ASYNC_CHECK_CD) && (dstatus & SER_DCD)) {
#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
printk("ttyS%d CD now %s...", info->line,
(!(status & SER_DCD)) ? "on" : "off");
tty_hangup(info->tty);
}
}
- if (info->state->flags & ASYNC_CTS_FLOW) {
+ if (info->flags & ASYNC_CTS_FLOW) {
if (info->tty->hw_stopped) {
if (!(status & SER_CTS)) {
#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
static irqreturn_t ser_vbl_int( int irq, void *data)
{
/* vbl is just a periodic interrupt we tie into to update modem status */
- struct async_struct *info = data;
+ struct serial_state *info = data;
/*
* TBD - is it better to unregister from this interrupt or to
* ignore it if MSI is clear ?
static irqreturn_t ser_rx_int(int irq, void *dev_id)
{
- struct serial_state *state = dev_id;
- struct async_struct *info = state->info;
+ struct serial_state *info = dev_id;
#ifdef SERIAL_DEBUG_INTR
printk("ser_rx_int...");
#endif
- if (!info || !info->tty)
+ if (!info->tty)
return IRQ_NONE;
receive_chars(info);
static irqreturn_t ser_tx_int(int irq, void *dev_id)
{
- struct serial_state *state = dev_id;
- struct async_struct *info = state->info;
+ struct serial_state *info = dev_id;
if (custom.serdatr & SDR_TBE) {
#ifdef SERIAL_DEBUG_INTR
printk("ser_tx_int...");
#endif
- if (!info || !info->tty)
+ if (!info->tty)
return IRQ_NONE;
transmit_chars(info);
* ---------------------------------------------------------------
*/
-static int startup(struct async_struct * info)
+static int startup(struct serial_state *info)
{
unsigned long flags;
int retval=0;
local_irq_save(flags);
- if (info->state->flags & ASYNC_INITIALIZED) {
+ if (info->flags & ASYNC_INITIALIZED) {
free_page(page);
goto errout;
}
* Set up the tty->alt_speed kludge
*/
if (info->tty) {
- if ((info->state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
info->tty->alt_speed = 57600;
- if ((info->state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
info->tty->alt_speed = 115200;
- if ((info->state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
info->tty->alt_speed = 230400;
- if ((info->state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
info->tty->alt_speed = 460800;
}
*/
change_speed(info, NULL);
- info->state->flags |= ASYNC_INITIALIZED;
+ info->flags |= ASYNC_INITIALIZED;
local_irq_restore(flags);
return 0;
* 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 shutdown(struct async_struct * info)
+static void shutdown(struct serial_state *info)
{
unsigned long flags;
struct serial_state *state;
- if (!(info->state->flags & ASYNC_INITIALIZED))
+ if (!(info->flags & ASYNC_INITIALIZED))
return;
- state = info->state;
+ state = info;
#ifdef SERIAL_DEBUG_OPEN
printk("Shutting down serial port %d ....\n", info->line);
if (info->tty)
set_bit(TTY_IO_ERROR, &info->tty->flags);
- info->state->flags &= ~ASYNC_INITIALIZED;
+ info->flags &= ~ASYNC_INITIALIZED;
local_irq_restore(flags);
}
* This routine is called to set the UART divisor registers to match
* the specified baud rate for a serial port.
*/
-static void change_speed(struct async_struct *info,
+static void change_speed(struct serial_state *info,
struct ktermios *old_termios)
{
int quot = 0, baud_base, baud;
baud = tty_get_baud_rate(info->tty);
if (!baud)
baud = 9600; /* B0 transition handled in rs_set_termios */
- baud_base = info->state->baud_base;
+ baud_base = info->baud_base;
if (baud == 38400 &&
- ((info->state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
- quot = info->state->custom_divisor;
+ ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
+ quot = info->custom_divisor;
else {
if (baud == 134)
/* Special case since 134 is really 134.5 */
if (!baud)
baud = 9600;
if (baud == 38400 &&
- ((info->state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
- quot = info->state->custom_divisor;
+ ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
+ quot = info->custom_divisor;
else {
if (baud == 134)
/* Special case since 134 is really 134.5 */
if (!quot)
quot = baud_base / 9600;
info->quot = quot;
- info->timeout = ((info->state->xmit_fifo_size*HZ*bits*quot) / baud_base);
+ info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base);
info->timeout += HZ/50; /* Add .02 seconds of slop */
/* CTS flow control flag and modem status interrupts */
info->IER &= ~UART_IER_MSI;
- if (info->state->flags & ASYNC_HARDPPS_CD)
+ if (info->flags & ASYNC_HARDPPS_CD)
info->IER |= UART_IER_MSI;
if (cflag & CRTSCTS) {
- info->state->flags |= ASYNC_CTS_FLOW;
+ info->flags |= ASYNC_CTS_FLOW;
info->IER |= UART_IER_MSI;
} else
- info->state->flags &= ~ASYNC_CTS_FLOW;
+ info->flags &= ~ASYNC_CTS_FLOW;
if (cflag & CLOCAL)
- info->state->flags &= ~ASYNC_CHECK_CD;
+ info->flags &= ~ASYNC_CHECK_CD;
else {
- info->state->flags |= ASYNC_CHECK_CD;
+ info->flags |= ASYNC_CHECK_CD;
info->IER |= UART_IER_MSI;
}
/* TBD:
static int rs_put_char(struct tty_struct *tty, unsigned char ch)
{
- struct async_struct *info;
+ struct serial_state *info;
unsigned long flags;
info = tty->driver_data;
static void rs_flush_chars(struct tty_struct *tty)
{
- struct async_struct *info = tty->driver_data;
+ struct serial_state *info = tty->driver_data;
unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_flush_chars"))
static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count)
{
int c, ret = 0;
- struct async_struct *info;
+ struct serial_state *info = tty->driver_data;
unsigned long flags;
- info = tty->driver_data;
-
if (serial_paranoia_check(info, tty->name, "rs_write"))
return 0;
static int rs_write_room(struct tty_struct *tty)
{
- struct async_struct *info = tty->driver_data;
+ struct serial_state *info = tty->driver_data;
if (serial_paranoia_check(info, tty->name, "rs_write_room"))
return 0;
static int rs_chars_in_buffer(struct tty_struct *tty)
{
- struct async_struct *info = tty->driver_data;
+ struct serial_state *info = tty->driver_data;
if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer"))
return 0;
static void rs_flush_buffer(struct tty_struct *tty)
{
- struct async_struct *info = tty->driver_data;
+ struct serial_state *info = tty->driver_data;
unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_flush_buffer"))
*/
static void rs_send_xchar(struct tty_struct *tty, char ch)
{
- struct async_struct *info = tty->driver_data;
+ struct serial_state *info = tty->driver_data;
unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_send_char"))
*/
static void rs_throttle(struct tty_struct * tty)
{
- struct async_struct *info = tty->driver_data;
+ struct serial_state *info = tty->driver_data;
unsigned long flags;
#ifdef SERIAL_DEBUG_THROTTLE
char buf[64];
static void rs_unthrottle(struct tty_struct * tty)
{
- struct async_struct *info = tty->driver_data;
+ struct serial_state *info = tty->driver_data;
unsigned long flags;
#ifdef SERIAL_DEBUG_THROTTLE
char buf[64];
* ------------------------------------------------------------
*/
-static int get_serial_info(struct async_struct * info,
+static int get_serial_info(struct serial_state *state,
struct serial_struct __user * retinfo)
{
struct serial_struct tmp;
- struct serial_state *state = info->state;
if (!retinfo)
return -EFAULT;
return 0;
}
-static int set_serial_info(struct async_struct * info,
+static int set_serial_info(struct serial_state *state,
struct serial_struct __user * new_info)
{
struct serial_struct new_serial;
- struct serial_state old_state, *state;
+ struct serial_state old_state;
unsigned int change_irq,change_port;
int retval = 0;
return -EFAULT;
tty_lock();
- state = info->state;
old_state = *state;
change_irq = new_serial.irq != state->irq;
state->custom_divisor = new_serial.custom_divisor;
state->close_delay = new_serial.close_delay * HZ/100;
state->closing_wait = new_serial.closing_wait * HZ/100;
- info->tty->low_latency = (state->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+ state->tty->low_latency = (state->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
check_and_exit:
if (state->flags & ASYNC_INITIALIZED) {
(state->flags & ASYNC_SPD_MASK)) ||
(old_state.custom_divisor != state->custom_divisor)) {
if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- info->tty->alt_speed = 57600;
+ state->tty->alt_speed = 57600;
if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- info->tty->alt_speed = 115200;
+ state->tty->alt_speed = 115200;
if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
- info->tty->alt_speed = 230400;
+ state->tty->alt_speed = 230400;
if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
- info->tty->alt_speed = 460800;
- change_speed(info, NULL);
+ state->tty->alt_speed = 460800;
+ change_speed(state, NULL);
}
} else
- retval = startup(info);
+ retval = startup(state);
tty_unlock();
return retval;
}
* transmit holding register is empty. This functionality
* allows an RS485 driver to be written in user space.
*/
-static int get_lsr_info(struct async_struct * info, unsigned int __user *value)
+static int get_lsr_info(struct serial_state *info, unsigned int __user *value)
{
unsigned char status;
unsigned int result;
static int rs_tiocmget(struct tty_struct *tty)
{
- struct async_struct * info = tty->driver_data;
+ struct serial_state *info = tty->driver_data;
unsigned char control, status;
unsigned long flags;
static int rs_tiocmset(struct tty_struct *tty, unsigned int set,
unsigned int clear)
{
- struct async_struct * info = tty->driver_data;
+ struct serial_state *info = tty->driver_data;
unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
*/
static int rs_break(struct tty_struct *tty, int break_state)
{
- struct async_struct * info = tty->driver_data;
+ struct serial_state *info = tty->driver_data;
unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_break"))
static int rs_get_icount(struct tty_struct *tty,
struct serial_icounter_struct *icount)
{
- struct async_struct *info = tty->driver_data;
+ struct serial_state *info = tty->driver_data;
struct async_icount cnow;
unsigned long flags;
local_irq_save(flags);
- cnow = info->state->icount;
+ cnow = info->icount;
local_irq_restore(flags);
icount->cts = cnow.cts;
icount->dsr = cnow.dsr;
static int rs_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
- struct async_struct * info = tty->driver_data;
+ struct serial_state *info = tty->driver_data;
struct async_icount cprev, cnow; /* kernel counter temps */
void __user *argp = (void __user *)arg;
unsigned long flags;
case TIOCSERGSTRUCT:
if (copy_to_user(argp,
- info, sizeof(struct async_struct)))
+ info, sizeof(struct serial_state)))
return -EFAULT;
return 0;
case TIOCMIWAIT:
local_irq_save(flags);
/* note the counters on entry */
- cprev = info->state->icount;
+ cprev = info->icount;
local_irq_restore(flags);
while (1) {
interruptible_sleep_on(&info->delta_msr_wait);
if (signal_pending(current))
return -ERESTARTSYS;
local_irq_save(flags);
- cnow = info->state->icount; /* atomic copy */
+ cnow = info->icount; /* atomic copy */
local_irq_restore(flags);
if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
- struct async_struct *info = tty->driver_data;
+ struct serial_state *info = tty->driver_data;
unsigned long flags;
unsigned int cflag = tty->termios->c_cflag;
*/
static void rs_close(struct tty_struct *tty, struct file * filp)
{
- struct async_struct * info = tty->driver_data;
- struct serial_state *state;
+ struct serial_state *state = tty->driver_data;
unsigned long flags;
- if (!info || serial_paranoia_check(info, tty->name, "rs_close"))
+ if (!state || serial_paranoia_check(state, tty->name, "rs_close"))
return;
- state = info->state;
-
local_irq_save(flags);
if (tty_hung_up_p(filp)) {
}
#ifdef SERIAL_DEBUG_OPEN
- printk("rs_close ttys%d, count = %d\n", info->line, state->count);
+ printk("rs_close ttys%d, count = %d\n", state->line, state->count);
#endif
if ((tty->count == 1) && (state->count != 1)) {
/*
* interrupt driver to stop checking the data ready bit in the
* line status register.
*/
- info->read_status_mask &= ~UART_LSR_DR;
+ state->read_status_mask &= ~UART_LSR_DR;
if (state->flags & ASYNC_INITIALIZED) {
/* disable receive interrupts */
custom.intena = IF_RBF;
* has completely drained; this is especially
* important if there is a transmit FIFO!
*/
- rs_wait_until_sent(tty, info->timeout);
+ rs_wait_until_sent(tty, state->timeout);
}
- shutdown(info);
+ shutdown(state);
rs_flush_buffer(tty);
tty_ldisc_flush(tty);
tty->closing = 0;
- info->tty = NULL;
- if (info->blocked_open) {
+ state->tty = NULL;
+ if (state->blocked_open) {
if (state->close_delay) {
msleep_interruptible(jiffies_to_msecs(state->close_delay));
}
- wake_up_interruptible(&info->open_wait);
+ wake_up_interruptible(&state->open_wait);
}
state->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
- wake_up_interruptible(&info->close_wait);
+ wake_up_interruptible(&state->close_wait);
local_irq_restore(flags);
}
*/
static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
{
- struct async_struct * info = tty->driver_data;
+ struct serial_state *info = tty->driver_data;
unsigned long orig_jiffies, char_time;
int lsr;
if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent"))
return;
- if (info->state->xmit_fifo_size == 0)
+ if (info->xmit_fifo_size == 0)
return; /* Just in case.... */
orig_jiffies = jiffies;
* Note: we have to use pretty tight timings here to satisfy
* the NIST-PCTS.
*/
- char_time = (info->timeout - HZ/50) / info->state->xmit_fifo_size;
+ char_time = (info->timeout - HZ/50) / info->xmit_fifo_size;
char_time = char_time / 5;
if (char_time == 0)
char_time = 1;
*/
static void rs_hangup(struct tty_struct *tty)
{
- struct async_struct * info = tty->driver_data;
- struct serial_state *state = info->state;
+ struct serial_state *info = tty->driver_data;
if (serial_paranoia_check(info, tty->name, "rs_hangup"))
return;
- state = info->state;
-
rs_flush_buffer(tty);
shutdown(info);
- state->count = 0;
- state->flags &= ~ASYNC_NORMAL_ACTIVE;
+ info->count = 0;
+ info->flags &= ~ASYNC_NORMAL_ACTIVE;
info->tty = NULL;
wake_up_interruptible(&info->open_wait);
}
* ------------------------------------------------------------
*/
static int block_til_ready(struct tty_struct *tty, struct file * filp,
- struct async_struct *info)
+ struct serial_state *info)
{
#ifdef DECLARE_WAITQUEUE
DECLARE_WAITQUEUE(wait, current);
#else
struct wait_queue wait = { current, NULL };
#endif
- struct serial_state *state = info->state;
int retval;
int do_clocal = 0, extra_count = 0;
unsigned long flags;
* until it's done, and then try again.
*/
if (tty_hung_up_p(filp) ||
- (state->flags & ASYNC_CLOSING)) {
- if (state->flags & ASYNC_CLOSING)
+ (info->flags & ASYNC_CLOSING)) {
+ if (info->flags & ASYNC_CLOSING)
interruptible_sleep_on(&info->close_wait);
#ifdef SERIAL_DO_RESTART
- return ((state->flags & ASYNC_HUP_NOTIFY) ?
+ return ((info->flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS);
#else
return -EAGAIN;
*/
if ((filp->f_flags & O_NONBLOCK) ||
(tty->flags & (1 << TTY_IO_ERROR))) {
- state->flags |= ASYNC_NORMAL_ACTIVE;
+ info->flags |= ASYNC_NORMAL_ACTIVE;
return 0;
}
/*
* Block waiting for the carrier detect and the line to become
* free (i.e., not in use by the callout). While we are in
- * this loop, state->count is dropped by one, so that
+ * this loop, info->count is dropped by one, so that
* rs_close() knows when to free things. We restore it upon
* exit, either normal or abnormal.
*/
add_wait_queue(&info->open_wait, &wait);
#ifdef SERIAL_DEBUG_OPEN
printk("block_til_ready before block: ttys%d, count = %d\n",
- state->line, state->count);
+ info->line, info->count);
#endif
local_irq_save(flags);
if (!tty_hung_up_p(filp)) {
extra_count = 1;
- state->count--;
+ info->count--;
}
local_irq_restore(flags);
info->blocked_open++;
local_irq_restore(flags);
set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
- !(state->flags & ASYNC_INITIALIZED)) {
+ !(info->flags & ASYNC_INITIALIZED)) {
#ifdef SERIAL_DO_RESTART
- if (state->flags & ASYNC_HUP_NOTIFY)
+ if (info->flags & ASYNC_HUP_NOTIFY)
retval = -EAGAIN;
else
retval = -ERESTARTSYS;
#endif
break;
}
- if (!(state->flags & ASYNC_CLOSING) &&
+ if (!(info->flags & ASYNC_CLOSING) &&
(do_clocal || (!(ciab.pra & SER_DCD)) ))
break;
if (signal_pending(current)) {
}
#ifdef SERIAL_DEBUG_OPEN
printk("block_til_ready blocking: ttys%d, count = %d\n",
- info->line, state->count);
+ info->line, info->count);
#endif
tty_unlock();
schedule();
__set_current_state(TASK_RUNNING);
remove_wait_queue(&info->open_wait, &wait);
if (extra_count)
- state->count++;
+ info->count++;
info->blocked_open--;
#ifdef SERIAL_DEBUG_OPEN
printk("block_til_ready after blocking: ttys%d, count = %d\n",
- info->line, state->count);
+ info->line, info->count);
#endif
if (retval)
return retval;
- state->flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
-}
-
-static int get_async_struct(int line, struct async_struct **ret_info)
-{
- struct async_struct *info;
- struct serial_state *sstate;
-
- sstate = rs_table + line;
- sstate->count++;
- if (sstate->info) {
- *ret_info = sstate->info;
- return 0;
- }
- info = kzalloc(sizeof(struct async_struct), GFP_KERNEL);
- if (!info) {
- sstate->count--;
- return -ENOMEM;
- }
-#ifdef DECLARE_WAITQUEUE
- init_waitqueue_head(&info->open_wait);
- init_waitqueue_head(&info->close_wait);
- init_waitqueue_head(&info->delta_msr_wait);
-#endif
- info->state = sstate;
- if (sstate->info) {
- kfree(info);
- *ret_info = sstate->info;
- return 0;
- }
- *ret_info = sstate->info = info;
+ info->flags |= ASYNC_NORMAL_ACTIVE;
return 0;
}
*/
static int rs_open(struct tty_struct *tty, struct file * filp)
{
- struct async_struct *info;
+ struct serial_state *info = rs_table + tty->index;
int retval;
- retval = get_async_struct(tty->index, &info);
- if (retval) {
- return retval;
- }
- tty->driver_data = info;
+ info->count++;
info->tty = tty;
+ tty->driver_data = info;
if (serial_paranoia_check(info, tty->name, "rs_open"))
return -ENODEV;
#ifdef SERIAL_DEBUG_OPEN
- printk("rs_open %s, count = %d\n", tty->name, info->state->count);
+ printk("rs_open %s, count = %d\n", tty->name, info->count);
#endif
- info->tty->low_latency = (info->state->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+ tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
/*
* If the port is the middle of closing, bail out now
*/
if (tty_hung_up_p(filp) ||
- (info->state->flags & ASYNC_CLOSING)) {
- if (info->state->flags & ASYNC_CLOSING)
+ (info->flags & ASYNC_CLOSING)) {
+ if (info->flags & ASYNC_CLOSING)
interruptible_sleep_on(&info->close_wait);
#ifdef SERIAL_DO_RESTART
- return ((info->state->flags & ASYNC_HUP_NOTIFY) ?
+ return ((info->flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS);
#else
return -EAGAIN;
static inline void line_info(struct seq_file *m, struct serial_state *state)
{
- struct async_struct *info = state->info, scr_info;
char stat_buf[30], control, status;
unsigned long flags;
seq_printf(m, "%d: uart:amiga_builtin",state->line);
- /*
- * Figure out the current RS-232 lines
- */
- if (!info) {
- info = &scr_info; /* This is just for serial_{in,out} */
-
- info->quot = 0;
- info->tty = NULL;
- }
local_irq_save(flags);
status = ciab.pra;
- control = info ? info->MCR : status;
+ control = (state->flags & ASYNC_INITIALIZED) ? state->MCR : status;
local_irq_restore(flags);
stat_buf[0] = 0;
if(!(status & SER_DCD))
strcat(stat_buf, "|CD");
- if (info->quot) {
- seq_printf(m, " baud:%d", state->baud_base / info->quot);
- }
+ if (state->quot)
+ seq_printf(m, " baud:%d", state->baud_base / state->quot);
seq_printf(m, " tx:%d rx:%d", state->icount.tx, state->icount.rx);
state->icount.rx = state->icount.tx = 0;
state->icount.frame = state->icount.parity = 0;
state->icount.overrun = state->icount.brk = 0;
+ init_waitqueue_head(&state->open_wait);
+ init_waitqueue_head(&state->close_wait);
+ init_waitqueue_head(&state->delta_msr_wait);
printk(KERN_INFO "ttyS%d is the amiga builtin serial port\n",
state->line);
{
int error;
struct serial_state *state = platform_get_drvdata(pdev);
- struct async_struct *info = state->info;
/* printk("Unloading %s: version %s\n", serial_name, serial_version); */
if ((error = tty_unregister_driver(serial_driver)))
error);
put_tty_driver(serial_driver);
- rs_table[0].info = NULL;
- kfree(info);
-
- free_irq(IRQ_AMIGA_TBE, rs_table);
- free_irq(IRQ_AMIGA_RBF, rs_table);
+ free_irq(IRQ_AMIGA_TBE, state);
+ free_irq(IRQ_AMIGA_RBF, state);
platform_set_drvdata(pdev, NULL);