Commit d9a9168b authored by Marcelo Tosatti's avatar Marcelo Tosatti Committed by Trond Myklebust

[PATCH] Fix pc300_tty.c -> implement tiocmset/tiocmget

PC300 MLPPP support is currently marked broken in 2.6.x.

To fix that, attached patch implements tiocmset/tiocmget methods on the
pc300_tty.c driver, which is the new method tty drivers are supposed to
use instead ioctl.

This fixes two related issues in the ioctl handler:

- ioctl requesting RTS signal would affect DTR signal
- The RTS signal is now handled.

Bonus: Throw out unused ioctl handler
parent 9c07b6c6
...@@ -382,7 +382,7 @@ config PC300 ...@@ -382,7 +382,7 @@ config PC300
config PC300_MLPPP config PC300_MLPPP
bool "Cyclades-PC300 MLPPP support" bool "Cyclades-PC300 MLPPP support"
depends on PC300 && PPP_MULTILINK && PPP_SYNC_TTY && HDLC_PPP && BROKEN depends on PC300 && PPP_MULTILINK && PPP_SYNC_TTY && HDLC_PPP
help help
Say 'Y' to this option if you are planning to use Multilink PPP over the Say 'Y' to this option if you are planning to use Multilink PPP over the
PC300 synchronous communication boards. PC300 synchronous communication boards.
......
...@@ -124,16 +124,18 @@ static int cpc_tty_write(struct tty_struct *tty, int from_user, ...@@ -124,16 +124,18 @@ static int cpc_tty_write(struct tty_struct *tty, int from_user,
const unsigned char *buf, int count); const unsigned char *buf, int count);
static int cpc_tty_write_room(struct tty_struct *tty); static int cpc_tty_write_room(struct tty_struct *tty);
static int cpc_tty_chars_in_buffer(struct tty_struct *tty); static int cpc_tty_chars_in_buffer(struct tty_struct *tty);
static int cpc_tty_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);
static void cpc_tty_flush_buffer(struct tty_struct *tty); static void cpc_tty_flush_buffer(struct tty_struct *tty);
static void cpc_tty_hangup(struct tty_struct *tty); static void cpc_tty_hangup(struct tty_struct *tty);
static void cpc_tty_rx_work(void *data); static void cpc_tty_rx_work(void *data);
static void cpc_tty_tx_work(void *data); static void cpc_tty_tx_work(void *data);
static int cpc_tty_send_to_card(pc300dev_t *dev,void *buf, int len); static int cpc_tty_send_to_card(pc300dev_t *dev,void *buf, int len);
static void cpc_tty_trace(pc300dev_t *dev, char* buf, int len, char rxtx); static void cpc_tty_trace(pc300dev_t *dev, char* buf, int len, char rxtx);
static void cpc_tty_dtr_off(pc300dev_t *pc300dev); static void cpc_tty_signal_off(pc300dev_t *pc300dev, unsigned char);
static void cpc_tty_dtr_on(pc300dev_t *pc300dev); static void cpc_tty_signal_on(pc300dev_t *pc300dev, unsigned char);
int pc300_tiocmset(struct tty_struct *, struct file *,
unsigned int, unsigned int);
int pc300_tiocmget(struct tty_struct *, struct file *);
/* functions called by PC300 driver */ /* functions called by PC300 driver */
void cpc_tty_init(pc300dev_t *dev); void cpc_tty_init(pc300dev_t *dev);
...@@ -143,38 +145,38 @@ void cpc_tty_trigger_poll(pc300dev_t *pc300dev); ...@@ -143,38 +145,38 @@ void cpc_tty_trigger_poll(pc300dev_t *pc300dev);
void cpc_tty_reset_var(void); void cpc_tty_reset_var(void);
/* /*
* PC300 TTY clear DTR signal * PC300 TTY clear "signal"
*/ */
static void cpc_tty_dtr_off(pc300dev_t *pc300dev) static void cpc_tty_signal_off(pc300dev_t *pc300dev, unsigned char signal)
{ {
pc300ch_t *pc300chan = (pc300ch_t *)pc300dev->chan; pc300ch_t *pc300chan = (pc300ch_t *)pc300dev->chan;
pc300_t *card = (pc300_t *) pc300chan->card; pc300_t *card = (pc300_t *) pc300chan->card;
int ch = pc300chan->channel; int ch = pc300chan->channel;
unsigned long flags; unsigned long flags;
CPC_TTY_DBG("%s-tty: Clear signal DTR\n", CPC_TTY_DBG("%s-tty: Clear signal %x\n",
((struct net_device*)(pc300dev->hdlc))->name); ((struct net_device*)(pc300dev->hdlc))->name, signal);
CPC_TTY_LOCK(card, flags); CPC_TTY_LOCK(card, flags);
cpc_writeb(card->hw.scabase + M_REG(CTL,ch), cpc_writeb(card->hw.scabase + M_REG(CTL,ch),
cpc_readb(card->hw.scabase+M_REG(CTL,ch))& CTL_DTR); cpc_readb(card->hw.scabase+M_REG(CTL,ch))& signal);
CPC_TTY_UNLOCK(card,flags); CPC_TTY_UNLOCK(card,flags);
} }
/* /*
* PC300 TTY set DTR signal to ON * PC300 TTY set "signal" to ON
*/ */
static void cpc_tty_dtr_on(pc300dev_t *pc300dev) static void cpc_tty_signal_on(pc300dev_t *pc300dev, unsigned char signal)
{ {
pc300ch_t *pc300chan = (pc300ch_t *)pc300dev->chan; pc300ch_t *pc300chan = (pc300ch_t *)pc300dev->chan;
pc300_t *card = (pc300_t *) pc300chan->card; pc300_t *card = (pc300_t *) pc300chan->card;
int ch = pc300chan->channel; int ch = pc300chan->channel;
unsigned long flags; unsigned long flags;
CPC_TTY_DBG("%s-tty: Set signal DTR\n", CPC_TTY_DBG("%s-tty: Set signal %x\n",
((struct net_device*)(pc300dev->hdlc))->name); ((struct net_device*)(pc300dev->hdlc))->name, signal);
CPC_TTY_LOCK(card, flags); CPC_TTY_LOCK(card, flags);
cpc_writeb(card->hw.scabase + M_REG(CTL,ch), cpc_writeb(card->hw.scabase + M_REG(CTL,ch),
cpc_readb(card->hw.scabase+M_REG(CTL,ch))& ~CTL_DTR); cpc_readb(card->hw.scabase+M_REG(CTL,ch))& ~signal);
CPC_TTY_UNLOCK(card,flags); CPC_TTY_UNLOCK(card,flags);
} }
...@@ -229,7 +231,8 @@ void cpc_tty_init(pc300dev_t *pc300dev) ...@@ -229,7 +231,8 @@ void cpc_tty_init(pc300dev_t *pc300dev)
serial_drv.write = cpc_tty_write; serial_drv.write = cpc_tty_write;
serial_drv.write_room = cpc_tty_write_room; serial_drv.write_room = cpc_tty_write_room;
serial_drv.chars_in_buffer = cpc_tty_chars_in_buffer; serial_drv.chars_in_buffer = cpc_tty_chars_in_buffer;
serial_drv.ioctl = cpc_tty_ioctl; serial_drv.tiocmset = pc300_tiocmset;
serial_drv.tiocmget = pc300_tiocmget;
serial_drv.flush_buffer = cpc_tty_flush_buffer; serial_drv.flush_buffer = cpc_tty_flush_buffer;
serial_drv.hangup = cpc_tty_hangup; serial_drv.hangup = cpc_tty_hangup;
...@@ -270,7 +273,7 @@ void cpc_tty_init(pc300dev_t *pc300dev) ...@@ -270,7 +273,7 @@ void cpc_tty_init(pc300dev_t *pc300dev)
memcpy(&cpc_tty->name[aux], "-tty", 5); memcpy(&cpc_tty->name[aux], "-tty", 5);
cpc_open((struct net_device *)pc300dev->hdlc); cpc_open((struct net_device *)pc300dev->hdlc);
cpc_tty_dtr_off(pc300dev); cpc_tty_signal_off(pc300dev, CTL_DTR);
CPC_TTY_DBG("%s: Initializing TTY Sync Driver, tty major#%d minor#%i\n", CPC_TTY_DBG("%s: Initializing TTY Sync Driver, tty major#%d minor#%i\n",
cpc_tty->name,CPC_TTY_MAJOR,cpc_tty->tty_minor); cpc_tty->name,CPC_TTY_MAJOR,cpc_tty->tty_minor);
...@@ -332,7 +335,7 @@ static int cpc_tty_open(struct tty_struct *tty, struct file *flip) ...@@ -332,7 +335,7 @@ static int cpc_tty_open(struct tty_struct *tty, struct file *flip)
cpc_tty_area[port].tty = tty; cpc_tty_area[port].tty = tty;
tty->driver_data = &cpc_tty_area[port]; tty->driver_data = &cpc_tty_area[port];
cpc_tty_dtr_on(cpc_tty->pc300dev); cpc_tty_signal_on(cpc_tty->pc300dev, CTL_DTR);
} }
cpc_tty->num_open++; cpc_tty->num_open++;
...@@ -379,7 +382,7 @@ static void cpc_tty_close(struct tty_struct *tty, struct file *flip) ...@@ -379,7 +382,7 @@ static void cpc_tty_close(struct tty_struct *tty, struct file *flip)
return; return;
} }
cpc_tty_dtr_off(cpc_tty->pc300dev); cpc_tty_signal_off(cpc_tty->pc300dev, CTL_DTR);
CPC_TTY_LOCK(cpc_tty->pc300dev->chan->card, flags); /* lock irq */ CPC_TTY_LOCK(cpc_tty->pc300dev->chan->card, flags); /* lock irq */
cpc_tty->tty = NULL; cpc_tty->tty = NULL;
...@@ -556,18 +559,13 @@ static int cpc_tty_chars_in_buffer(struct tty_struct *tty) ...@@ -556,18 +559,13 @@ static int cpc_tty_chars_in_buffer(struct tty_struct *tty)
return(0); return(0);
} }
/* int pc300_tiocmset(struct tty_struct *tty, struct file *file,
* PC300 TTY IOCTL routine unsigned int set, unsigned int clear)
*
* This routine treats TIOCMBIS (set DTR signal) and TIOCMBIC (clear DTR
* signal)IOCTL commands.
*/
static int cpc_tty_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{ {
st_cpc_tty_area *cpc_tty; st_cpc_tty_area *cpc_tty;
CPC_TTY_DBG("%s: set:%x clear:%x\n", __FUNCTION__, set, clear);
if (!tty || !tty->driver_data ) { if (!tty || !tty->driver_data ) {
CPC_TTY_DBG("hdlcX-tty: no TTY to chars in buffer\n"); CPC_TTY_DBG("hdlcX-tty: no TTY to chars in buffer\n");
return -ENODEV; return -ENODEV;
...@@ -575,27 +573,45 @@ static int cpc_tty_ioctl(struct tty_struct *tty, struct file *file, ...@@ -575,27 +573,45 @@ static int cpc_tty_ioctl(struct tty_struct *tty, struct file *file,
cpc_tty = (st_cpc_tty_area *) tty->driver_data; cpc_tty = (st_cpc_tty_area *) tty->driver_data;
if ((cpc_tty->tty != tty) || (cpc_tty->state != CPC_TTY_ST_OPEN)) { if (set & TIOCM_RTS)
CPC_TTY_DBG("%s: TTY is not opened\n",cpc_tty->name); cpc_tty_signal_on(cpc_tty->pc300dev, CTL_RTS);
return -ENODEV; if (set & TIOCM_DTR)
} cpc_tty_signal_on(cpc_tty->pc300dev, CTL_DTR);
CPC_TTY_DBG("%s: IOCTL cmd %x\n",cpc_tty->name,cmd); if (clear & TIOCM_RTS)
cpc_tty_signal_off(cpc_tty->pc300dev, CTL_RTS);
if (clear & TIOCM_DTR)
cpc_tty_signal_off(cpc_tty->pc300dev, CTL_DTR);
switch (cmd) {
case TIOCMBIS : /* set DTR */
cpc_tty_dtr_on(cpc_tty->pc300dev);
break;
case TIOCMBIC: /* clear DTR */
cpc_tty_dtr_off(cpc_tty->pc300dev);
break;
default :
return -ENOIOCTLCMD;
}
return 0; return 0;
} }
int pc300_tiocmget(struct tty_struct *tty, struct file *file)
{
unsigned int result;
unsigned char status;
unsigned long flags;
st_cpc_tty_area *cpc_tty = (st_cpc_tty_area *) tty->driver_data;
pc300dev_t *pc300dev = cpc_tty->pc300dev;
pc300ch_t *pc300chan = (pc300ch_t *)pc300dev->chan;
pc300_t *card = (pc300_t *) pc300chan->card;
int ch = pc300chan->channel;
cpc_tty = (st_cpc_tty_area *) tty->driver_data;
CPC_TTY_DBG("%s-tty: tiocmget\n",
((struct net_device*)(pc300dev->hdlc))->name);
CPC_TTY_LOCK(card, flags);
status = cpc_readb(card->hw.scabase+M_REG(CTL,ch));
CPC_TTY_UNLOCK(card,flags);
result = ((status & CTL_DTR) ? TIOCM_DTR : 0) |
((status & CTL_RTS) ? TIOCM_RTS : 0);
return result;
}
/* /*
* PC300 TTY Flush Buffer routine * PC300 TTY Flush Buffer routine
* *
...@@ -660,7 +676,7 @@ static void cpc_tty_hangup(struct tty_struct *tty) ...@@ -660,7 +676,7 @@ static void cpc_tty_hangup(struct tty_struct *tty)
cpc_tty->name,res); cpc_tty->name,res);
} }
} }
cpc_tty_dtr_off(cpc_tty->pc300dev); cpc_tty_signal_off(cpc_tty->pc300dev, CTL_DTR);
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment