From 1d62878c784211efa8979652a4ecd12b0ab4f9fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Revol?= Date: Fri, 26 Mar 2010 23:44:07 +0000 Subject: [PATCH] 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. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35965 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/drivers/ports/pc_serial/Driver.cpp | 97 ++++++++++++++++--- .../kernel/drivers/ports/pc_serial/Driver.h | 12 ++- .../drivers/ports/pc_serial/SerialDevice.cpp | 4 + .../drivers/ports/pc_serial/SerialDevice.h | 4 + 4 files changed, 101 insertions(+), 16 deletions(-) diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/Driver.cpp b/src/add-ons/kernel/drivers/ports/pc_serial/Driver.cpp index 085c5186c1..147e587f81 100644 --- a/src/add-ons/kernel/drivers/ports/pc_serial/Driver.cpp +++ b/src/add-ons/kernel/drivers/ports/pc_serial/Driver.cpp @@ -1,4 +1,8 @@ /* + * Copyright 2009-2010, François Revol, . + * 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 @@ static const uint32 sBeBoxRates[] = { }; #endif +// XXX: should really be generated from metadata (CSV ?) + static const struct serial_support_descriptor sSupportedDevices[] = { #ifdef HANDLE_ISA_COM @@ -73,47 +79,71 @@ static const struct serial_support_descriptor sSupportedDevices[] = { // 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 @@ scan_bus(bus_type bus) 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 @@ scan_pci_alt() 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 @@ next_split_alt: // 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 @@ next_split_alt: master = device; ioport += supported->constraints.split; + portCount++; goto next_split_alt; // try next part of the I/O range now diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/Driver.h b/src/add-ons/kernel/drivers/ports/pc_serial/Driver.h index f3e5a0709f..c03e340ee5 100644 --- a/src/add-ons/kernel/drivers/ports/pc_serial/Driver.h +++ b/src/add-ons/kernel/drivers/ports/pc_serial/Driver.h @@ -1,4 +1,8 @@ /* + * Copyright 2009-2010, François Revol, . + * 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 @@ extern "C" { #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 @@ struct port_constraints { 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 @@ struct serial_support_descriptor { // 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; diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp index b3b1e0c6f8..0412824cfd 100644 --- a/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp +++ b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp @@ -1,4 +1,8 @@ /* + * Copyright 2009-2010, François Revol, . + * 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: * diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.h b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.h index 57cc422f17..f8d216d5e1 100644 --- a/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.h +++ b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.h @@ -1,4 +1,8 @@ /* + * Copyright 2009-2010, François Revol, . + * 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: *