[haiku-commits] r35965 - haiku/trunk/src/add-ons/kernel/drivers/ports/pc_serial

  • From: revol@xxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sat, 27 Mar 2010 00:44:07 +0100 (CET)

Author: mmu_man
Date: 2010-03-27 00:44:07 +0100 (Sat, 27 Mar 2010)
New Revision: 35965
Changeset: http://dev.haiku-os.org/changeset/35965/haiku

Modified:
   haiku/trunk/src/add-ons/kernel/drivers/ports/pc_serial/Driver.cpp
   haiku/trunk/src/add-ons/kernel/drivers/ports/pc_serial/Driver.h
   haiku/trunk/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp
   haiku/trunk/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.h
Log:
Update copyrights. Mention TuneTracker Systems as a sponsor.
Add several ways to restrict UART probing when matching devices:
- max port count,
- PCI subsystem ID mask (some cards encode the port count there),
- Base Address Register mask (some cards only have UART in the first 2 ranges).
Use those to match 2 specific NetMos chips, and avoid screwing up when 
input_server tries to access UARTs at boggus ranges.


Modified: haiku/trunk/src/add-ons/kernel/drivers/ports/pc_serial/Driver.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/drivers/ports/pc_serial/Driver.cpp   
2010-03-26 21:18:08 UTC (rev 35964)
+++ haiku/trunk/src/add-ons/kernel/drivers/ports/pc_serial/Driver.cpp   
2010-03-26 23:44:07 UTC (rev 35965)
@@ -1,4 +1,8 @@
 /*
+ * Copyright 2009-2010, François Revol, <revol@xxxxxxx>.
+ * Sponsored by TuneTracker Systems.
+ * Based on the Haiku usb_serial driver which is:
+ *
  * Copyright (c) 2007-2008 by Michael Lotz
  * Heavily based on the original usb_serial driver which is:
  *
@@ -61,6 +65,8 @@
 };
 #endif
 
+// XXX: should really be generated from metadata (CSV ?)
+
 static const struct serial_support_descriptor sSupportedDevices[] = {
 
 #ifdef HANDLE_ISA_COM
@@ -73,47 +79,71 @@
        // vendor/device matches first
 
 /*
+       // vendor: OxfordSemi
+#define VN "OxfordSemi"
        { B_PCI_BUS, "OxfordSemi 16950 Serial Port", sDefaultRates, NULL, { 32, 
32, 8 },
          { PCI_simple_communications, PCI_serial, PCI_serial_16950,
-               0x1415, 0x9501 } },
+               0x1415, 0x9501, PCI_INVAL, PCI_INVAL } },
 */
+
+
+       // vendor: NetMos
+#define VN "NetMos"
+
+       // used in Manhattan cards
+       // 1 function / port
+       { B_PCI_BUS, VN" 16550 Serial Port", sDefaultRates, NULL, { 8, 8, 8, 0, 
0, 0 },
+         { PCI_simple_communications, PCI_serial, PCI_serial_16550,
+               0x9710, 0x9865, PCI_INVAL, PCI_INVAL } },
+
+       // http://www.moschip.com/data/products/NM9835/Data%20Sheet_9835.pdf
+       // single function with all ports
+       // only BAR 0 & 1 are UART
+       { B_PCI_BUS, VN" 16550 Serial Port", sDefaultRates, NULL, { 8, 8, 8, 
0x3, 2, 0x000f },
+         { PCI_simple_communications, PCI_serial, PCI_serial_16550,
+               0x9710, 0x9835, PCI_INVAL, PCI_INVAL } },
+
+#undef VN
+
+
+
        // generic fallback matches
        /*
        { B_PCI_BUS, "Generic XT Serial Port", NULL },
          { PCI_INVAL, PCI_INVAL, PCI_simple_communications,
-               PCI_serial, PCI_serial_xt } },
+               PCI_serial, PCI_serial_xt, PCI_INVAL, PCI_INVAL } },
                
        { B_PCI_BUS, "Generic 16450 Serial Port", NULL },
          { PCI_INVAL, PCI_INVAL, PCI_simple_communications,
-               PCI_serial, PCI_serial_16450 } },
+               PCI_serial, PCI_serial_16450, PCI_INVAL, PCI_INVAL } },
                
        */
        { B_PCI_BUS, "Generic 16550 Serial Port", sDefaultRates, NULL, { 8, 8, 
8 },
          { PCI_simple_communications, PCI_serial, PCI_serial_16550,
-               PCI_INVAL, PCI_INVAL } },
+               PCI_INVAL, PCI_INVAL, PCI_INVAL, PCI_INVAL } },
 
        { B_PCI_BUS, "Generic 16650 Serial Port", sDefaultRates, NULL, { 8, 8, 
8 },
          { PCI_simple_communications, PCI_serial, PCI_serial_16650,
-               PCI_INVAL, PCI_INVAL } },
+               PCI_INVAL, PCI_INVAL, PCI_INVAL, PCI_INVAL } },
 
        { B_PCI_BUS, "Generic 16750 Serial Port", sDefaultRates, NULL, { 8, 8, 
8 },
          { PCI_simple_communications, PCI_serial, PCI_serial_16750,
-               PCI_INVAL, PCI_INVAL } },
+               PCI_INVAL, PCI_INVAL, PCI_INVAL, PCI_INVAL } },
 
        { B_PCI_BUS, "Generic 16850 Serial Port", sDefaultRates, NULL, { 8, 8, 
8 },
          { PCI_simple_communications, PCI_serial, PCI_serial_16850,
-               PCI_INVAL, PCI_INVAL } },
+               PCI_INVAL, PCI_INVAL, PCI_INVAL, PCI_INVAL } },
 
        { B_PCI_BUS, "Generic 16950 Serial Port", sDefaultRates, NULL, { 8, 8, 
8 },
          { PCI_simple_communications, PCI_serial, PCI_serial_16950,
-               PCI_INVAL, PCI_INVAL } },
+               PCI_INVAL, PCI_INVAL, PCI_INVAL, PCI_INVAL } },
 
        // non PCI_serial devices
 
        // beos zz driver supported that one
        { B_PCI_BUS, "Lucent Modem", sDefaultRates, NULL, { 8, 8, 8 },
          { PCI_simple_communications, PCI_simple_communications_other, 0x00, 
-               0x11C1, 0x0480 } }, 
+               0x11C1, 0x0480, PCI_INVAL, PCI_INVAL } }, 
 
        { B_PCI_BUS, NULL, NULL, NULL, {0}, {0} }
 };
@@ -408,6 +438,9 @@
                resource_descriptor iodesc;
                SerialDevice *master = NULL;
 
