This patch was applied to a 2.4.7 kernel.
Caleb
--- ./drivers/char/serial_orig.bak	Fri Aug 10 08:22:13 2001
+++ ./drivers/char/serial.c	Fri Aug 10 09:41:36 2001
@@ -57,10 +57,12 @@
  * 10/00: add in optional software flow control for serial console.
  *	  Kanoj Sarcar <kanoj@sgi.com>  (Modified by Theodore Ts'o)
  *
+ *  8/01: added support for ConnectTech Blueheat PCI boards (RS485
+ *        support) <caleb@aei-tech.com>
  */
-static char *serial_version = "5.05c";
-static char *serial_revdate = "2001-07-08";
+static char *serial_version = "5.05d";
+static char *serial_revdate = "2001-08-10";
 /*
  * Serial driver configuration section.  Here are the various options:
@@ -1417,6 +1419,9 @@
 	 */
 	mod_timer(&serial_timer, jiffies + 2*HZ/100);
+	if (state->lmode_fn)
+	  (state->lmode_fn)(state,TIOCSER485SET,NULL);
+
 	/*
 	 * Set up the tty->alt_speed kludge
 	 */
@@ -2523,6 +2528,7 @@
 		    unsigned int cmd, unsigned long arg)
 {
 	struct async_struct * info = (struct async_struct *)tty->driver_data;
+	struct serial_state * state = info->state;
 	struct async_icount cprev, cnow;	/* kernel counter temps */
 	struct serial_icounter_struct icount;
 	unsigned long flags;
@@ -2580,6 +2586,10 @@
 				 (tmp ? CLOCAL : 0));
 			return 0;
 #endif
+	case TIOCSER485GET:
+	case TIOCSER485SET:
+	  if (state->lmode_fn)
+	    return (state->lmode_fn)(state, cmd, (unsigned int *) arg);
 		case TIOCMGET:
 			return get_modem_info(info, (unsigned int *) arg);
 		case TIOCMBIS:
@@ -3985,6 +3995,7 @@
 		if (line < 0)
 			break;
 		rs_table[line].baud_base = base_baud;
+		rs_table[line].lmode_fn = board->lmode_fn;
 		rs_table[line].dev = dev;
 	}
 }
