summaryrefslogtreecommitdiffstats
path: root/drivers/char/epca.c
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2005-09-06 15:16:44 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-07 16:57:20 -0700
commitf2cf8e25ba4cf4e0881e612125858b4eed563ee4 (patch)
tree194b4015f7265924fc02da4741150f379e7f2c7a /drivers/char/epca.c
parent5dd42c262bd742fa3602180bbe5550b4828de8f3 (diff)
[PATCH] Clean up the old digi support and rescue it
Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/char/epca.c')
-rw-r--r--drivers/char/epca.c1588
1 files changed, 459 insertions, 1129 deletions
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index 6025e1866c7e..58d3738a2b7f 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -6,6 +6,8 @@
For technical support please email digiLinux@dgii.com or
call Digi tech support at (612) 912-3456
+ ** This driver is no longer supported by Digi **
+
Much of this design and code came from epca.c which was
copyright (C) 1994, 1995 Troy De Jongh, and subsquently
modified by David Nugent, Christoph Lameter, Mike McLagan.
@@ -43,31 +45,19 @@
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <asm/io.h>
-
-#ifdef CONFIG_PCI
-#define ENABLE_PCI
-#endif /* CONFIG_PCI */
-
-#define putUser(arg1, arg2) put_user(arg1, (unsigned long __user *)arg2)
-#define getUser(arg1, arg2) get_user(arg1, (unsigned __user *)arg2)
-
-#ifdef ENABLE_PCI
+#include <linux/spinlock.h>
#include <linux/pci.h>
#include "digiPCI.h"
-#endif /* ENABLE_PCI */
+
#include "digi1.h"
#include "digiFep1.h"
#include "epca.h"
#include "epcaconfig.h"
-#if BITS_PER_LONG != 32
-# error FIXME: this driver only works on 32-bit platforms
-#endif
-
/* ---------------------- Begin defines ------------------------ */
-#define VERSION "1.3.0.1-LK"
+#define VERSION "1.3.0.1-LK2.6"
/* This major needs to be submitted to Linux to join the majors list */
@@ -81,13 +71,17 @@
/* ----------------- Begin global definitions ------------------- */
-static char mesg[100];
static int nbdevs, num_cards, liloconfig;
static int digi_poller_inhibited = 1 ;
static int setup_error_code;
static int invalid_lilo_config;
+/* The ISA boards do window flipping into the same spaces so its only sane
+ with a single lock. It's still pretty efficient */
+
+static spinlock_t epca_lock = SPIN_LOCK_UNLOCKED;
+
/* -----------------------------------------------------------------------
MAXBOARDS is typically 12, but ISA and EISA cards are restricted to
7 below.
@@ -129,58 +123,58 @@ static struct timer_list epca_timer;
configured.
----------------------------------------------------------------------- */
-static inline void memwinon(struct board_info *b, unsigned int win);
-static inline void memwinoff(struct board_info *b, unsigned int win);
-static inline void globalwinon(struct channel *ch);
-static inline void rxwinon(struct channel *ch);
-static inline void txwinon(struct channel *ch);
-static inline void memoff(struct channel *ch);
-static inline void assertgwinon(struct channel *ch);
-static inline void assertmemoff(struct channel *ch);
+static void memwinon(struct board_info *b, unsigned int win);
+static void memwinoff(struct board_info *b, unsigned int win);
+static void globalwinon(struct channel *ch);
+static void rxwinon(struct channel *ch);
+static void txwinon(struct channel *ch);
+static void memoff(struct channel *ch);
+static void assertgwinon(struct channel *ch);
+static void assertmemoff(struct channel *ch);
/* ---- Begin more 'specific' memory functions for cx_like products --- */
-static inline void pcxem_memwinon(struct board_info *b, unsigned int win);
-static inline void pcxem_memwinoff(struct board_info *b, unsigned int win);
-static inline void pcxem_globalwinon(struct channel *ch);
-static inline void pcxem_rxwinon(struct channel *ch);
-static inline void pcxem_txwinon(struct channel *ch);
-static inline void pcxem_memoff(struct channel *ch);
+static void pcxem_memwinon(struct board_info *b, unsigned int win);
+static void pcxem_memwinoff(struct board_info *b, unsigned int win);
+static void pcxem_globalwinon(struct channel *ch);
+static void pcxem_rxwinon(struct channel *ch);
+static void pcxem_txwinon(struct channel *ch);
+static void pcxem_memoff(struct channel *ch);
/* ------ Begin more 'specific' memory functions for the pcxe ------- */
-static inline void pcxe_memwinon(struct board_info *b, unsigned int win);
-static inline void pcxe_memwinoff(struct board_info *b, unsigned int win);
-static inline void pcxe_globalwinon(struct channel *ch);
-static inline void pcxe_rxwinon(struct channel *ch);
-static inline void pcxe_txwinon(struct channel *ch);
-static inline void pcxe_memoff(struct channel *ch);
+static void pcxe_memwinon(struct board_info *b, unsigned int win);
+static void pcxe_memwinoff(struct board_info *b, unsigned int win);
+static void pcxe_globalwinon(struct channel *ch);
+static void pcxe_rxwinon(struct channel *ch);
+static void pcxe_txwinon(struct channel *ch);
+static void pcxe_memoff(struct channel *ch);
/* ---- Begin more 'specific' memory functions for the pc64xe and pcxi ---- */
/* Note : pc64xe and pcxi share the same windowing routines */
-static inline void pcxi_memwinon(struct board_info *b, unsigned int win);
-static inline void pcxi_memwinoff(struct board_info *b, unsigned int win);
-static inline void pcxi_globalwinon(struct channel *ch);
-static inline void pcxi_rxwinon(struct channel *ch);
-static inline void pcxi_txwinon(struct channel *ch);
-static inline void pcxi_memoff(struct channel *ch);
+static void pcxi_memwinon(struct board_info *b, unsigned int win);
+static void pcxi_memwinoff(struct board_info *b, unsigned int win);
+static void pcxi_globalwinon(struct channel *ch);
+static void pcxi_rxwinon(struct channel *ch);
+static void pcxi_txwinon(struct channel *ch);
+static void pcxi_memoff(struct channel *ch);
/* - Begin 'specific' do nothing memory functions needed for some cards - */
-static inline void dummy_memwinon(struct board_info *b, unsigned int win);
-static inline void dummy_memwinoff(struct board_info *b, unsigned int win);
-static inline void dummy_globalwinon(struct channel *ch);
-static inline void dummy_rxwinon(struct channel *ch);
-static inline void dummy_txwinon(struct channel *ch);
-static inline void dummy_memoff(struct channel *ch);
-static inline void dummy_assertgwinon(struct channel *ch);
-static inline void dummy_assertmemoff(struct channel *ch);
+static void dummy_memwinon(struct board_info *b, unsigned int win);
+static void dummy_memwinoff(struct board_info *b, unsigned int win);
+static void dummy_globalwinon(struct channel *ch);
+static void dummy_rxwinon(struct channel *ch);
+static void dummy_txwinon(struct channel *ch);
+static void dummy_memoff(struct channel *ch);
+static void dummy_assertgwinon(struct channel *ch);
+static void dummy_assertmemoff(struct channel *ch);
/* ------------------- Begin declare functions ----------------------- */
-static inline struct channel *verifyChannel(register struct tty_struct *);
-static inline void pc_sched_event(struct channel *, int);
+static struct channel *verifyChannel(struct tty_struct *);
+static void pc_sched_event(struct channel *, int);
static void epca_error(int, char *);
static void pc_close(struct tty_struct *, struct file *);
static void shutdown(struct channel *);
@@ -215,15 +209,11 @@ static void pc_unthrottle(struct tty_struct *tty);
static void digi_send_break(struct channel *ch, int msec);
static void setup_empty_event(struct tty_struct *tty, struct channel *ch);
void epca_setup(char *, int *);
-void console_print(const char *);
static int get_termio(struct tty_struct *, struct termio __user *);
static int pc_write(struct tty_struct *, const unsigned char *, int);
-int pc_init(void);
-
-#ifdef ENABLE_PCI
+static int pc_init(void);
static int init_PCI(void);
-#endif /* ENABLE_PCI */
/* ------------------------------------------------------------------
@@ -237,41 +227,41 @@ static int init_PCI(void);
making direct calls deserves what they get.
-------------------------------------------------------------------- */
-static inline void memwinon(struct board_info *b, unsigned int win)
+static void memwinon(struct board_info *b, unsigned int win)
{
(b->memwinon)(b, win);
}
-static inline void memwinoff(struct board_info *b, unsigned int win)
+static void memwinoff(struct board_info *b, unsigned int win)
{
(b->memwinoff)(b, win);
}
-static inline void globalwinon(struct channel *ch)
+static void globalwinon(struct channel *ch)
{
(ch->board->globalwinon)(ch);
}
-static inline void rxwinon(struct channel *ch)
+static void rxwinon(struct channel *ch)
{
(ch->board->rxwinon)(ch);
}
-static inline void txwinon(struct channel *ch)
+static void txwinon(struct channel *ch)
{
(ch->board->txwinon)(ch);
}
-static inline void memoff(struct channel *ch)
+static void memoff(struct channel *ch)
{
(ch->board->memoff)(ch);
}
-static inline void assertgwinon(struct channel *ch)
+static void assertgwinon(struct channel *ch)
{
(ch->board->assertgwinon)(ch);
}
-static inline void assertmemoff(struct channel *ch)
+static void assertmemoff(struct channel *ch)
{
(ch->board->assertmemoff)(ch);
}
@@ -281,66 +271,66 @@ static inline void assertmemoff(struct channel *ch)
and CX series cards.
------------------------------------------------------------ */
-static inline void pcxem_memwinon(struct board_info *b, unsigned int win)
+static void pcxem_memwinon(struct board_info *b, unsigned int win)
{
- outb_p(FEPWIN|win, (int)b->port + 1);
+ outb_p(FEPWIN|win, b->port + 1);
}
-static inline void pcxem_memwinoff(struct board_info *b, unsigned int win)
+static void pcxem_memwinoff(struct board_info *b, unsigned int win)
{
- outb_p(0, (int)b->port + 1);
+ outb_p(0, b->port + 1);
}
-static inline void pcxem_globalwinon(struct channel *ch)
+static void pcxem_globalwinon(struct channel *ch)
{
outb_p( FEPWIN, (int)ch->board->port + 1);
}
-static inline void pcxem_rxwinon(struct channel *ch)
+static void pcxem_rxwinon(struct channel *ch)
{
outb_p(ch->rxwin, (int)ch->board->port + 1);
}
-static inline void pcxem_txwinon(struct channel *ch)
+static void pcxem_txwinon(struct channel *ch)
{
outb_p(ch->txwin, (int)ch->board->port + 1);
}
-static inline void pcxem_memoff(struct channel *ch)
+static void pcxem_memoff(struct channel *ch)
{
outb_p(0, (int)ch->board->port + 1);
}
/* ----------------- Begin pcxe memory window stuff ------------------ */
-static inline void pcxe_memwinon(struct board_info *b, unsigned int win)
+static void pcxe_memwinon(struct board_info *b, unsigned int win)
{
- outb_p(FEPWIN | win, (int)b->port + 1);
+ outb_p(FEPWIN | win, b->port + 1);
}
-static inline void pcxe_memwinoff(struct board_info *b, unsigned int win)
+static void pcxe_memwinoff(struct board_info *b, unsigned int win)
{
- outb_p(inb((int)b->port) & ~FEPMEM,
- (int)b->port + 1);
- outb_p(0, (int)b->port + 1);
+ outb_p(inb(b->port) & ~FEPMEM,
+ b->port + 1);
+ outb_p(0, b->port + 1);
}
-static inline void pcxe_globalwinon(struct channel *ch)
+static void pcxe_globalwinon(struct channel *ch)
{
outb_p( FEPWIN, (int)ch->board->port + 1);
}
-static inline void pcxe_rxwinon(struct channel *ch)
+static void pcxe_rxwinon(struct channel *ch)
{
outb_p(ch->rxwin, (int)ch->board->port + 1);
}
-static inline void pcxe_txwinon(struct channel *ch)
+static void pcxe_txwinon(struct channel *ch)
{
outb_p(ch->txwin, (int)ch->board->port + 1);
}
-static inline void pcxe_memoff(struct channel *ch)
+static void pcxe_memoff(struct channel *ch)
{
outb_p(0, (int)ch->board->port);
outb_p(0, (int)ch->board->port + 1);
@@ -348,44 +338,44 @@ static inline void pcxe_memoff(struct channel *ch)
/* ------------- Begin pc64xe and pcxi memory window stuff -------------- */
-static inline void pcxi_memwinon(struct board_info *b, unsigned int win)
+static void pcxi_memwinon(struct board_info *b, unsigned int win)
{
- outb_p(inb((int)b->port) | FEPMEM, (int)b->port);
+ outb_p(inb(b->port) | FEPMEM, b->port);
}
-static inline void pcxi_memwinoff(struct board_info *b, unsigned int win)
+static void pcxi_memwinoff(struct board_info *b, unsigned int win)
{
- outb_p(inb((int)b->port) & ~FEPMEM, (int)b->port);
+ outb_p(inb(b->port) & ~FEPMEM, b->port);
}
-static inline void pcxi_globalwinon(struct channel *ch)
+static void pcxi_globalwinon(struct channel *ch)
{
- outb_p(FEPMEM, (int)ch->board->port);
+ outb_p(FEPMEM, ch->board->port);
}
-static inline void pcxi_rxwinon(struct channel *ch)
+static void pcxi_rxwinon(struct channel *ch)
{
- outb_p(FEPMEM, (int)ch->board->port);
+ outb_p(FEPMEM, ch->board->port);
}
-static inline void pcxi_txwinon(struct channel *ch)
+static void pcxi_txwinon(struct channel *ch)
{
- outb_p(FEPMEM, (int)ch->board->port);
+ outb_p(FEPMEM, ch->board->port);
}
-static inline void pcxi_memoff(struct channel *ch)
+static void pcxi_memoff(struct channel *ch)
{
- outb_p(0, (int)ch->board->port);
+ outb_p(0, ch->board->port);
}
-static inline void pcxi_assertgwinon(struct channel *ch)
+static void pcxi_assertgwinon(struct channel *ch)
{
- epcaassert(inb((int)ch->board->port) & FEPMEM, "Global memory off");
+ epcaassert(inb(ch->board->port) & FEPMEM, "Global memory off");
}
-static inline void pcxi_assertmemoff(struct channel *ch)
+static void pcxi_assertmemoff(struct channel *ch)
{
- epcaassert(!(inb((int)ch->board->port) & FEPMEM), "Memory on");
+ epcaassert(!(inb(ch->board->port) & FEPMEM), "Memory on");
}
@@ -398,185 +388,143 @@ static inline void pcxi_assertmemoff(struct channel *ch)
may or may not do anything.
---------------------------------------------------------------------------*/
-static inline void dummy_memwinon(struct board_info *b, unsigned int win)
+static void dummy_memwinon(struct board_info *b, unsigned int win)
{
}
-static inline void dummy_memwinoff(struct board_info *b, unsigned int win)
+static void dummy_memwinoff(struct board_info *b, unsigned int win)
{
}
-static inline void dummy_globalwinon(struct channel *ch)
+static void dummy_globalwinon(struct channel *ch)
{
}
-static inline void dummy_rxwinon(struct channel *ch)
+static void dummy_rxwinon(struct channel *ch)
{
}
-static inline void dummy_txwinon(struct channel *ch)
+static void dummy_txwinon(struct channel *ch)
{
}
-static inline void dummy_memoff(struct channel *ch)
+static void dummy_memoff(struct channel *ch)
{
}
-static inline void dummy_assertgwinon(struct channel *ch)
+static void dummy_assertgwinon(struct channel *ch)
{
}
-static inline void dummy_assertmemoff(struct channel *ch)
+static void dummy_assertmemoff(struct channel *ch)
{
}
/* ----------------- Begin verifyChannel function ----------------------- */
-static inline struct channel *verifyChannel(register struct tty_struct *tty)
+static struct channel *verifyChannel(struct tty_struct *tty)
{ /* Begin verifyChannel */
-
/* --------------------------------------------------------------------
This routine basically provides a sanity check. It insures that
the channel returned is within the proper range of addresses as
well as properly initialized. If some bogus info gets passed in
through tty->driver_data this should catch it.
- --------------------------------------------------------------------- */
-
- if (tty)
- { /* Begin if tty */
-
- register struct channel *ch = (struct channel *)tty->driver_data;
-
- if ((ch >= &digi_channels[0]) && (ch < &digi_channels[nbdevs]))
- {
+ --------------------------------------------------------------------- */
+ if (tty) {
+ struct channel *ch = (struct channel *)tty->driver_data;
+ if ((ch >= &digi_channels[0]) && (ch < &digi_channels[nbdevs])) {
if (ch->magic == EPCA_MAGIC)
return ch;
}
-
- } /* End if tty */
-
- /* Else return a NULL for invalid */
+ }
return NULL;
} /* End verifyChannel */
/* ------------------ Begin pc_sched_event ------------------------- */
-static inline void pc_sched_event(struct channel *ch, int event)
-{ /* Begin pc_sched_event */
-
-
+static void pc_sched_event(struct channel *ch, int event)
+{
/* ----------------------------------------------------------------------
We call this to schedule interrupt processing on some event. The
kernel sees our request and calls the related routine in OUR driver.
-------------------------------------------------------------------------*/
-
ch->event |= 1 << event;
schedule_work(&ch->tqueue);
-
-
} /* End pc_sched_event */
/* ------------------ Begin epca_error ------------------------- */
static void epca_error(int line, char *msg)
-{ /* Begin epca_error */
-
+{
printk(KERN_ERR "epca_error (Digi): line = %d %s\n",line,msg);
- return;
-
-} /* End epca_error */
+}
/* ------------------ Begin pc_close ------------------------- */
static void pc_close(struct tty_struct * tty, struct file * filp)
-{ /* Begin pc_close */
-
+{
struct channel *ch;
unsigned long flags;
-
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
if it is valid. This serves as a sanity check.
------------------------------------------------------------- */
-
- if ((ch = verifyChannel(tty)) != NULL)
- { /* Begin if ch != NULL */
-
- save_flags(flags);
- cli();
-
- if (tty_hung_up_p(filp))
- {
- restore_flags(flags);
+ if ((ch = verifyChannel(tty)) != NULL) { /* Begin if ch != NULL */
+ spin_lock_irqsave(&epca_lock, flags);
+ if (tty_hung_up_p(filp)) {
+ spin_unlock_irqrestore(&epca_lock, flags);
return;
}
-
/* Check to see if the channel is open more than once */
- if (ch->count-- > 1)
- { /* Begin channel is open more than once */
-
+ if (ch->count-- > 1) {
+ /* Begin channel is open more than once */
/* -------------------------------------------------------------
Return without doing anything. Someone might still be using
the channel.
---------------------------------------------------------------- */
-
- restore_flags(flags);
+ spin_unlock_irqrestore(&epca_lock, flags);
return;
} /* End channel is open more than once */
/* Port open only once go ahead with shutdown & reset */
-
- if (ch->count < 0)
- {
- ch->count = 0;
- }
+ if (ch->count < 0)
+ BUG();
/* ---------------------------------------------------------------
Let the rest of the driver know the channel is being closed.
This becomes important if an open is attempted before close
is finished.
------------------------------------------------------------------ */
-
ch->asyncflags |= ASYNC_CLOSING;
-
tty->closing = 1;
- if (ch->asyncflags & ASYNC_INITIALIZED)
- {
+ spin_unlock_irqrestore(&epca_lock, flags);
+
+ if (ch->asyncflags & ASYNC_INITIALIZED) {
/* Setup an event to indicate when the transmit buffer empties */
setup_empty_event(tty, ch);
tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
}
-
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
tty_ldisc_flush(tty);
shutdown(ch);
+
+ spin_lock_irqsave(&epca_lock, flags);
tty->closing = 0;
ch->event = 0;
ch->tty = NULL;
+ spin_unlock_irqrestore(&epca_lock, flags);
- if (ch->blocked_open)
- { /* Begin if blocked_open */
-
+ if (ch->blocked_open) { /* Begin if blocked_open */
if (ch->close_delay)
- {
msleep_interruptible(jiffies_to_msecs(ch->close_delay));
- }
-
wake_up_interruptible(&ch->open_wait);
-
} /* End if blocked_open */
-
ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED |
ASYNC_CLOSING);
wake_up_interruptible(&ch->close_wait);
-
-
- restore_flags(flags);
-
} /* End if ch != NULL */
-
} /* End pc_close */
/* ------------------ Begin shutdown ------------------------- */
@@ -586,15 +534,14 @@ static void shutdown(struct channel *ch)
unsigned long flags;
struct tty_struct *tty;
- volatile struct board_chan *bc;
+ struct board_chan *bc;
if (!(ch->asyncflags & ASYNC_INITIALIZED))
return;
- save_flags(flags);
- cli();
- globalwinon(ch);
+ spin_lock_irqsave(&epca_lock, flags);
+ globalwinon(ch);
bc = ch->brdchan;
/* ------------------------------------------------------------------
@@ -604,20 +551,17 @@ static void shutdown(struct channel *ch)
--------------------------------------------------------------------- */
if (bc)
- bc->idata = 0;
-
+ writeb(0, &bc->idata);
tty = ch->tty;
/* ----------------------------------------------------------------
If we're a modem control device and HUPCL is on, drop RTS & DTR.
------------------------------------------------------------------ */
- if (tty->termios->c_cflag & HUPCL)
- {
+ if (tty->termios->c_cflag & HUPCL) {
ch->omodem &= ~(ch->m_rts | ch->m_dtr);
fepcmd(ch, SETMODEM, 0, ch->m_dtr | ch->m_rts, 10, 1);
}
-
memoff(ch);
/* ------------------------------------------------------------------
@@ -628,7 +572,7 @@ static void shutdown(struct channel *ch)
/* Prevent future Digi programmed interrupts from coming active */
ch->asyncflags &= ~ASYNC_INITIALIZED;
- restore_flags(flags);
+ spin_unlock_irqrestore(&epca_lock, flags);
} /* End shutdown */
@@ -636,7 +580,6 @@ static void shutdown(struct channel *ch)
static void pc_hangup(struct tty_struct *tty)
{ /* Begin pc_hangup */
-
struct channel *ch;
/* ---------------------------------------------------------
@@ -644,25 +587,21 @@ static void pc_hangup(struct tty_struct *tty)
if it is valid. This serves as a sanity check.
------------------------------------------------------------- */
- if ((ch = verifyChannel(tty)) != NULL)
- { /* Begin if ch != NULL */
-
+ if ((ch = verifyChannel(tty)) != NULL) { /* Begin if ch != NULL */
unsigned long flags;
- save_flags(flags);
- cli();
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
tty_ldisc_flush(tty);
shutdown(ch);
+ spin_lock_irqsave(&epca_lock, flags);
ch->tty = NULL;
ch->event = 0;
ch->count = 0;
- restore_flags(flags);
ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED);
+ spin_unlock_irqrestore(&epca_lock, flags);
wake_up_interruptible(&ch->open_wait);
-
} /* End if ch != NULL */
} /* End pc_hangup */
@@ -672,18 +611,14 @@ static void pc_hangup(struct tty_struct *tty)
static int pc_write(struct tty_struct * tty,
const unsigned char *buf, int bytesAvailable)
{ /* Begin pc_write */
-
- register unsigned int head, tail;
- register int dataLen;
- register int size;
- register int amountCopied;
-
-
+ unsigned int head, tail;
+ int dataLen;
+ int size;
+ int amountCopied;
struct channel *ch;
unsigned long flags;
int remain;
- volatile struct board_chan *bc;
-
+ struct board_chan *bc;
/* ----------------------------------------------------------------
pc_write is primarily called directly by the kernel routine
@@ -706,24 +641,20 @@ static int pc_write(struct tty_struct * tty,
bc = ch->brdchan;
size = ch->txbufsize;
-
amountCopied = 0;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
- head = bc->tin & (size - 1);
- tail = bc->tout;
+ head = readw(&bc->tin) & (size - 1);
+ tail = readw(&bc->tout);
- if (tail != bc->tout)
- tail = bc->tout;
+ if (tail != readw(&bc->tout))
+ tail = readw(&bc->tout);
tail &= (size - 1);
/* If head >= tail, head has not wrapped around. */
- if (head >= tail)
- { /* Begin head has not wrapped */
-
+ if (head >= tail) { /* Begin head has not wrapped */
/* ---------------------------------------------------------------
remain (much like dataLen above) represents the total amount of
space available on the card for data. Here dataLen represents
@@ -731,26 +662,19 @@ static int pc_write(struct tty_struct * tty,
buffer. This is important because a memcpy cannot be told to
automatically wrap around when it hits the buffer end.
------------------------------------------------------------------ */
-
dataLen = size - head;
remain = size - (head - tail) - 1;
-
- } /* End head has not wrapped */
- else
- { /* Begin head has wrapped around */
+ } else { /* Begin head has wrapped around */
remain = tail - head - 1;
dataLen = remain;
} /* End head has wrapped around */
-
/* -------------------------------------------------------------------
Check the space on the card. If we have more data than
space; reduce the amount of data to fit the space.
---------------------------------------------------------------------- */
-
bytesAvailable = min(remain, bytesAvailable);
-
txwinon(ch);
while (bytesAvailable > 0)
{ /* Begin while there is data to copy onto card */
@@ -767,26 +691,21 @@ static int pc_write(struct tty_struct * tty,
amountCopied += dataLen;
bytesAvailable -= dataLen;
- if (head >= size)
- {
+ if (head >= size) {
head = 0;
dataLen = tail;
}
-
} /* End while there is data to copy onto card */
-
ch->statusflags |= TXBUSY;
globalwinon(ch);
- bc->tin = head;
+ writew(head, &bc->tin);
- if ((ch->statusflags & LOWWAIT) == 0)
- {
+ if ((ch->statusflags & LOWWAIT) == 0) {
ch->statusflags |= LOWWAIT;
- bc->ilow = 1;
+ writeb(1, &bc->ilow);
}
memoff(ch);
- restore_flags(flags);
-
+ spin_unlock_irqrestore(&epca_lock, flags);
return(amountCopied);
} /* End pc_write */
@@ -795,11 +714,7 @@ static int pc_write(struct tty_struct * tty,
static void pc_put_char(struct tty_struct *tty, unsigned char c)
{ /* Begin pc_put_char */
-
-
pc_write(tty, &c, 1);
- return;
-
} /* End pc_put_char */
/* ------------------ Begin pc_write_room ------------------------- */
@@ -811,7 +726,7 @@ static int pc_write_room(struct tty_struct *tty)
struct channel *ch;
unsigned long flags;
unsigned int head, tail;
- volatile struct board_chan *bc;
+ struct board_chan *bc;
remain = 0;
@@ -820,33 +735,29 @@ static int pc_write_room(struct tty_struct *tty)
if it is valid. This serves as a sanity check.
------------------------------------------------------------- */
- if ((ch = verifyChannel(tty)) != NULL)
- {
- save_flags(flags);
- cli();
+ if ((ch = verifyChannel(tty)) != NULL) {
+ spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
bc = ch->brdchan;
- head = bc->tin & (ch->txbufsize - 1);
- tail = bc->tout;
+ head = readw(&bc->tin) & (ch->txbufsize - 1);
+ tail = readw(&bc->tout);
- if (tail != bc->tout)
- tail = bc->tout;
+ if (tail != readw(&bc->tout))
+ tail = readw(&bc->tout);
/* Wrap tail if necessary */
tail &= (ch->txbufsize - 1);
if ((remain = tail - head - 1) < 0 )
remain += ch->txbufsize;
- if (remain && (ch->statusflags & LOWWAIT) == 0)
- {
+ if (remain && (ch->statusflags & LOWWAIT) == 0) {
ch->statusflags |= LOWWAIT;
- bc->ilow = 1;
+ writeb(1, &bc->ilow);
}
memoff(ch);
- restore_flags(flags);
+ spin_unlock_irqrestore(&epca_lock, flags);
}
-
/* Return how much room is left on card */
return remain;
@@ -862,8 +773,7 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
int remain;
unsigned long flags;
struct channel *ch;
- volatile struct board_chan *bc;
-
+ struct board_chan *bc;
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
@@ -873,34 +783,27 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
if ((ch = verifyChannel(tty)) == NULL)
return(0);
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
bc = ch->brdchan;
- tail = bc->tout;
- head = bc->tin;
- ctail = ch->mailbox->cout;
+ tail = readw(&bc->tout);
+ head = readw(&bc->tin);
+ ctail = readw(&ch->mailbox->cout);
- if (tail == head && ch->mailbox->cin == ctail && bc->tbusy == 0)
+ if (tail == head && readw(&ch->mailbox->cin) == ctail && readb(&bc->tbusy) == 0)
chars = 0;
- else
- { /* Begin if some space on the card has been used */
-
- head = bc->tin & (ch->txbufsize - 1);
+ else { /* Begin if some space on the card has been used */
+ head = readw(&bc->tin) & (ch->txbufsize - 1);
tail &= (ch->txbufsize - 1);
-
/* --------------------------------------------------------------
The logic here is basically opposite of the above pc_write_room
here we are finding the amount of bytes in the buffer filled.
Not the amount of bytes empty.
------------------------------------------------------------------- */
-
if ((remain = tail - head - 1) < 0 )
remain += ch->txbufsize;
-
chars = (int)(ch->txbufsize - remain);
-
/* -------------------------------------------------------------
Make it possible to wakeup anything waiting for output
in tty_ioctl.c, etc.
@@ -908,15 +811,12 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
If not already set. Setup an event to indicate when the
transmit buffer empties
----------------------------------------------------------------- */
-
if (!(ch->statusflags & EMPTYWAIT))
setup_empty_event(tty,ch);
} /* End if some space on the card has been used */
-
memoff(ch);
- restore_flags(flags);
-
+ spin_unlock_irqrestore(&epca_lock, flags);
/* Return number of characters residing on card. */
return(chars);
@@ -930,67 +830,46 @@ static void pc_flush_buffer(struct tty_struct *tty)
unsigned int tail;
unsigned long flags;
struct channel *ch;
- volatile struct board_chan *bc;
-
-
+ struct board_chan *bc;
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
if it is valid. This serves as a sanity check.
------------------------------------------------------------- */
-
if ((ch = verifyChannel(tty)) == NULL)
return;
- save_flags(flags);
- cli();
-
+ spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
-
bc = ch->brdchan;
- tail = bc->tout;
-
+ tail = readw(&bc->tout);
/* Have FEP move tout pointer; effectively flushing transmit buffer */
-
fepcmd(ch, STOUT, (unsigned) tail, 0, 0, 0);
-
memoff(ch);
- restore_flags(flags);
-
+ spin_unlock_irqrestore(&epca_lock, flags);
wake_up_interruptible(&tty->write_wait);
tty_wakeup(tty);
-
} /* End pc_flush_buffer */
/* ------------------ Begin pc_flush_chars ---------------------- */
static void pc_flush_chars(struct tty_struct *tty)
{ /* Begin pc_flush_chars */
-
struct channel * ch;
-
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
if it is valid. This serves as a sanity check.
------------------------------------------------------------- */
-
- if ((ch = verifyChannel(tty)) != NULL)
- {
+ if ((ch = verifyChannel(tty)) != NULL) {
unsigned long flags;
-
- save_flags(flags);
- cli();
-
+ spin_lock_irqsave(&epca_lock, flags);
/* ----------------------------------------------------------------
If not already set and the transmitter is busy setup an event
to indicate when the transmit empties.
------------------------------------------------------------------- */
-
if ((ch->statusflags & TXBUSY) && !(ch->statusflags & EMPTYWAIT))
setup_empty_event(tty,ch);
-
- restore_flags(flags);
+ spin_unlock_irqrestore(&epca_lock, flags);
}
-
} /* End pc_flush_chars */
/* ------------------ Begin block_til_ready ---------------------- */
@@ -998,14 +877,11 @@ static void pc_flush_chars(struct tty_struct *tty)
static int block_til_ready(struct tty_struct *tty,
struct file *filp, struct channel *ch)
{ /* Begin block_til_ready */
-
DECLARE_WAITQUEUE(wait,current);
int retval, do_clocal = 0;
unsigned long flags;
-
- if (tty_hung_up_p(filp))
- {
+ if (tty_hung_up_p(filp)) {
if (ch->asyncflags & ASYNC_HUP_NOTIFY)
retval = -EAGAIN;
else
@@ -1017,8 +893,7 @@ static int block_til_ready(struct tty_struct *tty,
If the device is in the middle of being closed, then block
until it's done, and then try again.
-------------------------------------------------------------------- */
- if (ch->asyncflags & ASYNC_CLOSING)
- {
+ if (ch->asyncflags & ASYNC_CLOSING) {
interruptible_sleep_on(&ch->close_wait);
if (ch->asyncflags & ASYNC_HUP_NOTIFY)
@@ -1027,43 +902,29 @@ static int block_til_ready(struct tty_struct *tty,
return -ERESTARTSYS;
}
- if (filp->f_flags & O_NONBLOCK)
- {
+ if (filp->f_flags & O_NONBLOCK) {
/* -----------------------------------------------------------------
If non-blocking mode is set, then make the check up front
and then exit.
-------------------------------------------------------------------- */
-
ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
-
return 0;
}
-
-
if (tty->termios->c_cflag & CLOCAL)
do_clocal = 1;
-
- /* Block waiting for the carrier detect and the line to become free */
+ /* Block waiting for the carrier detect and the line to become free */
retval = 0;
add_wait_queue(&ch->open_wait, &wait);
- save_flags(flags);
- cli();
-
+ spin_lock_irqsave(&epca_lock, flags);
/* We dec count so that pc_close will know when to free things */
if (!tty_hung_up_p(filp))
ch->count--;
-
- restore_flags(flags);
-
ch->blocked_open++;
-
while(1)
{ /* Begin forever while */
-
set_current_state(TASK_INTERRUPTIBLE);
-
if (tty_hung_up_p(filp) ||
!(ch->asyncflags & ASYNC_INITIALIZED))
{
@@ -1073,17 +934,14 @@ static int block_til_ready(struct tty_struct *tty,
retval = -ERESTARTSYS;
break;
}
-
if (!(ch->asyncflags & ASYNC_CLOSING) &&
(do_clocal || (ch->imodem & ch->dcd)))
break;
-
- if (signal_pending(current))
- {
+ if (signal_pending(current)) {