patch-2.1.16 linux/drivers/char/esp.c
Next file: linux/drivers/char/esp.h
Previous file: linux/drivers/char/Makefile
Back to the patch index
Back to the overall index
- Lines: 795
- Date:
Wed Dec 18 10:47:20 1996
- Orig file:
v2.1.15/linux/drivers/char/esp.c
- Orig date:
Thu Dec 12 19:37:01 1996
diff -u --recursive --new-file v2.1.15/linux/drivers/char/esp.c linux/drivers/char/esp.c
@@ -79,7 +79,7 @@
#define WAKEUP_CHARS 1024
static char *serial_name = "ESP driver";
-static char *serial_version = "1.0";
+static char *serial_version = "1.1";
DECLARE_TASK_QUEUE(tq_esp);
@@ -118,6 +118,7 @@
static void autoconfig(struct esp_struct * info);
static void change_speed(struct esp_struct *info);
+static void rs_wait_until_sent(struct tty_struct *, int);
/*
* This assumes you have a 1.8432 MHz clock for your UART.
@@ -173,11 +174,13 @@
}
/*
- * This is used to figure out the divisor speeds and the timeouts
+ * This is used to figure out the divisor speeds
*/
-static int baud_table[] = {
- 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
- 9600, 19200, 38400, 57600, 115200, 230400, 460800, 0 };
+static int quot_table[] = {
+/* 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, */
+ 0, 18432, 12288, 8378, 6878, 6144, 4608, 3072, 1536, 768,
+/* 1800,2400,4800,9600,19200,38400,57600,115200,230400,460800 */
+ 512, 384, 192, 96, 48, 24, 16, 8, 4, 2, 0 };
static inline unsigned int serial_in(struct esp_struct *info, int offset)
{
@@ -279,17 +282,16 @@
mark_bh(ESP_BH);
}
-static _INLINE_ void receive_chars_dma(struct esp_struct *info, int *dma_bytes,
- int *dma_direction, unsigned int *who_dma)
+static _INLINE_ void receive_chars_dma(struct esp_struct *info, int *dma_bytes)
{
unsigned int num_chars;
if (*dma_bytes) {
- info->stat_flags |= STAT_NEED_DMA;
+ info->stat_flags |= ESP_STAT_NEED_DMA;
return;
}
- info->stat_flags &= ~(STAT_RX_TIMEOUT | STAT_NEED_DMA);
+ info->stat_flags &= ~(ESP_STAT_RX_TIMEOUT | ESP_STAT_NEED_DMA);
serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
serial_out(info, UART_ESI_CMD1, ESI_GET_RX_AVAIL);
@@ -300,8 +302,7 @@
return;
*dma_bytes = num_chars;
- *dma_direction = DMA_MODE_READ;
- *who_dma = info->port;
+ info->stat_flags |= ESP_STAT_DMA_RX;
disable_dma(dma);
clear_dma_ff(dma);
set_dma_mode(dma, DMA_MODE_READ);
@@ -362,18 +363,19 @@
}
static _INLINE_ void receive_chars_dma_done(struct esp_struct *info,
- int *dma_bytes, int *dma_direction, unsigned int *who_dma, int status)
+ int *dma_bytes, int status)
{
struct tty_struct *tty = info->tty;
int num_bytes, bytes_left, x_bytes;
struct tty_flip_buffer *buffer;
- if (!(*dma_bytes) || (*who_dma != info->port))
+ if (!(info->stat_flags & ESP_STAT_DMA_RX))
return;
disable_dma(dma);
clear_dma_ff(dma);
+ info->stat_flags &= ~ESP_STAT_DMA_RX;
num_bytes = *dma_bytes - get_dma_residue(dma);
buffer = &(tty->flip);
@@ -433,22 +435,21 @@
if (*dma_bytes != num_bytes) {
*dma_bytes = 0;
- receive_chars_dma(info, dma_bytes, dma_direction, who_dma);
+ receive_chars_dma(info, dma_bytes);
} else
*dma_bytes = 0;
}
-static _INLINE_ void transmit_chars_dma(struct esp_struct *info, int *dma_bytes,
- int *dma_direction, unsigned int *who_dma)
+static _INLINE_ void transmit_chars_dma(struct esp_struct *info, int *dma_bytes)
{
int count;
if (*dma_bytes) {
- info->stat_flags |= STAT_NEED_DMA;
+ info->stat_flags |= ESP_STAT_NEED_DMA;
return;
}
- info->stat_flags &= ~STAT_NEED_DMA;
+ info->stat_flags &= ~ESP_STAT_NEED_DMA;
if ((info->xmit_cnt <= 0) || info->tty->stopped ||
info->tty->hw_stopped) {
@@ -495,8 +496,7 @@
}
*dma_bytes = count;
- *dma_direction = DMA_MODE_WRITE;
- *who_dma = info->port;
+ info->stat_flags |= ESP_STAT_DMA_TX;
disable_dma(dma);
clear_dma_ff(dma);
set_dma_mode(dma, DMA_MODE_WRITE);
@@ -507,11 +507,11 @@
}
static _INLINE_ void transmit_chars_dma_done(struct esp_struct *info,
- int *dma_bytes, int *dma_direction, unsigned int *who_dma)
+ int *dma_bytes)
{
int num_bytes;
- if (!(*dma_bytes) || (*who_dma != info->port))
+ if (!(info->stat_flags & ESP_STAT_DMA_TX))
return;
disable_dma(dma);
@@ -523,7 +523,6 @@
{
*dma_bytes -= num_bytes;
memmove(dma_buffer, dma_buffer + num_bytes, *dma_bytes);
- *dma_direction = DMA_MODE_WRITE;
disable_dma(dma);
clear_dma_ff(dma);
set_dma_mode(dma, DMA_MODE_WRITE);
@@ -531,8 +530,10 @@
set_dma_count(dma, *dma_bytes);
enable_dma(dma);
serial_out(info, UART_ESI_CMD1, ESI_START_DMA_TX);
- } else
+ } else {
*dma_bytes = 0;
+ info->stat_flags &= ~ESP_STAT_DMA_TX;
+ }
}
static _INLINE_ void check_modem_status(struct esp_struct *info)
@@ -607,8 +608,6 @@
int pre_bytes;
int check_dma_only = 0;
static int dma_bytes;
- static int dma_direction;
- static int who_dma;
#ifdef SERIAL_DEBUG_INTR
printk("rs_interrupt_single(%d)...", irq);
@@ -624,7 +623,7 @@
do {
if (!info->tty || (check_dma_only &&
- !(info->stat_flags & STAT_NEED_DMA))) {
+ !(info->stat_flags & ESP_STAT_NEED_DMA))) {
info = info->next_port;
continue;
}
@@ -638,7 +637,7 @@
err_status |= serial_in(info, UART_ESI_STAT2);
if (err_status & 0x0100)
- info->stat_flags |= STAT_RX_TIMEOUT;
+ info->stat_flags |= ESP_STAT_RX_TIMEOUT;
if (err_status & 0x2000) /* UART status */
check_modem_status(info);
@@ -654,23 +653,19 @@
}
if ((scratch & 0x88) || /* DMA completed or timed out */
- (err_status & 0x1c00) /* receive error */)
- if (dma_direction == DMA_MODE_READ)
+ (err_status & 0x1c00) /* receive error */) {
receive_chars_dma_done(info, &dma_bytes,
- &dma_direction, &who_dma, err_status);
- else
- transmit_chars_dma_done(info, &dma_bytes,
- &dma_direction, &who_dma);
+ err_status);
+ transmit_chars_dma_done(info, &dma_bytes);
+ }
if (((scratch & 0x01) ||
- (info->stat_flags & STAT_RX_TIMEOUT)) &&
+ (info->stat_flags & ESP_STAT_RX_TIMEOUT)) &&
(info->IER & UART_IER_RDI))
- receive_chars_dma(info, &dma_bytes, &dma_direction,
- &who_dma);
+ receive_chars_dma(info, &dma_bytes);
if ((scratch & 0x02) && (info->IER & UART_IER_THRI))
- transmit_chars_dma(info, &dma_bytes, &dma_direction,
- &who_dma);
+ transmit_chars_dma(info, &dma_bytes);
info->last_active = jiffies;
@@ -815,7 +810,7 @@
return 0;
}
- if (!info->port || !info->type) {
+ if (!info->port) {
if (info->tty)
set_bit(TTY_IO_ERROR, &info->tty->flags);
restore_flags(flags);
@@ -916,10 +911,8 @@
}
info->MCR = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
- info->MCR_noint = UART_MCR_DTR | UART_MCR_RTS;
#if defined(__alpha__) && !defined(CONFIG_PCI)
info->MCR |= UART_MCR_OUT1 | UART_MCR_OUT2;
- info->MCR_noint |= UART_MCR_OUT1 | UART_MCR_OUT2;
#endif
serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
@@ -1060,14 +1053,13 @@
serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
serial_out(info, UART_ESI_CMD2, 0x00);
- if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
+ if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
- info->MCR_noint &= ~(UART_MCR_DTR|UART_MCR_RTS);
- }
+ info->MCR &= ~UART_MCR_OUT2;
serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
serial_out(info, UART_ESI_CMD2, UART_MCR);
- serial_out(info, UART_ESI_CMD2, info->MCR_noint);
+ serial_out(info, UART_ESI_CMD2, info->MCR);
if (info->tty)
set_bit(TTY_IO_ERROR, &info->tty->flags);
@@ -1085,8 +1077,9 @@
unsigned short port;
int quot = 0;
unsigned cflag,cval;
- int i;
+ int i, bits;
unsigned char flow1 = 0, flow2 = 0;
+ unsigned long flags;
if (!info->tty || !info->tty->termios)
return;
@@ -1113,53 +1106,36 @@
if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
quot = info->custom_divisor;
}
- if (quot) {
- info->timeout = ((1024*HZ*15*quot) /
- info->baud_base) + 2;
- } else if (baud_table[i] == 134) {
- quot = (2*info->baud_base / 269);
- info->timeout = (1024*HZ*30/269) + 2;
- } else if (baud_table[i]) {
- quot = info->baud_base / baud_table[i];
- info->timeout = (1024*HZ*15/baud_table[i]) + 2;
- } else {
- quot = 0;
- info->timeout = 0;
- }
- if (quot) {
- info->MCR |= UART_MCR_DTR;
- info->MCR_noint |= UART_MCR_DTR;
- cli();
- serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
- serial_out(info, UART_ESI_CMD2, UART_MCR);
- serial_out(info, UART_ESI_CMD2, info->MCR);
- sti();
- } else {
- info->MCR &= ~UART_MCR_DTR;
- info->MCR_noint &= ~UART_MCR_DTR;
- cli();
- serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
- serial_out(info, UART_ESI_CMD2, UART_MCR);
- serial_out(info, UART_ESI_CMD2, info->MCR);
- sti();
- return;
- }
+
/* byte size and parity */
switch (cflag & CSIZE) {
- case CS5: cval = 0x00; break;
- case CS6: cval = 0x01; break;
- case CS7: cval = 0x02; break;
- case CS8: cval = 0x03; break;
- default: cval = 0x00; break; /* too keep GCC shut... */
+ case CS5: cval = 0x00; bits = 7; break;
+ case CS6: cval = 0x01; bits = 8; break;
+ case CS7: cval = 0x02; bits = 9; break;
+ case CS8: cval = 0x03; bits = 10; break;
+ default: cval = 0x00; bits = 7; break;
}
if (cflag & CSTOPB) {
cval |= 0x04;
+ bits++;
}
- if (cflag & PARENB)
+ if (cflag & PARENB) {
cval |= UART_LCR_PARITY;
+ bits++;
+ }
if (!(cflag & PARODD))
cval |= UART_LCR_EPAR;
+ if (!quot) {
+ quot = quot_table[i];
+
+ /* default to 9600 bps */
+ if (!quot)
+ quot = BASE_BAUD / 9600;
+ }
+
+ info->timeout = ((1024 * HZ * bits * quot) / BASE_BAUD) + (HZ / 50);
+
/* CTS flow control flag and modem status interrupts */
/* info->IER &= ~UART_IER_MSI; */
if (cflag & CRTSCTS) {
@@ -1213,7 +1189,7 @@
if (I_IXOFF(info->tty))
flow1 |= 0x81;
- cli();
+ save_flags(flags); cli();
/* set baud */
serial_out(info, UART_ESI_CMD1, ESI_SET_BAUD);
serial_out(info, UART_ESI_CMD2, quot >> 8);
@@ -1260,7 +1236,7 @@
serial_out(info, UART_ESI_CMD2, (trigger + 4) / 256);
serial_out(info, UART_ESI_CMD2, (trigger + 4) % 256);
- sti();
+ restore_flags(flags);
}
static void rs_put_char(struct tty_struct *tty, unsigned char ch)
@@ -1459,12 +1435,12 @@
if (!retinfo)
return -EFAULT;
memset(&tmp, 0, sizeof(tmp));
- tmp.type = info->type;
+ tmp.type = PORT_16550A;
tmp.line = info->line;
tmp.port = info->port;
tmp.irq = info->irq;
tmp.flags = info->flags;
- tmp.baud_base = info->baud_base;
+ tmp.baud_base = BASE_BAUD;
tmp.close_delay = info->close_delay;
tmp.closing_wait = info->closing_wait;
tmp.custom_divisor = info->custom_divisor;
@@ -1479,7 +1455,7 @@
struct serial_struct new_serial;
struct esp_struct old_info;
unsigned int change_irq;
- int retval = 0;
+ int i, retval = 0;
struct esp_struct *current_async;
unsigned long flags = 0;
@@ -1488,10 +1464,10 @@
copy_from_user(&new_serial,new_info,sizeof(new_serial));
old_info = *info;
- if ((info->type != new_serial.type) ||
+ if ((new_serial.type != PORT_16550A) ||
(new_serial.hub6) ||
(info->port != new_serial.port) ||
- (info->baud_base != new_serial.baud_base) ||
+ (new_serial.baud_base != BASE_BAUD) ||
(new_serial.irq > 15) ||
(new_serial.irq < 1))
return -EINVAL;
@@ -1503,7 +1479,6 @@
if (!suser()) {
if (change_irq ||
- (new_serial.baud_base != info->baud_base) ||
(new_serial.close_delay != info->close_delay) ||
((new_serial.flags & ~ASYNC_USR_MASK) !=
(info->flags & ~ASYNC_USR_MASK)))
@@ -1519,24 +1494,31 @@
if (change_irq) {
save_flags(flags); cli();
+ i = 1;
- current_async = info;
- do {
- if ((current_async->line >= info->line) &&
- (current_async->line < (info->line + 8))) {
- if (current_async == info) {
- if (current_async->count > 1) {
+ while ((i < 16) && !IRQ_ports[i])
+ i++;
+
+ if (i < 16) {
+ current_async = IRQ_ports[i];
+
+ do {
+ if ((current_async->line >= info->line) &&
+ (current_async->line < (info->line + 8))) {
+ if (current_async == info) {
+ if (current_async->count > 1) {
+ restore_flags(flags);
+ return -EBUSY;
+ }
+ } else {
restore_flags(flags);
return -EBUSY;
}
- } else {
- restore_flags(flags);
- return -EBUSY;
}
- }
-
- current_async = current_async->next_port;
- } while (current_async != info);
+
+ current_async = current_async->next_port;
+ } while (current_async != IRQ_ports[i]);
+ }
}
/*
@@ -1544,14 +1526,12 @@
* At this point, we start making changes.....
*/
- info->baud_base = new_serial.baud_base;
info->flags = ((info->flags & ~ASYNC_FLAGS) |
(new_serial.flags & ASYNC_FLAGS));
info->custom_divisor = new_serial.custom_divisor;
info->close_delay = new_serial.close_delay * HZ/100;
info->closing_wait = new_serial.closing_wait * HZ/100;
- release_region(info->port,8);
if (change_irq) {
/*
* We need to shutdown the serial port at the old
@@ -1576,12 +1556,9 @@
restore_flags(flags);
}
- if(info->type != PORT_UNKNOWN)
- request_region(info->port,8,"esp(set)");
-
check_and_exit:
- if (!info->port || !info->type)
+ if (!info->port)
return 0;
if (info->flags & ASYNC_INITIALIZED) {
if (((old_info.flags & ASYNC_SPD_MASK) !=
@@ -1649,33 +1626,21 @@
switch (cmd) {
case TIOCMBIS:
- if (arg & TIOCM_RTS) {
+ if (arg & TIOCM_RTS)
info->MCR |= UART_MCR_RTS;
- info->MCR_noint |= UART_MCR_RTS;
- }
- if (arg & TIOCM_DTR) {
+ if (arg & TIOCM_DTR)
info->MCR |= UART_MCR_DTR;
- info->MCR_noint |= UART_MCR_DTR;
- }
break;
case TIOCMBIC:
- if (arg & TIOCM_RTS) {
+ if (arg & TIOCM_RTS)
info->MCR &= ~UART_MCR_RTS;
- info->MCR_noint &= ~UART_MCR_RTS;
- }
- if (arg & TIOCM_DTR) {
+ if (arg & TIOCM_DTR)
info->MCR &= ~UART_MCR_DTR;
- info->MCR_noint &= ~UART_MCR_DTR;
- }
break;
case TIOCMSET:
info->MCR = ((info->MCR & ~(UART_MCR_RTS | UART_MCR_DTR))
| ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
| ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
- info->MCR_noint = ((info->MCR_noint
- & ~(UART_MCR_RTS | UART_MCR_DTR))
- | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
- | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
break;
default:
return -EINVAL;
@@ -1688,29 +1653,6 @@
return 0;
}
-static int do_autoconfig(struct esp_struct * info)
-{
- int retval;
-
- if (!suser())
- return -EPERM;
-
- if (info->count > 1)
- return -EBUSY;
-
- shutdown(info);
-
- cli();
- autoconfig(info);
- sti();
-
- retval = startup(info);
- if (retval)
- return retval;
- return 0;
-}
-
-
/*
* This routine sends a break character out the serial port.
*/
@@ -1759,15 +1701,24 @@
if (retval)
return retval;
tty_wait_until_sent(tty, 0);
- if (!arg)
+ if (current->signal & ~current->blocked)
+ return -EINTR;
+ if (!arg) {
send_break(info, HZ/4); /* 1/4 second */
+ if (current->signal & ~current->blocked)
+ return -EINTR;
+ }
return 0;
case TCSBRKP: /* support for POSIX tcsendbreak() */
retval = tty_check_change(tty);
if (retval)
return retval;
tty_wait_until_sent(tty, 0);
+ if (current->signal & ~current->blocked)
+ return -EINTR;
send_break(info, arg ? arg*(HZ/10) : HZ/4);
+ if (current->signal & ~current->blocked)
+ return -EINTR;
return 0;
case TIOCGSOFTCAR:
return put_user(C_CLOCAL(tty) ? 1 : 0,
@@ -1801,7 +1752,8 @@
return set_serial_info(info,
(struct serial_struct *) arg);
case TIOCSERCONFIG:
- return do_autoconfig(info);
+ /* do not reconfigure after initial configuration */
+ return 0;
case TIOCSERGWILD:
return put_user(0L, (unsigned long *) arg);
@@ -1884,6 +1836,32 @@
change_speed(info);
+ /* Handle transition to B0 status */
+ if ((old_termios->c_cflag & CBAUD) &&
+ !(tty->termios->c_cflag & CBAUD)) {
+ info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
+ cli();
+ serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
+ serial_out(info, UART_ESI_CMD2, UART_MCR);
+ serial_out(info, UART_ESI_CMD2, info->MCR);
+ sti();
+ }
+
+ /* Handle transition away from B0 status */
+ if (!(old_termios->c_cflag & CBAUD) &&
+ (tty->termios->c_cflag & CBAUD)) {
+ info->MCR |= UART_MCR_DTR;
+ if (!tty->hw_stopped ||
+ !(tty->termios->c_cflag & CRTSCTS))
+ info->MCR |= UART_MCR_RTS;
+ cli();
+ serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
+ serial_out(info, UART_ESI_CMD2, UART_MCR);
+ serial_out(info, UART_ESI_CMD2, info->MCR);
+ sti();
+ }
+
+ /* Handle turning of CRTSCTS */
if ((old_termios->c_cflag & CRTSCTS) &&
!(tty->termios->c_cflag & CRTSCTS)) {
tty->hw_stopped = 0;
@@ -1917,7 +1895,6 @@
{
struct esp_struct * info = (struct esp_struct *)tty->driver_data;
unsigned long flags;
- unsigned long timeout;
if (!info || serial_paranoia_check(info, tty->device, "rs_close"))
return;
@@ -1995,19 +1972,7 @@
* has completely drained; this is especially
* important if there is a transmit FIFO!
*/
- timeout = jiffies+HZ;
- serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
- serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL);
- while ((serial_in(info, UART_ESI_STAT1) != 0x03) ||
- (serial_in(info, UART_ESI_STAT2) != 0xff)) {
- current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + info->timeout;
- schedule();
- if (jiffies > timeout)
- break;
- serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
- serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL);
- }
+ rs_wait_until_sent(tty, info->timeout);
}
shutdown(info);
if (tty->driver.flush_buffer)
@@ -2044,6 +2009,46 @@
restore_flags(flags);
}
+static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+ struct esp_struct *info = (struct esp_struct *)tty->driver_data;
+ unsigned long orig_jiffies, char_time;
+ unsigned long flags;
+
+ if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent"))
+ return;
+
+ orig_jiffies = jiffies;
+ char_time = ((info->timeout - HZ / 50) / 1024) / 5;
+
+ if (!char_time)
+ char_time = 1;
+
+ save_flags(flags); cli();
+ serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
+ serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL);
+
+ while ((serial_in(info, UART_ESI_STAT1) != 0x03) ||
+ (serial_in(info, UART_ESI_STAT2) != 0xff)) {
+ current->state = TASK_INTERRUPTIBLE;
+ current->counter = 0;
+ current->timeout = jiffies + char_time;
+ schedule();
+
+ if (current->signal & ~current->blocked)
+ break;
+
+ if (timeout && ((orig_jiffies + timeout) < jiffies))
+ break;
+
+ serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
+ serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL);
+ }
+
+ restore_flags(flags);
+ current->state = TASK_RUNNING;
+}
+
/*
* esp_hangup() --- called by tty_hangup() when a hangup is signaled.
*/
@@ -2152,7 +2157,8 @@
info->blocked_open++;
while (1) {
cli();
- if (!(info->flags & ASYNC_CALLOUT_ACTIVE)) {
+ if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
+ (tty->termios->c_cflag & CBAUD)) {
unsigned int scratch;
serial_out(info, UART_ESI_CMD1, ESI_READ_UART);
@@ -2342,8 +2348,6 @@
unsigned port = info->port;
unsigned long flags;
- info->type = PORT_UNKNOWN;
-
if (!port)
return;
@@ -2360,6 +2364,7 @@
status2 = status1 & 0x70;
if (status2 != 0x20) {
printk(" Old ESP found at %x\n",info->port);
+ info->port = 0;
} else {
serial_out(info, UART_ESI_CMD1, 0x02);
status1 = serial_in(info, UART_ESI_STAT1) & 0x03;
@@ -2369,8 +2374,7 @@
else
info->irq = 3;
}
- info->type = PORT_16550A;
- request_region(port,8,"esp(auto)");
+ request_region(port,8,"esp");
/* put card in enhanced mode */
/* this prevents access through */
@@ -2382,6 +2386,8 @@
serial_out(info, UART_ESI_CMD2, UART_MCR);
serial_out(info, UART_ESI_CMD2, 0x00);
}
+ } else {
+ info->port = 0;
}
restore_flags(flags);
@@ -2444,6 +2450,7 @@
esp_driver.stop = rs_stop;
esp_driver.start = rs_start;
esp_driver.hangup = esp_hangup;
+ esp_driver.wait_until_sent = rs_wait_until_sent;
/*
* The callout device is just like normal device except for
@@ -2470,7 +2477,22 @@
do {
info->port = esp[i] + offset;
- info->baud_base = BASE_BAUD;
+
+ /* check if i/o region is already in use */
+ if (check_region(info->port, 8)) {
+ /* if it is a primary port, skip secondary ports */
+ if (!offset)
+ i++;
+ else if (offset == 56) {
+ i++;
+ offset = 0;
+ }
+ else
+ offset += 8;
+
+ continue;
+ }
+
info->custom_divisor = (divisor[i] >> (offset / 2)) & 0xf;
info->flags = STD_COM_FLAGS;
if (info->custom_divisor)
@@ -2480,7 +2502,6 @@
info->magic = ESP_MAGIC;
info->line = (i * 8) + (offset / 8);
info->tty = 0;
- info->type = PORT_UNKNOWN;
info->close_delay = 5*HZ/10;
info->closing_wait = 30*HZ;
info->tqueue.routine = do_softint;
@@ -2494,7 +2515,7 @@
info->irq = 9;
autoconfig(info);
- if (info->type == PORT_UNKNOWN) {
+ if (!info->port) {
i++;
offset = 0;
continue;
@@ -2559,8 +2580,7 @@
current_async = IRQ_ports[0];
while (current_async != 0) {
- if (current_async->type != PORT_UNKNOWN)
- release_region(current_async->port, 8);
+ release_region(current_async->port, 8);
current_async = current_async->next_port;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov