Hi

Attached is my port of decision's serial patch to 2.2.16 as promised. I
have removed some bits out of the original patch (available from
decision.com.tw iirc, against some oldish 2.2.x kernel) that I didn't
think were important. What I know about the serial driver borders on
dangerous so YMMV. I've only tested it on the PCCOM8 card but it "works
for me".

No warranties/support/guarantees. I don't plan on using this anymore
as the 4 line patch to the 5.01 serial driver is much nicer IMHO ...

Cheers,

--Craig
diff -urN linux-2.2.16.vanilla/drivers/char/Config.in 
linux-2.2.16.decision/drivers/char/Config.in
--- linux-2.2.16.vanilla/drivers/char/Config.in Wed Jul 26 14:12:18 2000
+++ linux-2.2.16.decision/drivers/char/Config.in        Wed Jul 26 14:17:38 2000
@@ -19,6 +19,7 @@
    bool '   Autodetect IRQ on standard ports (unsafe)' CONFIG_SERIAL_DETECT_IRQ
    bool '   Support special multiport boards' CONFIG_SERIAL_MULTIPORT
    bool '   Support the Bell Technologies HUB6 card' CONFIG_HUB6
+   bool '   Support the Decision PCCOM PCI card' CONFIG_DCIPCCOM_PCI
 fi
 bool 'Non-standard serial port support' CONFIG_SERIAL_NONSTANDARD
 if [ "$CONFIG_SERIAL_NONSTANDARD" = "y" ]; then
diff -urN linux-2.2.16.vanilla/drivers/char/serial.c 
linux-2.2.16.decision/drivers/char/serial.c
--- linux-2.2.16.vanilla/drivers/char/serial.c  Wed Jul 26 14:12:18 2000
+++ linux-2.2.16.decision/drivers/char/serial.c Wed Jul 26 14:36:48 2000
@@ -40,6 +40,10 @@
 /*
  * Serial driver configuration section.  Here are the various options:
  *
+ * CONFIG_DCIPCCOM_PCI
+ *             Enable support for the Decision PCCOM PCI 4/8-Port
+ *             cards if CONFIG_PCI is defined
+ *
  * CONFIG_HUB6
  *             Enables support for the venerable Bell Technologies
  *             HUB6 card.
@@ -63,6 +67,12 @@
  */
 #include <linux/config.h>
 
+#ifndef CONFIG_PCI
+#ifdef CONFIG_DCIPCCOM_PCI
+#undef CONFIG_DCIPCCOM_PCI
+#endif /* CONFIG_DCIPCCOM_PCI */
+#endif /* CONFIG_PCI */
+
 #undef SERIAL_PARANOIA_CHECK
 #define CONFIG_SERIAL_NOPAUSE_IO
 #define SERIAL_DO_RESTART
@@ -94,6 +104,15 @@
 #endif
 #endif
 
+#ifdef CONFIG_DCIPCCOM_PCI
+#ifndef CONFIG_SERIAL_MANY_PORTS
+#define CONFIG_SERIAL_MANY_PORTS
+#endif
+#ifndef CONFIG_SERIAL_SHARE_IRQ
+#define CONFIG_SERIAL_SHARE_IRQ
+#endif
+#endif /* CONFIG_DCIPCCOM_PCI */
+
 /* Set of debugging defines */
 
 #undef SERIAL_DEBUG_INTR
@@ -143,6 +162,10 @@
 #include <linux/console.h>
 #endif
 
+#ifdef CONFIG_PCI
+#include <linux/pci.h>
+#endif /* CONFIG_PCI */
+
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -179,6 +202,46 @@
 static struct console sercons;
 #endif
 
+#ifdef CONFIG_DCIPCCOM_PCI
+
+/*
+ * Programming Interface
+ */
+#define PCI_PI_SERIAL_XT       0x00
+#define PCI_PI_SERIAL_16450    0x01
+#define PCI_PI_SERIAL_16550    0x02
+#define PCI_PI_SERIAL_16650    0x03
+
+/*
+ * Vendor
+ */
+#define PCI_DECISION           0x6666
+
+/*
+ * Class-, SubClass-, and Vendor-specific
+ */
+#define PCI_DC_SIO_PORT                0x2F
+#define PCI_DC_SIO_2P          0x00
+#define PCI_DC_SIO_4P          0x01
+#define PCI_DC_SIO_8P          0x02
+#define PCI_DC_SIO_16P         0x03
+ 
+#define PCI_DC_SIO_TYPE                0x2E
+#define PCI_DC_SIO_RS232       0x00
+#define PCI_DC_SIO_RS422       0x01
+#define PCI_DC_SIO_RS485       0x02
+
+/*
+ * Hardware configuration
+ */
+#define PCCOM_PCI_VECT_2P(base)         (base + 0x10)
+#define PCCOM_PCI_SWID_2P(base)         (base + 0x10)
+#define PCCOM_PCI_VECT_4P(base)         (base + 0x20)
+#define PCCOM_PCI_SWID_4P(base)         (base + 0x20)
+#define PCCOM_PCI_VECT_8P(base)         (base + 0x40)
+#define PCCOM_PCI_SWID_8P(base)         (base + 0x80)
+#endif /* CONFIG_DCIPCCOM_PCI */
+
 static unsigned detect_uart_irq (struct serial_state * state);
 static void autoconfig(struct serial_state * info);
 static void change_speed(struct async_struct *info, struct termios *old);
@@ -212,6 +275,16 @@
 static struct termios *serial_termios[NR_PORTS];
 static struct termios *serial_termios_locked[NR_PORTS];
 
+#ifdef CONFIG_DCIPCCOM_PCI
+#define serial_dcpci_nr_cards  2
+#define serial_dcpci_minor1    44
+#define serial_dcpci_minor2    52
+
+static int serial_dcpci_minor[serial_dcpci_nr_cards] = {
+       serial_dcpci_minor1, serial_dcpci_minor2
+};
+#endif /* CONFIG_DCIPCCOM_PCI */
+
 #ifndef MIN
 #define MIN(a,b)       ((a) < (b) ? (a) : (b))
 #endif
@@ -2825,6 +2898,10 @@
 static _INLINE_ void show_serial_version(void)
 {
        printk(KERN_INFO "%s version %s with", serial_name, serial_version);
+#ifdef CONFIG_DCIPCCOM_PCI
+       printk(" DCI_PCCOM_PCI");
+#define SERIAL_OPT
+#endif /* CONFIG_DCIPCCOM_PCI */
 #ifdef CONFIG_HUB6
        printk(" HUB-6");
 #define SERIAL_OPT
@@ -2853,6 +2930,178 @@
 #undef SERIAL_OPT
 }
 
+#ifdef CONFIG_DCIPCCOM_PCI
+
+/*
+ * dci_pci_detect() - Test PCI bus presence and Decision PCCOM PCI.
+ */
+static void
+dci_pci_detect(void)
+{
+#define DCIPCCOM_PCI_PI_MAX            4
+
+       static unsigned char dcipccom_pci_pi[DCIPCCOM_PCI_PI_MAX] = {
+               PCI_PI_SERIAL_XT,    PCI_PI_SERIAL_16450, 
+               PCI_PI_SERIAL_16550, PCI_PI_SERIAL_16650
+       };
+
+       struct pci_dev       *pdev = NULL;
+       int                  reg, vect;
+       unsigned int         class = PCI_CLASS_COMMUNICATION_SERIAL;
+       unsigned short       vendor;
+       unsigned int         base;
+       unsigned char        pi, irq, nport, pcid;
+       unsigned int         i, index, card;
+       int                  rc;
+       struct serial_state  *info;
+
+       if (pci_present() == 0) /* PCI bus not present */
+               return;
+
+       for (index = card = 0; card < serial_dcpci_nr_cards; index++) {
+               /*
+                * find sio communication class
+                */
+               for (i = 0; i < DCIPCCOM_PCI_PI_MAX; i++) {
+                       pi = dcipccom_pci_pi[i];
+                       if ((pdev = pci_find_class((class << 8) | pi, pdev))
+                               != NULL)
+                               break;
+               }
+               if (i == DCIPCCOM_PCI_PI_MAX) break;
+
+               /*
+                * find decision card
+                */
+               if ((rc = pci_read_config_word(pdev, PCI_VENDOR_ID,
+                                            &vendor)) != PCIBIOS_SUCCESSFUL)
+                       break;
+               if (vendor != PCI_DECISION) continue;
+
+               /*
+                * determine programming interface
+                */
+               if ((rc = pci_read_config_byte(pdev, PCI_CLASS_PROG,
+                                          &pi)) != PCIBIOS_SUCCESSFUL) break;
+               switch (pi) {
+               case PCI_PI_SERIAL_XT:
+               case PCI_PI_SERIAL_16450:
+               case PCI_PI_SERIAL_16550:
+               case PCI_PI_SERIAL_16650:
+                       break;
+               default:
+                       continue;
+               }
+
+               /*
+                * NPORT
+                */
+               if ((rc = pci_read_config_byte(pdev, PCI_DC_SIO_PORT,
+                                     &nport)) != PCIBIOS_SUCCESSFUL) break;
+               switch (nport) {
+               case PCI_DC_SIO_2P:
+                       nport = 2;
+                       break;
+               case PCI_DC_SIO_4P:
+                       nport = 4;
+                       break;
+               case PCI_DC_SIO_8P:
+                       nport = 8;
+                       break;
+               case PCI_DC_SIO_16P:
+                       nport = 16;
+                       break;
+               default:
+                       nport = 0;
+                       break;
+               }
+
+#if 0
+               printk("nport = %d\n", nport);
+#endif
+      
+               /*
+                * IRQ
+                */
+               if ((rc = pci_read_config_byte(pdev,
+                            PCI_INTERRUPT_LINE, &irq)) != PCIBIOS_SUCCESSFUL)
+                       break;
+
+#if 0
+               printk("IRQ %d\n", irq);
+#endif
+
+               /*
+                * I/O Base addr
+                */
+               i = 0;
+               for (reg = PCI_BASE_ADDRESS_2; reg <= PCI_BASE_ADDRESS_5;
+                                                               i++, reg += 4) {
+                       if ((rc = pci_read_config_dword(pdev, reg,
+                                       &base)) != PCIBIOS_SUCCESSFUL) return;
+      
+                       if (!base) continue;
+
+#if 0
+                       printk("I/O %d at 0x%x\n", i, base); 
+#endif
+
+                       if (base & PCI_BASE_ADDRESS_SPACE) {
+                               base &= PCI_BASE_ADDRESS_IO_MASK;
+#if 0
+                               printk("I/O %d at 0x%x\n", i, base); 
+#endif
+                               break;
+                       }
+               }
+
+               switch (nport) {
+               case 2:
+                       vect = PCCOM_PCI_VECT_2P(base);
+                       pcid = inb(PCCOM_PCI_SWID_2P(base)) >> 4;
+                       break;
+               case 4:
+                       vect = PCCOM_PCI_VECT_4P(base);
+                       pcid = inb(PCCOM_PCI_SWID_4P(base)) >> 4;
+                       break;
+               case 8:
+                       vect = PCCOM_PCI_VECT_8P(base);
+                       pcid = inb(PCCOM_PCI_SWID_8P(base)) >> 4;
+                       break;
+               default:
+                       vect = 0;
+                       pcid = 0;
+                       break;
+               }
+
+#if 0
+               printk("dci_pci_detect(%d): (nport, base, irq) = (%d, %x, %d)\n",
+                               card, (unsigned)nport, base, (unsigned)irq);
+#endif
+
+               info = rs_table + serial_dcpci_minor[card];
+               for (i = 0; i < nport; info++, i++) {
+                       info->port = base + (i << 3);   
+                       info->irq  = irq;
+#if 0
+                       printk("%d --> [%d]\n", i, irq);
+#endif
+               }
+
+#if 0
+               cards[set].nport = nport;
+               cards[set].irq   = irq;
+               cards[set].addr  = base;
+               cards[set].vect  = vect;
+               cards[set].pcid  = pcid;
+#endif
+
+               card++;
+       }
+} /* dci_pci_detect() */
+
+#endif /* CONFIG_DCIPCCOM_PCI */
+
 /*
  * This routine detect the IRQ of a serial port by clearing OUT2 when
  * no UART interrupt are requested (IER = 0) (*GPL*). This seems to work at
@@ -3179,6 +3428,13 @@
        if (tty_register_driver(&callout_driver))
                panic("Couldn't register callout driver\n");
        
+#ifdef CONFIG_DCIPCCOM_PCI
+       /*
+        * detect Decision PCCOM PCI cards
+        */
+       dci_pci_detect();
+#endif /* CONFIG_DCIPCCOM_PCI */
+
        for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
                state->magic = SSTATE_MAGIC;
                state->line = i;
diff -urN linux-2.2.16.vanilla/drivers/pci/oldproc.c 
linux-2.2.16.decision/drivers/pci/oldproc.c
--- linux-2.2.16.vanilla/drivers/pci/oldproc.c  Wed Jul 26 14:12:19 2000
+++ linux-2.2.16.decision/drivers/pci/oldproc.c Wed Jul 26 14:40:08 2000
@@ -517,6 +517,11 @@
        DEVICE( S3,             S3_SONICVIBES,  "SonicVibes"),
        DEVICE( DCI,            DCI_PCCOM4,     "PC COM PCI Bus 4 port serial 
Adapter"),
        DEVICE( GENROCO,        GENROCO_HFP832, "TURBOstor HFP832"),
+#ifdef CONFIG_DCIPCCOM_PCI
+       DEVICE( DECISION,       DECISION_PCCOM4,"Decision PCCOM PCI 4-Port"),
+       DEVICE( DECISION,       DECISION_PCCOM8,"Decision PCCOM PCI 8-Port"),
+       DEVICE( DECISION,       DECISION_PCCOM2,"Decision PCCOM PCI 2-Port"),
+#endif /* CONFIG_DCIPCCOM_PCI */
        DEVICE( INTEL,          INTEL_82375,    "82375EB"),
        DEVICE( INTEL,          INTEL_82424,    "82424ZX Saturn"),
        DEVICE( INTEL,          INTEL_82378,    "82378IB"),
@@ -856,7 +861,7 @@
              case PCI_VENDOR_ID_AVANCE:        return "Avance";
              case PCI_VENDOR_ID_NETVIN:        return "NetVin";
              case PCI_VENDOR_ID_S3:            return "S3 Inc.";
-             case PCI_VENDOR_ID_DCI:           return "Decision Computer Int.";
+             case PCI_VENDOR_ID_DECISION:      return "Decision Computer Int.";
              case PCI_VENDOR_ID_GENROCO:       return "Genroco";
              case PCI_VENDOR_ID_INTEL:         return "Intel";
              case PCI_VENDOR_ID_KTI:           return "KTI";
diff -urN linux-2.2.16.vanilla/include/asm-i386/serial.h 
linux-2.2.16.decision/include/asm-i386/serial.h
--- linux-2.2.16.vanilla/include/asm-i386/serial.h      Tue May 11 19:35:45 1999
+++ linux-2.2.16.decision/include/asm-i386/serial.h     Wed Jul 26 14:42:20 2000
@@ -108,6 +108,51 @@
 #define HUB6_SERIAL_PORT_DFNS
 #endif
 
+/*
+ * Decision PCCOM PCI 2/4/8-port cards support
+ *
+ * You can have up to two cards in the system.
+ */
+#if (defined(CONFIG_DCIPCCOM_PCI) && defined(CONFIG_SERIAL_MANY_PORTS))
+
+#ifndef CONFIG_HUB6
+#undef HUB6_SERIAL_PORT_DFNS
+#define HUB6_SERIAL_PORT_DFNS          \
+       { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,0) },  /* ttyS32 */ \
+       { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,1) },  /* ttyS33 */ \
+       { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,2) },  /* ttyS34 */ \
+       { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,3) },  /* ttyS35 */ \
+       { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,4) },  /* ttyS36 */ \
+       { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,5) },  /* ttyS37 */ \
+       { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,0) },  /* ttyS38 */ \
+       { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,1) },  /* ttyS39 */ \
+       { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,2) },  /* ttyS40 */ \
+       { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,3) },  /* ttyS41 */ \
+       { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,4) },  /* ttyS42 */ \
+       { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,5) },  /* ttyS43 */
+#endif /* CONFIG_HUB6 */
+
+#define DCIPCCOM_PCI_SERIAL_PORT_DFNS  \
+        { 0, BASE_BAUD, 0x0, 0, STD_COM_FLAGS },       /* ttyS44 */ \
+        { 0, BASE_BAUD, 0x0, 0, STD_COM_FLAGS },       /* ttyS45 */ \
+        { 0, BASE_BAUD, 0x0, 0, STD_COM_FLAGS },       /* ttyS46 */ \
+        { 0, BASE_BAUD, 0x0, 0, STD_COM_FLAGS },       /* ttyS47 */ \
+        { 0, BASE_BAUD, 0x0, 0, STD_COM_FLAGS },       /* ttyS48 */ \
+        { 0, BASE_BAUD, 0x0, 0, STD_COM_FLAGS },       /* ttyS49 */ \
+        { 0, BASE_BAUD, 0x0, 0, STD_COM_FLAGS },       /* ttyS50 */ \
+        { 0, BASE_BAUD, 0x0, 0, STD_COM_FLAGS },       /* ttyS51 */ \
+        { 0, BASE_BAUD, 0x0, 0, STD_COM_FLAGS },       /* ttyS52 */ \
+        { 0, BASE_BAUD, 0x0, 0, STD_COM_FLAGS },       /* ttyS53 */ \
+        { 0, BASE_BAUD, 0x0, 0, STD_COM_FLAGS },       /* ttyS54 */ \
+        { 0, BASE_BAUD, 0x0, 0, STD_COM_FLAGS },       /* ttyS55 */ \
+        { 0, BASE_BAUD, 0x0, 0, STD_COM_FLAGS },       /* ttyS56 */ \
+        { 0, BASE_BAUD, 0x0, 0, STD_COM_FLAGS },       /* ttyS57 */ \
+        { 0, BASE_BAUD, 0x0, 0, STD_COM_FLAGS },       /* ttyS58 */ \
+        { 0, BASE_BAUD, 0x0, 0, STD_COM_FLAGS },       /* ttyS59 */
+#else
+#define DCIPCCOM_PCI_SERIAL_PORT_DFNS
+#endif
+
 #ifdef CONFIG_MCA
 #define MCA_SERIAL_PORT_DFNS                   \
        { 0, BASE_BAUD, 0x3220, 3, STD_COM_FLAGS },     \
@@ -124,5 +169,6 @@
        STD_SERIAL_PORT_DEFNS           \
        EXTRA_SERIAL_PORT_DEFNS         \
        HUB6_SERIAL_PORT_DFNS           \
+       DCIPCCOM_PCI_SERIAL_PORT_DFNS   \
        MCA_SERIAL_PORT_DFNS
 
diff -urN linux-2.2.16.vanilla/include/linux/pci.h 
linux-2.2.16.decision/include/linux/pci.h
--- linux-2.2.16.vanilla/include/linux/pci.h    Wed Jul 26 14:12:28 2000
+++ linux-2.2.16.decision/include/linux/pci.h   Wed Jul 26 14:43:26 2000
@@ -1214,6 +1214,11 @@
 #define PCI_DEVICE_ID_INTERPHASE_5526  0x0004
 #define PCI_DEVICE_ID_INTERPHASE_55x6  0x0005
 
+#define PCI_VENDOR_ID_DECISION 0x6666
+#define PCI_DEVICE_ID_DECISION_PCCOM4  0x0001
+#define PCI_DEVICE_ID_DECISION_PCCOM8  0x0002
+#define PCI_DEVICE_ID_DECISION_PCCOM2  0x0004
+
 /*
  * The PCI interface treats multi-function devices as independent
  * devices.  The slot/function address of each device is encoded

Reply via email to