+               //TODO: handle maxports
+               //TODO: handle subsystem_id_mask
+
                // instanciate devices on IO ports
                for (int i = 0;
                        
gConfigManagerModule->get_nth_resource_descriptor_of_type(
@@ -508,20 +541,50 @@
 
                SerialDevice *master = NULL;
 
+               uint8 portCount = 0;
+               uint32 maxPorts = DEVICES_COUNT;
+
+               if (supported->constraints.maxports) {
+                       maxPorts = supported->constraints.maxports;
+                       TRACE_ALWAYS("card supports up to %d ports\n", 
maxPorts);
+               }
+               if (supported->constraints.subsystem_id_mask) {
+                       uint32 id = info.u.h0.subsystem_id;
+                       uint32 mask = supported->constraints.subsystem_id_mask;
+                       id &= mask;
+                       //TRACE_ALWAYS("mask: %lx, masked: %lx\n", mask, id);
+                       while (!(mask & 0x1)) {
+                               mask >>= 1;
+                               id >>= 1;
+                       }
+                       maxPorts = (uint8)id;
+                       TRACE_ALWAYS("subsystem id tells card has %d ports\n", 
maxPorts);
+               }
+
                // find I/O ports
                for (int r = 0; r < 6; r++) {
+                       uint32 regbase = info.u.h0.base_registers[r];
+                       uint32 reglen = info.u.h0.base_register_sizes[r];
+
                        /**/
-                       TRACE_ALWAYS("range at 0x%08lx len 0x%lx flags 
0x%02x\n",
-                               info.u.h0.base_registers[r], 
info.u.h0.base_register_sizes[r],
-                               info.u.h0.base_register_flags[r]);
+                       TRACE("ranges[%d] at 0x%08lx len 0x%lx flags 0x%02x\n", 
r,
+                               regbase, reglen, 
info.u.h0.base_register_flags[r]);
                        /**/
 
+                       // empty
+                       if (reglen == 0)
+                               continue;
+
                        // not I/O
                        if ((info.u.h0.base_register_flags[r] & 
PCI_address_space) == 0)
                                continue;
 
-                       uint32 regbase = info.u.h0.base_registers[r];
-                       uint32 reglen = info.u.h0.base_register_sizes[r];
+                       // the range for sure doesn't contain any UART
+                       if (supported->constraints.ignoremask & (1 << r)) {
+                               TRACE_ALWAYS("ignored regs at 0x%08lx len 
0x%lx\n",
+                                       regbase, reglen);
+                               continue;
+                       }
 
                        TRACE_ALWAYS("regs at 0x%08lx len 0x%lx\n",
                                regbase, reglen);
@@ -538,7 +601,10 @@
                        // no more to split
                        if ((ioport - regbase) >= reglen)
                                continue;
-               
+
+                       if (portCount >= maxPorts)
+                               break;
+
                        TRACE_ALWAYS("inserting device at io 0x%04lx as %s\n", 
ioport, 
                                supported->name);
 
@@ -553,6 +619,7 @@
                                master = device;
                        
                        ioport += supported->constraints.split;
+                       portCount++;
                        goto next_split_alt;
                        // try next part of the I/O range now
 

Modified: haiku/trunk/src/add-ons/kernel/drivers/ports/pc_serial/Driver.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/drivers/ports/pc_serial/Driver.h     
2010-03-26 21:18:08 UTC (rev 35964)
+++ haiku/trunk/src/add-ons/kernel/drivers/ports/pc_serial/Driver.h     
2010-03-26 23:44:07 UTC (rev 35965)
@@ -1,4 +1,8 @@
 /*
+ * Copyright 2009-2010, François Revol, <revol@xxxxxxx>.
+ * Sponsored by TuneTracker Systems.
+ * Based on the Haiku usb_serial driver which is:
+ *
  * Copyright (c) 2007-2008 by Michael Lotz
  * Heavily based on the original usb_serial driver which is:
  *
@@ -36,7 +40,7 @@
 #endif
 
 #define DRIVER_NAME            "pc_serial"             // driver name for 
debug output
-#define DEVICES_COUNT  20                              // max simultaneously 
open devices
+#define DEVICES_COUNT  2                               // max simultaneously 
open devices
 
 // avoid clashing with BeOS zz driver
 #define DEVFS_BASE             "ports/pc_serial"
@@ -59,9 +63,13 @@
        uint32 minsize;
        uint32 maxsize;
        uint32 split;           // range to split I/O ports for each device
+       uint8 ignoremask;       // bitmask of BARs to ignore when probing
+       uint8 maxports;         // max number of ports on the card if > 0
+       uint32 subsystem_id_mask;       // if set mask with subsys id and shift 
to get maxports
 };
 
 #define PCI_INVAL 0xffff
+
 struct serial_support_descriptor {
        bus_type bus;   // B_*_BUS
        const char *name;
@@ -79,6 +87,8 @@
                // for PCI: if PCI_INVAL then match class
                ushort  vendor_id;
                ushort  device_id;
+               ushort  subsystem_vendor_id;
+               ushort  subsystem_device_id;
        } match;
 };
 typedef struct serial_support_descriptor serial_support_descriptor;

Modified: 
haiku/trunk/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp     
2010-03-26 21:18:08 UTC (rev 35964)
+++ haiku/trunk/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp     
2010-03-26 23:44:07 UTC (rev 35965)
@@ -1,4 +1,8 @@
 /*
+ * Copyright 2009-2010, François Revol, <revol@xxxxxxx>.
+ * Sponsored by TuneTracker Systems.
+ * Based on the Haiku usb_serial driver which is:
+ *
  * Copyright (c) 2007-2008 by Michael Lotz
  * Heavily based on the original usb_serial driver which is:
  *

Modified: haiku/trunk/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.h       
2010-03-26 21:18:08 UTC (rev 35964)
+++ haiku/trunk/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.h       
2010-03-26 23:44:07 UTC (rev 35965)
@@ -1,4 +1,8 @@
 /*
+ * Copyright 2009-2010, François Revol, <revol@xxxxxxx>.
+ * Sponsored by TuneTracker Systems.
+ * Based on the Haiku usb_serial driver which is:
+ *
  * Copyright (c) 2007-2008 by Michael Lotz
  * Heavily based on the original usb_serial driver which is:
  *


Other related posts:

  • » [haiku-commits] r35965 - haiku/trunk/src/add-ons/kernel/drivers/ports/pc_serial - revol