@@ -4138,6 +4149,131 @@
 }
 /*
+ * These functions allow for setting for half, full, and slave duplex on
+ * ConnectTech Blueheat PCI multiport boards.  cti485 does the work.
+ * _2 and _4 do checking for the hybrid boards.
+ * They rely on the fact that the ports will start at a 256 aligned
+ * address to calculate which port on the board it is.
+ */
+
+static int pci_cti485_fn(struct serial_state *state, int ioctl,
+			 unsigned int *value) {
+
+        static unsigned char done_init = 0;
+	struct async_struct *info;
+	unsigned char port_offset;
+	unsigned char portmask;
+	unsigned char txctl_offset;
+	unsigned char rxctl_offset;
+	unsigned char differ_offset;
+	unsigned char bits;
+	unsigned long flags;
+
+	if (ioctl == TIOCSER485GET)
+		return put_user(state->lmode, value);
+
+	info = state->info;
+	port_offset = state->port % 0x100;
+	portmask = 1 << port_offset / 0x08;
+	txctl_offset = 0x6c - port_offset;
+	rxctl_offset = 0x70 - port_offset;
+
+	save_flags(flags); cli();
+	if (value)
+		state->lmode = *value;
+	else if (!done_init) {
+		differ_offset = 0x74 - port_offset;
+		bits = serial_in(info, differ_offset);
+		switch (bits) {
+			case 0x03:
+				state->lmode = TIOCSER485SLAVEMULTIPLEX;
+				break;
+			default:
+				state->lmode = TIOCSER485FULLDUPLEX;
+				break;
+		}
+	}
+	done_init = 1;
+	bits = serial_in(info, txctl_offset);
+	switch (state->lmode) {
+		default:
+		case TIOCSER485FULLDUPLEX:
+			bits &= ~portmask;
+			serial_out(info, txctl_offset, bits);
+
+			bits = serial_in(info, rxctl_offset);
+			bits |= portmask;
+			serial_out(info, rxctl_offset, bits);
+
+			serial_out(info, UART_LCR, 0xbf);
+			bits = serial_in(info, UART_FCTR);
+			bits &= ~UART_FCTR_TX_INT;
+			serial_out(info, UART_FCTR, bits);
+			serial_out(info, UART_LCR, 0);
+
+			restore_flags(flags);
+			return put_user(1, value);
+		case TIOCSER485HALFDUPLEX:
+			bits |= portmask;
+			serial_out(info, txctl_offset, bits);
+
+			bits = serial_in(info, rxctl_offset);
+			bits &= ~portmask;
+			serial_out(info, rxctl_offset, bits);
+
+			serial_out(info, UART_LCR, 0xbf);
+			bits = serial_in(info, UART_FCTR);
+			bits |= UART_FCTR_TX_INT;
+			serial_out(info, UART_FCTR, bits);
+			serial_out(info, UART_LCR, 0);
+
+			restore_flags(flags);
+			return put_user(1, value);
+		case TIOCSER485SLAVEMULTIPLEX:
+			bits |= portmask;
+			serial_out(info, txctl_offset, bits);
+
+			bits = serial_in(info, rxctl_offset);
+			bits |= portmask;
+			serial_out(info, rxctl_offset, bits);
+
+			serial_out(info, UART_LCR, 0xbf);
+			bits = serial_in(info, UART_FCTR);
+			bits |= UART_FCTR_TX_INT;
+			serial_out(info, UART_FCTR, bits);
+			serial_out(info, UART_LCR, 0);
+
+			restore_flags(flags);
+			return put_user(1, value);
+	}
+
+	restore_flags(flags);
+	return -EINVAL;
+}
+
+static int pci_cti485_4_fn(struct serial_state *state, int ioctl,
+			   unsigned int *value) {
+	int port = state->port;
+	int board_num = (port % 0x100) / 0x08;
+
+	if (board_num < 4)
+		return -ENOSYS;
+
+	return pci_cti485_fn(state, ioctl, value);
+}
+
+static int pci_cti485_2_fn(struct serial_state *state, int ioctl,
+			   unsigned int *value) {
+	int port = state->port;
+	int board_num = (port % 0x100) / 0x08;
+
+	if (board_num < 2)
+		return -ENOSYS;
+
+	return pci_cti485_fn(state, ioctl, value);
+}
+
+/*
  * Timedia has an explosion of boards, and to avoid the PCI table from
  * growing *huge*, we use this function to collapse some 70 entries
  * in the PCI table into one, for sanity's and compactness's sake.
@@ -4227,7 +4363,10 @@
 	pbn_b1_2_921600,
 	pbn_b1_4_921600,
+	pbn_b1_4_2_921600,     /* Added for 232/485 hybrid boards */
 	pbn_b1_8_921600,
+	pbn_b1_8_4_921600,     /* Added for 232/485 hybrid boards */
+	pbn_b1_8_2_921600,     /* Added for 232/485 hybrid boards */
 	pbn_b1_2_1382400,
 	pbn_b1_4_1382400,
@@ -4303,9 +4442,18 @@
 	{ SPCI_FL_BASE1, 4, 115200 },		/* pbn_b1_4_115200 */
 	{ SPCI_FL_BASE1, 8, 115200 },		/* pbn_b1_8_115200 */
-	{ SPCI_FL_BASE1, 2, 921600 },		/* pbn_b1_2_921600 */
-	{ SPCI_FL_BASE1, 4, 921600 },		/* pbn_b1_4_921600 */
-	{ SPCI_FL_BASE1, 8, 921600 },		/* pbn_b1_8_921600 */
+	{ SPCI_FL_BASE1, 2, 921600,		/* pbn_b1_2_921600 */
+	  0, 0, NULL, 0, pci_cti485_fn },
+	{ SPCI_FL_BASE1, 4, 921600,		/* pbn_b1_4_921600 */
+	  0, 0, NULL, 0, pci_cti485_fn },
+	{ SPCI_FL_BASE1, 4, 921600,             /* pbn_b1_4_2_921600 */
+	  0, 0, NULL, 0, pci_cti485_2_fn },
+	{ SPCI_FL_BASE1, 8, 921600,		/* pbn_b1_8_921600 */
+	  0, 0, NULL, 0, pci_cti485_fn },
+	{ SPCI_FL_BASE1, 8, 921600,
+	  0, 0, NULL, 0, pci_cti485_4_fn },       /* pbn_b1_8_4_921600 */
+	{ SPCI_FL_BASE1, 8, 921600,
+	  0, 0, NULL, 0, pci_cti485_2_fn },       /* pbn_b1_8_2_921600 */
 	{ SPCI_FL_BASE1, 2, 1382400 },		/* pbn_b1_2_1382400 */
 	{ SPCI_FL_BASE1, 4, 1382400 },		/* pbn_b1_4_1382400 */
@@ -4515,7 +4663,7 @@
 	{	PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
 		PCI_SUBVENDOR_ID_CONNECT_TECH,
 		PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4, 0, 0,
-		pbn_b1_8_921600 },
+		pbn_b1_8_4_921600 },
 	{	PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
 		PCI_SUBVENDOR_ID_CONNECT_TECH,
 		PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485, 0, 0,
@@ -4523,7 +4671,7 @@
 	{	PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
 		PCI_SUBVENDOR_ID_CONNECT_TECH,
 		PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2, 0, 0,
-		pbn_b1_4_921600 },
+		pbn_b1_4_2_921600 },
 	{	PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
 		PCI_SUBVENDOR_ID_CONNECT_TECH,
 		PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485, 0, 0,
@@ -4531,7 +4679,7 @@
 	{	PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
 		PCI_SUBVENDOR_ID_CONNECT_TECH,
 		PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_2_6, 0, 0,
-		pbn_b1_8_921600 },
+		pbn_b1_8_2_921600 },
 	{	PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
 		PCI_SUBVENDOR_ID_CONNECT_TECH,
 		PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1, 0, 0,
--- ./include/linux/serialP_orig.bak	Fri Aug 10 09:44:02 2001
+++ ./include/linux/serialP.h	Fri Aug 10 09:51:09 2001
@@ -51,6 +51,9 @@
 	struct termios		normal_termios;
 	struct termios		callout_termios;
 	int	io_type;
+	int (*lmode_fn)(struct serial_state *state, int ioctl,
+			unsigned int *value);
+	int lmode;
 	struct async_struct *info;
 	struct pci_dev	*dev;
 };
@@ -150,6 +153,8 @@
 	int (*init_fn)(struct pci_dev *dev, struct pci_board *board,
 			int enable);
 	int first_uart_offset;
+	int (*lmode_fn)(struct serial_state *state, int ioctl,
+			unsigned int *value);
 };
 struct pci_board_inst {
--- ./include/asm-i386/ioctls_orig.bak	Fri Aug 10 09:48:31 2001
+++ ./include/asm-i386/ioctls.h	Fri Aug 10 09:47:42 2001
@@ -68,6 +68,14 @@
 #define TIOCGHAYESESP   0x545E  /* Get Hayes ESP configuration */
 #define TIOCSHAYESESP   0x545F  /* Set Hayes ESP configuration */
+#define TIOCSER485SET   0x5460  /* Set the 485 line */
+#define TIOCSER485GET   0x5461  /* Get the 485 line */
+
+#define TIOCSER485FULLDUPLEX		0
+#define TIOCSER485HALFDUPLEX		1
+#define TIOCSER485SLAVEMULTIPLEX	2
+
+
 /* Used for packet mode */
 #define TIOCPKT_DATA		 0
 #define TIOCPKT_FLUSHREAD	 1
-- Caleb Tennis Analytical Engineering 2555 Technology Blvd Columbus, IN 47201-------------------------------------------------------
-- Caleb Tennis Analytical Engineering 2555 Technology Blvd Columbus, IN 47201 - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/