Message ID | 20200219043805.11093-2-shrirang.bagul@canonical.com |
---|---|
State | New |
Headers | show |
Series | UBUNTU: SAUCE: Updates to Exar USB serial driver | expand |
On 19.02.20 05:38, Shrirang Bagul wrote: > BugLink: http://bugs.launchpad.net/bugs/1863834 The above link should use https. This can be fixed when applying it (if ACK'ed). > > This patch adds the vendor release version on the Exar USB serial > device. Features include: > 1. Fix for RX fail after wake-up from sleep (S3/S4) > 2. Removes unnecessary debug messages > > Changelog: > > Version 1B, 11/6/2015 > Fixed Bug: The conditional logic to support kernel 3.9 was > incorrect(line 396 in xr_usb_serial_common.c). > > Version 1A, 1/9/2015 > This driver will work with any USB UART function in these Exar devices: > XR21V1410/1412/1414 > XR21B1411 > XR21B1420/1422/1424 > XR22801/802/804 > > Exar serial devices are typically enuremated as /dev/ttyXRUSB[0-3]. > > linux-oem buglink: http://bugs.launchpad.net/bugs/1685133 > > Signed-off-by: Shrirang Bagul <shrirang.bagul@canonical.com> > Acked-by: Colin Ian King <colin.king@canonical.com> > Acked-by: Stefan Bader <stefan.bader@canonical.com> > Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com> > Signed-off-by: Timo Aaltonen <timo.aaltonen@canonical.com> > (cherry picked from commit db1290efc02fd20056795bc3c23df6f81e275a54) > (source tag: Ubuntu-oem-4.15.0-1073.83) > Signed-off-by: Shrirang Bagul <shrirang.bagul@canonical.com> > --- > ubuntu/xr-usb-serial/README.txt | 3 + > ubuntu/xr-usb-serial/xr_get_smbios.c | 350 +++++++++++++++++ > ubuntu/xr-usb-serial/xr_get_smbios.h | 237 ++++++++++++ > ubuntu/xr-usb-serial/xr_usb_serial_common.c | 392 +++++++++++++++----- > ubuntu/xr-usb-serial/xr_usb_serial_common.h | 16 +- > ubuntu/xr-usb-serial/xr_usb_serial_hal.c | 244 ++++++++++-- > ubuntu/xr-usb-serial/xr_usb_serial_ioctl.h | 7 + > 7 files changed, 1119 insertions(+), 130 deletions(-) > create mode 100644 ubuntu/xr-usb-serial/xr_get_smbios.c > create mode 100644 ubuntu/xr-usb-serial/xr_get_smbios.h > > diff --git a/ubuntu/xr-usb-serial/README.txt b/ubuntu/xr-usb-serial/README.txt > index eb88f40f2080..242c8f368039 100644 > --- a/ubuntu/xr-usb-serial/README.txt > +++ b/ubuntu/xr-usb-serial/README.txt > @@ -1,5 +1,8 @@ > Exar USB Serial Driver > ====================== > +Version 1B, 11/6/2015 > +Fixed Bug: The conditional logic to support kernel 3.9 was incorrect(line 396 in xr_usb_serial_common.c). > + > Version 1A, 1/9/2015 > > This driver will work with any USB UART function in these Exar devices: > diff --git a/ubuntu/xr-usb-serial/xr_get_smbios.c b/ubuntu/xr-usb-serial/xr_get_smbios.c > new file mode 100644 > index 000000000000..05a995f1a957 > --- /dev/null > +++ b/ubuntu/xr-usb-serial/xr_get_smbios.c > @@ -0,0 +1,350 @@ > +/* > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > + */ > + > +static void *smbios_base = 0; > +/** SM-BIOS entry point structure */ > +struct smbios_entry_point_struct *smbios_entry_point = 0; > +/** DMI-BIOS entry point structure */ > +struct dmibios_entry_point_struct *dmibios_entry_point = 0; > +/** SM-BIOS, resp. DMI-BIOS structures base address; starting point */ > +void *smbios_structures_base = 0; > +/** enumeration of SM-BIOS, resp. DMI-BIOS types that do have subtypes */ > +__u8 smbios_types_with_subtypes[] = { TYPES_WITH_SUBTYPES }; > +/** contains the SMBIOS Version, e.g. V2.31 */ > +char smbios_version_string[32]; > +/** \fn unsigned char smbios_check_entry_point (void * addr) > + * \brief checks the entry point structure for correct checksum > + * \param addr pointer to the entry point structure > + * \return the checksum of the entry point structure, should be '0' > + * > + * This function checks the entry point structure for correct checksum. > + * The checksum is calculated with adding every byte of the structure > + * to the checksum byte. The entry point structure is considered correct > + * if the checksum byte is 0. > + * > + * \author Markus Lyra > + * \author Thomas Bretthauer > + * \date October 2000 > + */ > + > +unsigned char smbios_check_entry_point (void *addr) > +{ > + unsigned char *i; > + unsigned char checksum = 0; > + unsigned char length =((struct smbios_entry_point_struct *) addr)->entry_point_length; > + /* calculate checksum for entry point structure (should be 0) */ > + for (i = (unsigned char *) addr; i < (unsigned char *) addr + length; i++) > + checksum += *i; > + return checksum; > +} > + > +struct smbios_entry_point_struct * smbios_find_entry_point (void *base) > +{ > + struct smbios_entry_point_struct *entry_point = 0; /** SM-BIOS entry point */ > + unsigned int *temp; /** temp. pointer */ > + > + > + /* search for the magic dword - '_SM_� as DWORD formatted - on paragraph boundaries */ > + for (temp = base; > + !entry_point && temp < (unsigned int *) base + BIOS_MAP_LENGTH; > + temp += 4) > + { > + /* found the identifier ? */ > + if (*temp == SMBIOS_MAGIC_DWORD) > + { > + /* check if entry point valid (build checksum) */ > + if (!(smbios_check_entry_point (temp))) > + { > + entry_point = (struct smbios_entry_point_struct *) temp; > + > + /* fix display of Bios version string */ > + /* SMBios version is known as 2.1, 2.2, 2.3 and 2.3.1, never as 2.01 (JB) */ > + SM_BIOS_DEBUG("SM-BIOS V%d.%d entry point found at 0x%x\n", > + entry_point->major_version, entry_point->minor_version, (unsigned int) temp); > + > + SM_BIOS_DEBUG("V%d.%d\n", entry_point->major_version, entry_point->minor_version); > + } > + } > + } > + return entry_point; > +} > +struct dmibios_entry_point_struct *dmibios_find_entry_point (void *base) > +{ > + struct dmibios_entry_point_struct *entry_point = 0; /** DMI-BIOS entry point */ > + unsigned char *temp = 0; /** temp. pointer */ > + unsigned char biossignature[] = /** '_DMI20_NT_' */ > + { 0x5f, 0x44, 0x4d, 0x49, 0x32, 0x30, 0x5f, 0x4e, 0x54, 0x5f }; > + > + /* search for the DMI-BIOS signature on character boundary (hm?) */ > + for (temp = base; > + !entry_point && > + temp < (__u8 *) base + BIOS_MAP_LENGTH - sizeof (biossignature) - 32; > + temp++) > + { > + unsigned long *tempdword = (unsigned long *) temp; > + > + /* found the identifier '_DMI' ? (beginning of signature) */ > + if (*tempdword == DMIBIOS_MAGIC_DWORD) > + { > + entry_point = (struct dmibios_entry_point_struct *) temp; > + > + SM_BIOS_DEBUG ("DMI-BIOS revision %d entry point at 0x%x\n", > + entry_point->revision, (unsigned int) temp); > + > + sprintf(smbios_version_string, "V%d\n", entry_point->revision); > + > + if (memcmp (temp, biossignature, sizeof (biossignature)) == 0) > + SM_BIOS_DEBUG ("DMI BIOS successfully identified\n"); > + } > + } > + return entry_point; > +} > +void dump_smbios_hex(unsigned char *p,int len) > +{ > + int i; > + SM_BIOS_DEBUG("dump_smbios_hex length:%d\n",len); > + for(i=0;i<len;i++) > + { > + if((p[i] == 0xc0)&&(p[i+1]==0x06)) > + SM_BIOS_DEBUG("Found 0xc0 at offset:%d 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x \n\t",i,p[i],p[i+1],p[i+2],p[i+3],p[i+4],p[i+5]); > + } > +} > +int smbios_type_has_subtype (unsigned char type) > +{ > + int i; > + > + > + for (i = 0; i < sizeof (smbios_types_with_subtypes); i++) > + if (type == smbios_types_with_subtypes[i]) > + return 1; > + > + return 0; > +} > + > +int smbios_get_struct_length (struct smbios_struct * struct_ptr) > +{ > + /* jump to string list */ > + unsigned char *ptr = (unsigned char *) struct_ptr + struct_ptr->length; > + > + /* search for the end of string list */ > + while (ptr[0] != 0x00 || ptr[1] != 0x00) > + ptr++; > + ptr += 2; /* terminating 0x0000 should be included */ > + > + return (int) ptr - (int) struct_ptr; > +} > + > +unsigned int smbios_get_readable_name(char *name, struct smbios_struct *struct_ptr) > +{ > + switch(struct_ptr->type) > + { > + case 0: return sprintf (name, "%s", RD_BIOS); > + case 1: return sprintf (name, "%s", RD_SYSTEM); > + case 2: return sprintf (name, "%s", RD_BASEBOARD); > + case 3: return sprintf (name, "%s", RD_ENCLOSURE); > + case 4: return sprintf (name, "%s", RD_PROCESSOR); > + case 5: return sprintf (name, "%s", RD_MEMCTRL); > + case 6: return sprintf (name, "%s", RD_MEMMOD); > + case 7: return sprintf (name, "%s", RD_CACHE); > + case 8: return sprintf (name, "%s", RD_PORT); > + case 9: return sprintf (name, "%s", RD_SLOT); > + case 10: return sprintf (name, "%s", RD_ONBOARD); > + case 11: return sprintf (name, "%s", RD_OEMSTRINGS); > + case 12: return sprintf (name, "%s", RD_SYSTEMCONFIG); > + case 13: return sprintf (name, "%s", RD_BIOSLANG); > + case 14: return sprintf (name, "%s", RD_GROUPASSOC); > + case 15: return sprintf (name, "%s", RD_EVENTLOG); > + case 16: return sprintf (name, "%s", RD_MEMARRAY); > + case 17: return sprintf (name, "%s", RD_MEMDEV); > + case 18: return sprintf (name, "%s", RD_32MEMERR); > + case 19: return sprintf (name, "%s", RD_MEMMAPPEDADR); > + case 20: return sprintf (name, "%s", RD_MEMMAPPEDDEV); > + case 21: return sprintf (name, "%s", RD_POINTINGDEV); > + case 22: return sprintf (name, "%s", RD_BATTERY); > + case 23: return sprintf (name, "%s", RD_RESET); > + case 24: return sprintf (name, "%s", RD_SECURITY); > + case 25: return sprintf (name, "%s", RD_PWRCTRL); > + case 26: return sprintf (name, "%s", RD_VOLTAGE); > + case 27: return sprintf (name, "%s", RD_COOLINGDEV); > + case 28: return sprintf (name, "%s", RD_TEMP); > + case 29: return sprintf (name, "%s", RD_CURRENT); > + case 30: return sprintf (name, "%s", RD_RMTACCESS); > + case 31: return sprintf (name, "%s", RD_BIS); > + case 32: return sprintf (name, "%s", RD_BOOT_INFO); > + case 33: return sprintf (name, "%s", RD_64MEMERR); > + case 34: return sprintf (name, "%s", RD_MANAGDEV); > + case 35: return sprintf (name, "%s", RD_MANAGDEVCOMP); > + case 36: return sprintf (name, "%s", RD_MANAGDEVTHRESH); > + case 37: return sprintf (name, "%s", RD_MEMCHANNEL); > + case 38: return sprintf (name, "%s", RD_IPMI); > + case 39: return sprintf (name, "%s", RD_PWRSUP); > + case 126: return sprintf (name, "%s", RD_INACTIVE); > + case 127: return sprintf (name, "%s", RD_EOT); > + default: return sprintf (name, "%d", struct_ptr->type); > + } > +} > +unsigned int smbios_get_readable_name_ext(char *name, struct smbios_struct *struct_ptr) > +{ > + return sprintf (name, "%d-%d", struct_ptr->type, struct_ptr->subtype); > +} > + > +int smbios_make_dir_entries (void) > +{ > + int i; > + unsigned int raw_name_length = 0; > + char raw_name[12]; /* e.g. 0.0 for structure type 0 , first instance */ > + unsigned int readable_name_length = 0; > + char readable_name[64]; /* e.g. Bios.0 for structure type 0 , first instance */ > + struct smbios_struct *struct_ptr = smbios_structures_base; > + /* > + * for every SMBIOS structure do ... > + */ > + for (i = 0; i < smbios_entry_point->no_of_structures; i++) > + { > + memset(raw_name,0,12); > + memset(readable_name,0,64); > + /* > + * generate an unique name for the file: "type[-subtype].count" > + */ > + if (smbios_type_has_subtype (((struct smbios_struct *) struct_ptr)->type)) > + { > + /* name will contain the raw file name, it equals the structure type (e.g. 1 for Type 1). > + * readable_name contains the interpreted file name (e.g. System for Type 1) > + */ > + raw_name_length = sprintf (raw_name, "%d-%d", struct_ptr->type, struct_ptr->subtype); > + readable_name_length = smbios_get_readable_name_ext(readable_name, struct_ptr); > + //printk(KERN_INFO "[%s] smbios_type_has_subtype[%d] length:%d\n",raw_name,struct_ptr->type,struct_ptr->length); > + } > + else > + { > + raw_name_length = sprintf (raw_name, "%d", struct_ptr->type); > + readable_name_length = smbios_get_readable_name(readable_name, struct_ptr); > + //printk(KERN_INFO "[%s] smbios_type_has type:%d length:%d\n",readable_name,struct_ptr->type,struct_ptr->length); > + } > + > + /* > + * go to the next structure > + */ > + struct_ptr =(struct smbios_struct *) ((unsigned char *) struct_ptr + smbios_get_struct_length(struct_ptr)); > + } > + > + return 0; > +} > + > +int smbios_check_if_have_exar_config(unsigned char *config0,unsigned char *config1) > +{ > + int i; > + int result = -1; > + unsigned char *p; > + smbios_base = ioremap (BIOS_START_ADDRESS, BIOS_MAP_LENGTH); > + if(!smbios_base) > + { > + SM_BIOS_DEBUG ("ioremap() for entry point failed\n"); > + result = -ENXIO; > + return result; > + } > + //printk(KERN_INFO "ioremap bios base at 0x%p\n", smbios_base); > + if (!(smbios_entry_point = smbios_find_entry_point (smbios_base))) > + { > + SM_BIOS_DEBUG ("SM-BIOS entry point not found\n"); > + iounmap (smbios_base); > + result = -ENXIO; > + return result; > + > + } > + /* > + * for SM-BIOS: > + * check if Pointer to DMI structures exist. > + * intermediate_string (_DMI_) is not '\0' terminated, > + * so strncmp() with sizeof(DMI_STRING) - 1 is needed. > + */ > + if (smbios_entry_point) > + { > + if (strncmp((char *) &(smbios_entry_point->intermediate_string), > + DMI_STRING, sizeof (DMI_STRING) - 1)) > + { > + SM_BIOS_DEBUG ("Pointer to DMI structures not found!\n"); > + > + } > + } > + > + /* > + * map the SM-BIOS structures physical address range. > + * the 'real' smbios_structures_base contains the starting > + * address, where the instances of dmi structures are located. > + */ > + if (smbios_entry_point) > + { > + if (!(smbios_structures_base = > + ioremap (smbios_entry_point->struct_table_address, > + (unsigned long) smbios_entry_point->struct_table_length))) > + { > + SM_BIOS_DEBUG("ioremap() for structures table failed\n"); > + iounmap (smbios_base); > + result = -ENXIO; > + return result; > + } > + } > + SM_BIOS_DEBUG(KERN_INFO "smbios_structures_base to 0x%p length %d no_of_structures:%d\n", > + smbios_structures_base, > + smbios_entry_point->struct_table_length, > + smbios_entry_point->no_of_structures); > + > + //dump_smbios_hex((unsigned char *)smbios_structures_base,smbios_entry_point->struct_table_length); > + p = (unsigned char *)smbios_structures_base; > + for(i=0;i<smbios_entry_point->struct_table_length;i++) > + { > + if((p[i] == 0xc0)&&(p[i+1]==0x06)) > + { > + SM_BIOS_DEBUG("Found 0xc0 at offset:%d 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x \n\t",i,p[i],p[i+1],p[i+2],p[i+3],p[i+4],p[i+5]); > + *config0 = p[i+4]; > + *config1 = p[i+5]; > + result = 0; > + break; > + } > + } > + //smbios_make_dir_entries(); > + iounmap (smbios_structures_base); > + iounmap (smbios_base); > + return result; > + > +} > +/* > +void dmi_dump_backup(void) > +{ > + const char *board_vendor, *board_name,*board_serial; > + const struct dmi_device *dmi; > + struct dmi_dev_onboard *donboard; > + board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); > + board_name = dmi_get_system_info(DMI_BOARD_NAME); > + board_serial = dmi_get_system_info(DMI_BOARD_SERIAL); > + printk(KERN_INFO "DMI_BOARD_VENDOR:%s\n",board_vendor); > + printk(KERN_INFO "DMI_BOARD_NAME:%s\n",board_name); > + printk(KERN_INFO "DMI_BOARD_SERIAL:%s\n",board_serial); > + for(i=0;i<256;i++) > + { > + dmi = NULL; > + //printk(KERN_INFO "dmi_find_device<%d>\n",i); > + while ((dmi = dmi_find_device(i,NULL, dmi)) != NULL) > + { > + //donboard = dmi->device_data; > + printk(KERN_INFO "<%d>Found name:%s type:%d \n",i,dmi->name,dmi->type); > + } > + } > + > +} > +*/ > + > diff --git a/ubuntu/xr-usb-serial/xr_get_smbios.h b/ubuntu/xr-usb-serial/xr_get_smbios.h > new file mode 100644 > index 000000000000..f56b33084dab > --- /dev/null > +++ b/ubuntu/xr-usb-serial/xr_get_smbios.h > @@ -0,0 +1,237 @@ > +/* Copyright (C) 2001-2001 Fujitsu Siemens Computers > + Joachim Braeuer > + This file is part of smbios > + > + smbios is free software; you can redistribute it and/or modify it > + under the terms of the GNU General Public License as published by > + the Free Software Foundation; either version 2 of the License, > + or (at your option) any later version. > + > + smbios is distributed in the hope that it will be useful, but WITHOUT > + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or > + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License > + for more details. > + > + You should have received a copy of the GNU General Public License > + along with smbios; see the file COPYING. If not, write to the > + Free Software Foundation, Inc., 59 Temple Place - Suite 330, > + Boston, MA 02111-1307, USA. > +*/ > + > +/* $Id: bios.h,v 1.2 2002/09/03 10:33:12 bretthauert Exp $ > + * > + * $Log: bios.h,v $ > + * Revision 1.2 2002/09/03 10:33:12 bretthauert > + * fixed a bug with 2.4 kernels (changed kmalloc parameter from > + * GFP_BUFFER to GFP_KERNEL > + * > + * Revision 1.1 2001/09/15 14:52:43 bretthauert > + * initial release > + * > + */ > + > +/** \file bios.h > + * declarations and prototypes of DMI-BIOS and SM-BIOS stuff > + * > + * \author Markus Lyra > + * \author Thomas Bretthauer > + * \author Joachim Braeuer > + * \version 0.11 > + * \date January 2001 > + */ > + > +#ifndef __SM_BIOS_H__ > +#define __SM_BIOS_H__ > + > +#include <linux/types.h> > +//#define _EN_DEBUG_ 1 > +#ifdef _EN_DEBUG_ > +# define SM_BIOS_DEBUG(fmt, args...) printk( KERN_DEBUG "smbios: " fmt, ## args) > +#else > +# define SM_BIOS_DEBUG(fmt, args...) /* not debugging: nothing */ > +#endif > +/* > + * Magic numbers > + */ > + > +/** start address of BIOS segment to scanned for SM-BIOS and DMI-BIOS */ > +#define BIOS_START_ADDRESS 0xF0000 > +/** length of the scanned BIOS area for SM-BIOS and DMI-BIOS */ > +#define BIOS_MAP_LENGTH 0x10000 > +/** magic 4 bytes to identify SM-BIOS entry point, paragraph boundary */ > +#define SMBIOS_MAGIC_DWORD 0x5F4D535F /* anchor string "_SM_" */ > +/** magic 4 bytes to identify DMI-BIOS entry point, byte boundary */ > +#define DMIBIOS_MAGIC_DWORD 0x494d445f /* anchor string "_DMI" */ > +/** identifier for SM-BIOS structures within SM-BIOS entry point */ > +#define DMI_STRING "_DMI_" > +/** list of types which are known to have subtyes; expandable! */ > +#define TYPES_WITH_SUBTYPES 185, 187, 208, 209, 210, 211, 212, 254 > +/** maximum block size for proc read function */ > +#define PROC_BLOCK_SIZE (3*1024) > + > + > +/** mode raw/cooked */ > +#define FILE_MODE_RAW 0 > +#define FILE_MODE_COOKED 1 > + > +/* > + * Structures > + */ > + > +/** SM-BIOS entry point structure > + * the SMBIOS Entry Point structure described below can be located by > + * application software by searching for the anchor string on paragraph > + * (16 byte) boundaries within the physical memory address range 000F0000h to > + * 000FFFFFh. This entry point encapsulates an intermediate anchor string > + * that is used by some existing DMI browsers. > + * > + * @note While the SMBIOS Major and Minor Versions (offsets 06h and 07h) > + * currently duplicate the information present in the SMBIOS BCD Revision > + * (offset 1Dh), they provide a path for future growth in this specification. > + * The BCD Revision, for example, provides only a single digit for each of > + * the major and minor version numbers. > + */ > +struct smbios_entry_point_struct > +{ > + /** "_SM_", specified as four ASCII characters (5F 53 4D 5F) */ > + __u32 anchor_string; > + /** checksum of the Entry Point Structure (EPS). This value, when added to > + * all other bytes in the EPS, will result in the value 00h (using 8 bit > + * addition calculations). Values in the EPS are summed starting at offset > + * 00h, for Entry Point Length bytes.*/ > + __u8 entry_point_checksum; > + /** Length of the Entry Point Structure, starting with the Anchor String > + * field, in bytes, currently 1Fh. */ > + __u8 entry_point_length; > + /** identifies the major version of this specification implemented in > + * the table structures, e.g. the value will be 0Ah for revision 10.22 > + * and 02h for revision 2.1 */ > + __u8 major_version; > + /** identifies the minor version of this specification implemented in > + * the table structures, e.g. the value will be 16h for revision 10.22 > + * and 01h for revision 2.1 */ > + __u8 minor_version; > + /** size of the largest SMBIOS structure, in bytes, and encompasses the > + * structure's formatted area and text strings. This is the value returned > + * as StructureSize from the Plug-n-Play 'Get SMBIOS Information' function */ > + __u16 max_struct_size; > + /** identifies the EPS revision implemented in this structure and identifies > + * the formatting of offsets 0Bh to 0Fh, one of: > + * 00h Entry Point based on SMBIOS 2.1 definition; formatted area is > + * reserved and set to all 00h. > + * 01h-FFh reserved for assignment via this specification */ > + __u8 revision; > + /** the value present in the Entry Point Revision field defines the > + * interpretation to be placed upon these5 bytes. */ > + __u8 formated_area[5]; > + /** "_DMI_", specified as five ASCII characters (5F 44 4D 49 5F) */ > + __u8 intermediate_string[5]; > + /** checksum of the Intermediate Entry Point Structure (IEPS). This value, > + * when added to all other bytes in the IEPS, will result in the value 00h > + * (using 8 bit addition calculations). Values in the IEPS are summed > + * starting at offset 10h, for 0Fh bytes */ > + __u8 intermediate_checksum; > + /** the 32 bit physical starting address of the read-only SMBIOS Structure > + * Table, that can start at any 32 bit address. This area contains all of the > + * SMBIOS structures fully packed together. These structures can then be > + * parsed to produce exactly the same format as that returned from a 'Get > + * SMBIOS Structure' function call. */ > + __u16 struct_table_length; > + __u32 struct_table_address; > + __u16 no_of_structures; > + __u8 bcd_revision; > +}__attribute__ ((packed)); > + > +/** SM-BIOS and DMI-BIOS structure header */ > +struct smbios_struct > +{ > + __u8 type ; > + __u8 length ; > + __u16 handle ; > + __u8 subtype; > + /* ... other fields are structure dependend ... */ > +} __attribute__ ((packed)); > + > +/** DMI-BIOS structure header */ > +struct dmibios_table_entry_struct > +{ > + __u16 size; > + __u16 handle; > + __u32 procedure; > +}__attribute__ ((packed)); > + > +/** DMI-BIOS entry point structure */ > +struct dmibios_entry_point_struct > +{ > + __u8 signature[10]; > + __u8 revision; > + struct dmibios_table_entry_struct entry[1]; > +}__attribute__ ((packed)); > + > +/** readable names for smbios structures, they serve as filenames in the /proc file system */ > +#define RD_BIOS "bios" > +#define RD_SYSTEM "system" > +#define RD_BASEBOARD "baseboard" > +#define RD_ENCLOSURE "enclosure" > +#define RD_PROCESSOR "processor" > +#define RD_MEMCTRL "memory_controller" > +#define RD_MEMMOD "memory_module" > +#define RD_CACHE "cache" > +#define RD_PORT "port_connector" > +#define RD_SLOT "system_slot" > +#define RD_ONBOARD "onboard_device" > +#define RD_OEMSTRINGS "oem_strings" > +#define RD_SYSTEMCONFIG "system_configuration" > +#define RD_BIOSLANG "bios_language" > +#define RD_GROUPASSOC "group_association" > +#define RD_EVENTLOG "system_event_log" > +#define RD_MEMARRAY "physical_memory_array" > +#define RD_MEMDEV "physical_memory_device" > +#define RD_32MEMERR "32bit_memory_error_information" > +#define RD_MEMMAPPEDADR "memory_array_mapped_address" > +#define RD_MEMMAPPEDDEV "memory_device_mapped_address" > +#define RD_POINTINGDEV "pointing_device" > +#define RD_BATTERY "portable_battery" > +#define RD_RESET "system_reset" > +#define RD_SECURITY "hardware_security" > +#define RD_PWRCTRL "system_power_controls" > +#define RD_VOLTAGE "voltage_probe" > +#define RD_COOLINGDEV "cooling_device" > +#define RD_TEMP "temperature_probe" > +#define RD_CURRENT "current_probe" > +#define RD_RMTACCESS "out_of_band_remote_access" > +#define RD_BIS "boot_integrity_services" > +#define RD_BOOT_INFO "system_boot_information" > +#define RD_64MEMERR "64bit_memory_error_information" > +#define RD_MANAGDEV "management_device" > +#define RD_MANAGDEVCOMP "management_device_component" > +#define RD_MANAGDEVTHRESH "management_device_thresholds" > +#define RD_MEMCHANNEL "memory_channel" > +#define RD_IPMI "ipmi_information" > +#define RD_PWRSUP "system_power_supply" > +#define RD_INACTIVE "inactive" > +#define RD_EOT "end_of_table" > + > + > +//extern smbios_entry_point_struct * smbios_entry_point; /* start of SMBIOS within the F-Segment */ > +//extern dmibios_entry_point_struct * dmibios_entry_point; /* start of DMIBIOS within the F-Segment */ > +extern void * smbios_structures_base; /* base of SMBIOS raw structures */ > +extern unsigned char smbios_types_with_subtypes[]; > +extern char smbios_version_string[32]; /* e.g. V2.31 */ > +/* > + * Functions > + */ > + > +/* for the description see the implementation file */ > +struct smbios_entry_point_struct * smbios_find_entry_point(void * base); > +struct dmibios_entry_point_struct * dmibios_find_entry_point(void * base); > +unsigned char smbios_check_entry_point(void * addr); > +int smbios_type_has_subtype(unsigned char type); > +int smbios_get_struct_length(struct smbios_struct * struct_ptr); > +int dmibios_get_struct_length(struct smbios_struct * struct_ptr); > +unsigned int smbios_get_readable_name_ext(char *readable_name, struct smbios_struct *struct_ptr); > +unsigned int smbios_get_readable_name(char *readable_name, struct smbios_struct *struct_ptr); > +int smbios_check_if_have_exar_config(unsigned char *config0,unsigned char *config1); > + > + > +#endif /* __BIOS_H__ */ > diff --git a/ubuntu/xr-usb-serial/xr_usb_serial_common.c b/ubuntu/xr-usb-serial/xr_usb_serial_common.c > index d16f072613b1..5d049855fb1a 100644 > --- a/ubuntu/xr-usb-serial/xr_usb_serial_common.c > +++ b/ubuntu/xr-usb-serial/xr_usb_serial_common.c > @@ -28,12 +28,12 @@ > * from www.exar.com that will work with kernel versions 2.6.18 to 3.4.x. > * > * ChangeLog: > - * Version 1A - Initial released version. > + * Version 1B - Initial released version. > */ > > -//#undef DEBUG > +#undef DEBUG > #undef VERBOSE_DEBUG > - > +#include <linux/gpio.h> > #include <linux/kernel.h> > #include <linux/errno.h> > #include <linux/init.h> > @@ -47,15 +47,20 @@ > #include <linux/uaccess.h> > #include <linux/usb.h> > #include <linux/usb/cdc.h> > +#include <linux/dmi.h> > #include <asm/byteorder.h> > #include <asm/unaligned.h> > #include <linux/list.h> > +#include <linux/delay.h> > +#include <asm/io.h> /* ioremap() */ > #include "linux/version.h" > > +#include "xr_get_smbios.h" > #include "xr_usb_serial_common.h" > #include "xr_usb_serial_ioctl.h" > > > + > #define DRIVER_AUTHOR "<uarttechsupport@exar.com>" > #define DRIVER_DESC "Exar USB UART (serial port) driver" > > @@ -65,6 +70,10 @@ static struct xr_usb_serial *xr_usb_serial_table[XR_USB_SERIAL_TTY_MINORS]; > > static DEFINE_MUTEX(xr_usb_serial_table_lock); > > + > + > + > + > /* > * xr_usb_serial_table accessors > */ > @@ -137,6 +146,7 @@ static int xr_usb_serial_ctrl_msg(struct xr_usb_serial *xr_usb_serial, int reque > return retval < 0 ? retval : 0; > } > > +#include "xr_get_smbios.c" > #include "xr_usb_serial_hal.c" > > > @@ -249,46 +259,6 @@ static ssize_t show_country_rel_date > } > > static DEVICE_ATTR(iCountryCodeRelDate, S_IRUGO, show_country_rel_date, NULL); > - > -static ssize_t set_rs485_422_en(struct device *dev, > - struct device_attribute *attr, const char *buf, > - size_t count) > -{ > - struct usb_interface *intf = to_usb_interface(dev); > - struct xr_usb_serial *xr_usb_serial = usb_get_intfdata(intf); > - int error, value = 0; > - > - error = kstrtoint(buf, 0, &value); > - if (error) > - return error; > - > - if (value == 0) { > - xr_usb_serial->rs485_422_en = false; > - } else if (value == 1) { > - // RS485,RS422 HD/FD mode > - xr_usb_serial->rs485_422_en = true; > - } > - > - return count; > -} > - > -static ssize_t show_rs485_422_en(struct device *dev, > - struct device_attribute *attr, char *buf) > -{ > - struct usb_interface *intf = to_usb_interface(dev); > - struct xr_usb_serial *xr_usb_serial = usb_get_intfdata(intf); > - > - if (xr_usb_serial->rs485_422_en == false) { > - return sprintf(buf, "0"); > - } else if (xr_usb_serial->rs485_422_en == true) { > - // RS485,RS422 HD/FD mode > - return sprintf(buf, "1"); > - } > - return 0; > -} > - > -static DEVICE_ATTR(bRS485_422_en, 0644, show_rs485_422_en, set_rs485_422_en); > - > /* > * Interrupt handlers for various XR_USB_SERIAL device responses > */ > @@ -298,7 +268,10 @@ static void xr_usb_serial_ctrl_irq(struct urb *urb) > { > struct xr_usb_serial *xr_usb_serial = urb->context; > struct usb_cdc_notification *dr = urb->transfer_buffer; > - struct tty_struct *tty; > +#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 9, 0) > +#else > + struct tty_struct *tty; > +#endif > unsigned char *data; > int newctrl; > int retval; > @@ -309,10 +282,11 @@ static void xr_usb_serial_ctrl_irq(struct urb *urb) > switch (status) { > case 0: > p = (unsigned char *)(urb->transfer_buffer); > + /* > for(i=0;i<urb->actual_length;i++) > { > dev_dbg(&xr_usb_serial->control->dev,"0x%02x\n",p[i]); > - } > + }*/ > /* success */ > break; > case -ECONNRESET: > @@ -362,7 +336,7 @@ static void xr_usb_serial_ctrl_irq(struct urb *urb) > } > #endif > xr_usb_serial->ctrlin = newctrl; > - > + #if 0 > dev_dbg(&xr_usb_serial->control->dev, > "%s - input control lines: dcd%c dsr%c break%c " > "ring%c framing%c parity%c overrun%c\n", > @@ -374,6 +348,7 @@ static void xr_usb_serial_ctrl_irq(struct urb *urb) > xr_usb_serial->ctrlin & XR_USB_SERIAL_CTRL_FRAMING ? '+' : '-', > xr_usb_serial->ctrlin & XR_USB_SERIAL_CTRL_PARITY ? '+' : '-', > xr_usb_serial->ctrlin & XR_USB_SERIAL_CTRL_OVERRUN ? '+' : '-'); > + #endif > break; > > default: > @@ -399,7 +374,7 @@ static int xr_usb_serial_submit_read_urb(struct xr_usb_serial *xr_usb_serial, in > if (!test_and_clear_bit(index, &xr_usb_serial->read_urbs_free)) > return 0; > > - dev_vdbg(&xr_usb_serial->data->dev, "%s - urb %d\n", __func__, index); > + //dev_vdbg(&xr_usb_serial->data->dev, "%s - urb %d\n", __func__, index); > > res = usb_submit_urb(xr_usb_serial->read_urbs[index], mem_flags); > if (res) { > @@ -430,10 +405,75 @@ static int xr_usb_serial_submit_read_urbs(struct xr_usb_serial *xr_usb_serial, g > } > static void xr_usb_serial_process_read_urb(struct xr_usb_serial *xr_usb_serial, struct urb *urb) > { > - struct tty_struct *tty; > +#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 9, 0) > +#else > + struct tty_struct *tty; > +#endif > + int preciseflags = xr_usb_serial->preciseflags; > + int have_extra_byte; > + int length; > + > if (!urb->actual_length) > return; > -#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 9, 0) > + > + if (preciseflags) > + { > + char *dp = urb->transfer_buffer; > + int i, ch, ch_flags; > + > + length = urb->actual_length; > + length = length + (xr_usb_serial->have_extra_byte ? 1 : 0); > + have_extra_byte = (preciseflags && (length & 1)); > + length = (preciseflags) ? (length / 2) : length; > + for (i = 0; i < length; ++i) > + { > + char tty_flag; > + if (i == 0) > + { > + if (xr_usb_serial->have_extra_byte) > + { > + ch = xr_usb_serial->extra_byte; > + } > + else > + { > + ch = *dp++; > + } > + } > + else > + { > + ch = *dp++; > + } > + ch_flags = *dp++; > + if (ch_flags & RAMCTL_BUFFER_PARITY) > + tty_flag = TTY_PARITY; > + else if (ch_flags & RAMCTL_BUFFER_BREAK) > + tty_flag = TTY_BREAK; > + else if (ch_flags & RAMCTL_BUFFER_FRAME) > + tty_flag = TTY_FRAME; > + else if (ch_flags & RAMCTL_BUFFER_OVERRUN) > + tty_flag = TTY_OVERRUN; > + else > + tty_flag = TTY_NORMAL; > + > + > +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) > + tty_insert_flip_char(&xr_usb_serial->port, ch, tty_flag); > + tty_flip_buffer_push(&xr_usb_serial->port); > +#else > + tty = tty_port_tty_get(&xr_usb_serial->port); > + if (!tty) > + return; > + tty_insert_flip_char(&xr_usb_serial->port, ch, tty_flag); > + tty_flip_buffer_push(tty); > + > + tty_kref_put(tty); > +#endif > + > + } > + } > + else > + { > +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) > tty_insert_flip_string(&xr_usb_serial->port, urb->transfer_buffer, > urb->actual_length); > tty_flip_buffer_push(&xr_usb_serial->port); > @@ -446,6 +486,7 @@ static void xr_usb_serial_process_read_urb(struct xr_usb_serial *xr_usb_serial, > > tty_kref_put(tty); > #endif > + } > } > > static void xr_usb_serial_read_bulk_callback(struct urb *urb) > @@ -453,9 +494,10 @@ static void xr_usb_serial_read_bulk_callback(struct urb *urb) > struct xr_usb_serial_rb *rb = urb->context; > struct xr_usb_serial *xr_usb_serial = rb->instance; > unsigned long flags; > - > + /* > dev_vdbg(&xr_usb_serial->data->dev, "%s - urb %d, len %d\n", __func__, > - rb->index, urb->actual_length); > + rb->index, urb->actual_length);*/ > + > set_bit(rb->index, &xr_usb_serial->read_urbs_free); > > if (!xr_usb_serial->dev) { > @@ -467,7 +509,7 @@ static void xr_usb_serial_read_bulk_callback(struct urb *urb) > if (urb->status) { > dev_dbg(&xr_usb_serial->data->dev, "%s - non-zero urb status: %d\n", > __func__, urb->status); > - return; > + //return; > } > xr_usb_serial_process_read_urb(xr_usb_serial, urb); > > @@ -505,9 +547,13 @@ static void xr_usb_serial_write_bulk(struct urb *urb) > static void xr_usb_serial_softint(struct work_struct *work) > { > struct xr_usb_serial *xr_usb_serial = container_of(work, struct xr_usb_serial, work); > - struct tty_struct *tty; > +#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 9, 0) > +#else > + struct tty_struct *tty; > +#endif > + > > - dev_vdbg(&xr_usb_serial->data->dev, "%s\n", __func__); > + //dev_vdbg(&xr_usb_serial->data->dev, "%s\n", __func__); > #if LINUX_VERSION_CODE > KERNEL_VERSION(3, 9, 0) > tty_port_tty_wakeup(&xr_usb_serial->port); > #else > @@ -528,7 +574,7 @@ static int xr_usb_serial_tty_install(struct tty_driver *driver, struct tty_struc > struct xr_usb_serial *xr_usb_serial; > int retval; > > - dev_dbg(tty->dev, "%s\n", __func__); > + //dev_dbg(tty->dev, "%s\n", __func__); > > xr_usb_serial = xr_usb_serial_get_by_index(tty->index); > if (!xr_usb_serial) > @@ -550,9 +596,10 @@ static int xr_usb_serial_tty_install(struct tty_driver *driver, struct tty_struc > static int xr_usb_serial_tty_open(struct tty_struct *tty, struct file *filp) > { > struct xr_usb_serial *xr_usb_serial = tty->driver_data; > - > - dev_dbg(tty->dev, "%s\n", __func__); > - > + int result; > + result = xr_usb_serial_fifo_reset(xr_usb_serial); > + //dev_dbg(tty->dev, "%s\n", __func__); > + > return tty_port_open(&xr_usb_serial->port, tty, filp); > } > > @@ -561,7 +608,7 @@ static int xr_usb_serial_port_activate(struct tty_port *port, struct tty_struct > struct xr_usb_serial *xr_usb_serial = container_of(port, struct xr_usb_serial, port); > int retval = -ENODEV; > > - dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); > + //dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); > > mutex_lock(&xr_usb_serial->mutex); > if (xr_usb_serial->disconnected) > @@ -624,14 +671,18 @@ static void xr_usb_serial_port_destruct(struct tty_port *port) > { > struct xr_usb_serial *xr_usb_serial = container_of(port, struct xr_usb_serial, port); > > - dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); > + //dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); > #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0) > tty_unregister_device(xr_usb_serial_tty_driver, xr_usb_serial->minor); > #endif > +#ifdef CONFIG_GPIOLIB > + gpiochip_remove(&xr_usb_serial->xr_usb_gpio); > +#endif > xr_usb_serial_release_minor(xr_usb_serial); > usb_put_intf(xr_usb_serial->control); > kfree(xr_usb_serial->country_codes); > kfree(xr_usb_serial); > + > } > > static void xr_usb_serial_port_shutdown(struct tty_port *port) > @@ -639,7 +690,7 @@ static void xr_usb_serial_port_shutdown(struct tty_port *port) > struct xr_usb_serial *xr_usb_serial = container_of(port, struct xr_usb_serial, port); > int i; > > - dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); > + //dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); > > mutex_lock(&xr_usb_serial->mutex); > if (!xr_usb_serial->disconnected) { > @@ -659,21 +710,21 @@ static void xr_usb_serial_port_shutdown(struct tty_port *port) > static void xr_usb_serial_tty_cleanup(struct tty_struct *tty) > { > struct xr_usb_serial *xr_usb_serial = tty->driver_data; > - dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); > + //dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); > tty_port_put(&xr_usb_serial->port); > } > > static void xr_usb_serial_tty_hangup(struct tty_struct *tty) > { > struct xr_usb_serial *xr_usb_serial = tty->driver_data; > - dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); > + //dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); > tty_port_hangup(&xr_usb_serial->port); > } > > static void xr_usb_serial_tty_close(struct tty_struct *tty, struct file *filp) > { > struct xr_usb_serial *xr_usb_serial = tty->driver_data; > - dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); > + //dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); > tty_port_close(&xr_usb_serial->port, tty, filp); > } > > @@ -689,7 +740,7 @@ static int xr_usb_serial_tty_write(struct tty_struct *tty, > if (!count) > return 0; > > - dev_vdbg(&xr_usb_serial->data->dev, "%s - count %d\n", __func__, count); > + //dev_vdbg(&xr_usb_serial->data->dev, "%s - count %d\n", __func__, count); > > spin_lock_irqsave(&xr_usb_serial->write_lock, flags); > wbn = xr_usb_serial_wb_alloc(xr_usb_serial); > @@ -706,7 +757,7 @@ static int xr_usb_serial_tty_write(struct tty_struct *tty, > } > > count = (count > xr_usb_serial->writesize) ? xr_usb_serial->writesize : count; > - dev_vdbg(&xr_usb_serial->data->dev, "%s - write %d\n", __func__, count); > + //dev_vdbg(&xr_usb_serial->data->dev, "%s - write %d\n", __func__, count); > memcpy(wb->buf, buf, count); > wb->len = count; > > @@ -785,7 +836,7 @@ static int xr_usb_serial_tty_break_ctl(struct tty_struct *tty, int state) > > retval = xr_usb_serial_send_break(xr_usb_serial, state ? 0xffff : 0); > if (retval < 0) > - dev_dbg(&xr_usb_serial->control->dev, "%s - send break failed\n", > + dev_err(&xr_usb_serial->control->dev, "%s - send break failed\n", > __func__); > return retval; > } > @@ -793,7 +844,7 @@ static int xr_usb_serial_tty_break_ctl(struct tty_struct *tty, int state) > static int xr_usb_serial_tty_tiocmget(struct tty_struct *tty) > { > struct xr_usb_serial *xr_usb_serial = tty->driver_data; > - dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_tty_tiocmget\n"); > + //dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_tty_tiocmget\n"); > return xr_usb_serial_tiocmget(xr_usb_serial); > > } > @@ -802,7 +853,7 @@ static int xr_usb_serial_tty_tiocmset(struct tty_struct *tty, > unsigned int set, unsigned int clear) > { > struct xr_usb_serial *xr_usb_serial = tty->driver_data; > - dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_tty_tiocmset set=0x%x clear=0x%x\n",set,clear); > + //dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_tty_tiocmset set=0x%x clear=0x%x\n",set,clear); > return xr_usb_serial_tiocmset(xr_usb_serial,set,clear); > > } > @@ -865,8 +916,9 @@ static int xr_usb_serial_tty_ioctl(struct tty_struct *tty, > { > struct xr_usb_serial *xr_usb_serial = tty->driver_data; > int rv = -ENOIOCTLCMD; > - unsigned int channel, reg, val; > - > + unsigned int channel, reg, val,preciseflags; > + int baud_rate = 0; > + struct usb_cdc_line_coding newline; > short *data; > switch (cmd) { > case TIOCGSERIAL: /* gets serial port data */ > @@ -895,7 +947,8 @@ static int xr_usb_serial_tty_ioctl(struct tty_struct *tty, > { > rv = xr_usb_serial_get_reg_ext(xr_usb_serial,channel,reg, data); > } > - if (rv != 1) { > + if (rv < 0) > + { > dev_err(&xr_usb_serial->control->dev, "Cannot get register (%d)\n", rv); > kfree(data); > return -EFAULT; > @@ -941,6 +994,93 @@ static int xr_usb_serial_tty_ioctl(struct tty_struct *tty, > return -EFAULT; > rv = 0; > break; > + case XR_USB_SERIAL_SET_GPIO_MODE_REG: > + xr_usb_serial_disable(xr_usb_serial); > + if (get_user(channel, (int __user *)arg)) > + return -EFAULT; > + if (get_user(val, (int __user *)(arg + sizeof(int)))) > + return -EFAULT; > + if (channel == -1) > + { > + //block = portdata->block; > + rv = xr_usb_serial_set_reg(xr_usb_serial,xr_usb_serial->reg_map.uart_gpio_mode_addr, val); > + } > + else > + { > + rv = xr_usb_serial_set_reg_ext(xr_usb_serial,channel,xr_usb_serial->reg_map.uart_gpio_mode_addr, val); > + } > + > + dev_dbg(&xr_usb_serial->control->dev, "XR_USB_SERIAL_SET_GPIO_MODE_REG 0x%x val:0x%x \n", xr_usb_serial->reg_map.uart_gpio_mode_addr,val); > + xr_usb_serial_enable(xr_usb_serial); > + if (rv < 0) > + return -EFAULT; > + break; > + case XR_USB_SERIAL_GET_GPIO_MODE_REG: > + xr_usb_serial_disable(xr_usb_serial); > + if (get_user(channel, (int __user *)arg)) > + return -EFAULT; > + > + data = kmalloc(2, GFP_KERNEL); > + if (data == NULL) { > + dev_err(&xr_usb_serial->control->dev, "%s - Cannot allocate USB buffer.\n", __func__); > + return -ENOMEM; > + } > + > + if (channel == -1) > + { > + rv = xr_usb_serial_get_reg(xr_usb_serial,xr_usb_serial->reg_map.uart_gpio_mode_addr, data); > + } > + else > + { > + rv = xr_usb_serial_get_reg_ext(xr_usb_serial,channel,xr_usb_serial->reg_map.uart_gpio_mode_addr,data); > + } > + > + xr_usb_serial_enable(xr_usb_serial); > + > + dev_dbg(&xr_usb_serial->control->dev, "XR_USB_SERIAL_GET_GPIO_MODE_REG 0x%x val:0x%x \n", xr_usb_serial->reg_map.uart_gpio_mode_addr,*data); > + > + if (rv < 0 ) { > + dev_err(&xr_usb_serial->control->dev, "Cannot get register (%d) channel=%d \n", rv,channel); > + kfree(data); > + return -EFAULT; > + } > + > + if (put_user(data[0], (int __user *)(arg + sizeof(int)))) { > + dev_err(&xr_usb_serial->control->dev, "Cannot put user result\n"); > + kfree(data); > + return -EFAULT; > + } > + > + kfree(data); > + break; > + case XRIOC_SET_ANY_BAUD_RATE: > + > + if (get_user(baud_rate, (int __user *)arg)) { > + dev_dbg(&xr_usb_serial->control->dev, "get_user errot \n"); > + return -EFAULT; > + } > + xr_usb_serial->line.dwDTERate = baud_rate; > + memcpy(&newline,&(xr_usb_serial->line),sizeof(struct usb_cdc_line_coding)); > + xr_usb_serial_disable(xr_usb_serial); > + rv = xr_usb_serial_set_line(xr_usb_serial,&newline); > + xr_usb_serial_enable(xr_usb_serial); > + dev_dbg(&xr_usb_serial->control->dev, "XRIOC_SET_ANY_BAUD_RATE set baud_rate:%d ret=%d\n", baud_rate,rv); > + break; > + case XRIOC_SET_PRECISE_FLAGS: > + preciseflags = arg; > + dev_dbg(&xr_usb_serial->control->dev, "%s VIOC_SET_PRECISE_FLAGS %d\n", __func__, preciseflags); > + xr_usb_serial_disable(xr_usb_serial); > + if (preciseflags) > + { > + xr_usb_serial->preciseflags = 1; > + } > + else > + { > + xr_usb_serial->preciseflags = 0; > + } > + xr_usb_serial_set_wide_mode(xr_usb_serial,xr_usb_serial->preciseflags); > + xr_usb_serial_enable(xr_usb_serial); > + break; > > } > > @@ -965,9 +1105,11 @@ static void xr_usb_serial_tty_set_termios(struct tty_struct *tty, > newline.bParityType = termios->c_cflag & PARENB ? > (termios->c_cflag & PARODD ? 1 : 2) + > (termios->c_cflag & CMSPAR ? 2 : 0) : 0; > + xr_usb_serial->trans9 = 0; > switch (termios->c_cflag & CSIZE) { > case CS5:/*using CS5 replace of the 9 bit data mode*/ > newline.bDataBits = 9; > + xr_usb_serial->trans9 =1; > break; > case CS6: > newline.bDataBits = 6; > @@ -993,15 +1135,27 @@ static void xr_usb_serial_tty_set_termios(struct tty_struct *tty, > xr_usb_serial_set_control(xr_usb_serial, xr_usb_serial->ctrlout = newctrl); > > xr_usb_serial_set_flow_mode(xr_usb_serial,tty,cflag);/*set the serial flow mode*/ > - > + if (xr_usb_serial->trans9) > + { > + /* Turn on wide mode if we're 9-bit transparent. */ > + xr_usb_serial_set_wide_mode(xr_usb_serial,1); > + } > + else if (!xr_usb_serial->preciseflags) > + { > + xr_usb_serial_set_wide_mode(xr_usb_serial,0); > + } > + > + > if (memcmp(&xr_usb_serial->line, &newline, sizeof newline)) > { > memcpy(&xr_usb_serial->line, &newline, sizeof newline); > + /* > dev_dbg(&xr_usb_serial->control->dev, "%s - set line: %d %d %d %d\n", > __func__, > le32_to_cpu(newline.dwDTERate), > newline.bCharFormat, newline.bParityType, > - newline.bDataBits); > + newline.bDataBits);*/ > + > xr_usb_serial_set_line(xr_usb_serial, &xr_usb_serial->line); > } > xr_usb_serial_enable(xr_usb_serial); > @@ -1060,6 +1214,36 @@ static int xr_usb_serial_write_buffers_alloc(struct xr_usb_serial *xr_usb_serial > return 0; > } > > +#ifdef CONFIG_GPIOLIB > +static int xr_usb_gpio_get(struct gpio_chip *chip, unsigned offset) > +{ > + struct xr_usb_serial *xr_usb_serial = container_of(chip, struct xr_usb_serial, xr_usb_gpio); > + dev_dbg(chip->dev, "xr_usb_gpio_get offset = %d channel = %d\n",offset,xr_usb_serial->channel); > + return 0; > +} > + > +static void xr_usb_gpio_set(struct gpio_chip *chip, unsigned offset, int val) > +{ > + struct xr_usb_serial *xr_usb_serial = container_of(chip, struct xr_usb_serial, xr_usb_gpio); > + dev_dbg(chip->dev, "xr_usb_gpio_set offset =%d val=%d channel = %d\n",offset,val,xr_usb_serial->channel); > +} > + > +static int xr_usb_gpio_direction_input(struct gpio_chip *chip,unsigned offset) > +{ > + struct xr_usb_serial *xr_usb_serial = container_of(chip, struct xr_usb_serial, xr_usb_gpio); > + dev_dbg(chip->dev, "xr_usb_gpio_direction_input offset =%d channel = %d\n",offset,xr_usb_serial->channel); > + return 0; > +} > + > +static int xr_usb_gpio_direction_output(struct gpio_chip *chip, > + unsigned offset, int val) > +{ > + struct xr_usb_serial *xr_usb_serial = container_of(chip, struct xr_usb_serial, xr_usb_gpio); > + dev_dbg(chip->dev, "xr_usb_gpio_direction_output offset =%d val=%d channel:%d\n",offset,val,xr_usb_serial->channel); > + return 0; > +} > +#endif > + > static int xr_usb_serial_probe(struct usb_interface *intf, > const struct usb_device_id *id) > { > @@ -1096,7 +1280,7 @@ static int xr_usb_serial_probe(struct usb_interface *intf, > > num_rx_buf = (quirks == SINGLE_RX_URB) ? 1 : XR_USB_SERIAL_NR; > > - dev_dbg(&intf->dev, "USB_device_id idVendor:%04x, idProduct %04x\n",id->idVendor,id->idProduct); > + //dev_dbg(&intf->dev, "USB_device_id idVendor:%04x, idProduct %04x\n",id->idVendor,id->idProduct); > > /* handle quirks deadly to normal probing*/ > if (quirks == NO_UNION_NORMAL) { > @@ -1337,7 +1521,7 @@ static int xr_usb_serial_probe(struct usb_interface *intf, > } > #else > xr_usb_serial->channel = epwrite->bEndpointAddress; > - dev_dbg(&intf->dev, "epwrite->bEndpointAddress =%d\n",epwrite->bEndpointAddress); > + //dev_dbg(&intf->dev, "epwrite->bEndpointAddress =%d\n",epwrite->bEndpointAddress); > #endif > buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &xr_usb_serial->ctrl_dma); > if (!buf) { > @@ -1424,14 +1608,9 @@ static int xr_usb_serial_probe(struct usb_interface *intf, > > usb_set_intfdata(intf, xr_usb_serial); > > - xr_usb_serial->rs485_422_en = false; //default enable rs232 > - i = device_create_file(&intf->dev, &dev_attr_bRS485_422_en); > - if (i < 0) > - goto alloc_fail7; > - > i = device_create_file(&intf->dev, &dev_attr_bmCapabilities); > if (i < 0) > - goto alloc_fail8; > + goto alloc_fail7; > > if (cfd) { /* export the country data */ > xr_usb_serial->country_codes = kmalloc(cfd->bLength - 4, GFP_KERNEL); > @@ -1470,7 +1649,7 @@ static int xr_usb_serial_probe(struct usb_interface *intf, > xr_usb_serial->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; > xr_usb_serial->ctrlurb->transfer_dma = xr_usb_serial->ctrl_dma; > > - dev_info(&intf->dev, "ttyXR_USB_SERIAL%d: USB XR_USB_SERIAL device\n", minor); > + //dev_info(&intf->dev, "ttyXR_USB_SERIAL%d: USB XR_USB_SERIAL device channel:%d\n", minor,xr_usb_serial->channel); > > xr_usb_serial_pre_setup(xr_usb_serial); > > @@ -1491,12 +1670,26 @@ static int xr_usb_serial_probe(struct usb_interface *intf, > &control_interface->dev); > if (IS_ERR(tty_dev)) { > rv = PTR_ERR(tty_dev); > - goto alloc_fail9; > + goto alloc_fail8; > } > #endif > - > +#ifdef CONFIG_GPIOLIB > + /* Setup GPIO cotroller */ > + xr_usb_serial->xr_usb_gpio.owner = THIS_MODULE; > + xr_usb_serial->xr_usb_gpio.dev = &control_interface->dev; > + xr_usb_serial->xr_usb_gpio.label = dev_name(&control_interface->dev); > + xr_usb_serial->xr_usb_gpio.direction_input = xr_usb_gpio_direction_input; > + xr_usb_serial->xr_usb_gpio.get = xr_usb_gpio_get; > + xr_usb_serial->xr_usb_gpio.direction_output = xr_usb_gpio_direction_output; > + xr_usb_serial->xr_usb_gpio.set = xr_usb_gpio_set; > + xr_usb_serial->xr_usb_gpio.base = 100 + xr_usb_serial->channel*10; > + xr_usb_serial->xr_usb_gpio.ngpio = 4; > + xr_usb_serial->xr_usb_gpio.can_sleep = 1; > + rv = gpiochip_add(&xr_usb_serial->xr_usb_gpio); > + dev_dbg(&xr_usb_serial->control->dev, "gpiochip_add %d\n",rv); > +#endif > return 0; > -alloc_fail9: > +alloc_fail8: > if (xr_usb_serial->country_codes) { > device_remove_file(&xr_usb_serial->control->dev, > &dev_attr_wCountryCodes); > @@ -1504,8 +1697,6 @@ static int xr_usb_serial_probe(struct usb_interface *intf, > &dev_attr_iCountryCodeRelDate); > } > device_remove_file(&xr_usb_serial->control->dev, &dev_attr_bmCapabilities); > -alloc_fail8: > - device_remove_file(&xr_usb_serial->control->dev, &dev_attr_bRS485_422_en); > alloc_fail7: > usb_set_intfdata(intf, NULL); > for (i = 0; i < XR_USB_SERIAL_NW; i++) > @@ -1530,7 +1721,7 @@ static void stop_data_traffic(struct xr_usb_serial *xr_usb_serial) > { > int i; > > - dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); > + //dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); > > usb_kill_urb(xr_usb_serial->ctrlurb); > for (i = 0; i < XR_USB_SERIAL_NW; i++) > @@ -1548,7 +1739,7 @@ static void xr_usb_serial_disconnect(struct usb_interface *intf) > struct tty_struct *tty; > int i; > > - dev_dbg(&intf->dev, "%s\n", __func__); > + //dev_dbg(&intf->dev, "%s\n", __func__); > > /* sibling interface is already cleaning up */ > if (!xr_usb_serial) > @@ -1563,7 +1754,6 @@ static void xr_usb_serial_disconnect(struct usb_interface *intf) > &dev_attr_iCountryCodeRelDate); > } > device_remove_file(&xr_usb_serial->control->dev, &dev_attr_bmCapabilities); > - device_remove_file(&xr_usb_serial->control->dev, &dev_attr_bRS485_422_en); > usb_set_intfdata(xr_usb_serial->control, NULL); > usb_set_intfdata(xr_usb_serial->data, NULL); > mutex_unlock(&xr_usb_serial->mutex); > @@ -1631,7 +1821,9 @@ static int xr_usb_serial_resume(struct usb_interface *intf) > struct xr_usb_serial_wb *wb; > int rv = 0; > int cnt; > - > + > + xr_usb_serial_pre_setup(xr_usb_serial); > + > spin_lock_irq(&xr_usb_serial->read_lock); > xr_usb_serial->susp_count -= 1; > cnt = xr_usb_serial->susp_count; > @@ -1670,7 +1862,10 @@ static int xr_usb_serial_resume(struct usb_interface *intf) > static int xr_usb_serial_reset_resume(struct usb_interface *intf) > { > struct xr_usb_serial *xr_usb_serial = usb_get_intfdata(intf); > - struct tty_struct *tty; > +#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 9, 0) > +#else > + struct tty_struct *tty; > +#endif > if (test_bit(ASYNCB_INITIALIZED, &xr_usb_serial->port.flags)){ > #if LINUX_VERSION_CODE > KERNEL_VERSION(3, 9, 0) > tty_port_tty_hangup(&xr_usb_serial->port, false); > @@ -1745,14 +1940,11 @@ static const struct tty_operations xr_usb_serial_ops = { > .tiocmget = xr_usb_serial_tty_tiocmget, > .tiocmset = xr_usb_serial_tty_tiocmset, > }; > - > -/* > - * Init / exit. > - */ > - > static int __init xr_usb_serial_init(void) > { > int retval; > + int i; > + > xr_usb_serial_tty_driver = alloc_tty_driver(XR_USB_SERIAL_TTY_MINORS); > if (!xr_usb_serial_tty_driver) > return -ENOMEM; > @@ -1780,17 +1972,17 @@ static int __init xr_usb_serial_init(void) > put_tty_driver(xr_usb_serial_tty_driver); > return retval; > } > - > + > printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); > > return 0; > } > - > static void __exit xr_usb_serial_exit(void) > { > usb_deregister(&xr_usb_serial_driver); > tty_unregister_driver(xr_usb_serial_tty_driver); > put_tty_driver(xr_usb_serial_tty_driver); > + > } > > module_init(xr_usb_serial_init); > diff --git a/ubuntu/xr-usb-serial/xr_usb_serial_common.h b/ubuntu/xr-usb-serial/xr_usb_serial_common.h > index fe3460c57adf..97e902425794 100644 > --- a/ubuntu/xr-usb-serial/xr_usb_serial_common.h > +++ b/ubuntu/xr-usb-serial/xr_usb_serial_common.h > @@ -70,6 +70,11 @@ > #define XR_USB_SERIAL_NW 16 > #define XR_USB_SERIAL_NR 16 > > +#define RAMCTL_BUFFER_PARITY 0x1 > +#define RAMCTL_BUFFER_BREAK 0x2 > +#define RAMCTL_BUFFER_FRAME 0x4 > +#define RAMCTL_BUFFER_OVERRUN 0x8 > + > struct xr_usb_serial_wb { > unsigned char *buf; > dma_addr_t dmah; > @@ -144,10 +149,19 @@ struct xr_usb_serial { > u8 bInterval; > struct xr_usb_serial_wb *delayed_wb; /* write queued for a device about to be woken */ > unsigned int channel; > + int preciseflags; /* USB: wide mode, TTY: flags per character */ > + int trans9; /* USB: wide mode, serial 9N1 */ > + int have_extra_byte; > + int extra_byte; > + > unsigned short DeviceVendor; > unsigned short DeviceProduct; > +#ifdef CONFIG_GPIOLIB > + struct gpio_chip xr_usb_gpio; > +#endif > struct reg_addr_map reg_map; > - bool rs485_422_en; > + int found_smbios_exar_config; > + unsigned char channel_config; > }; > > #define CDC_DATA_INTERFACE_TYPE 0x0a > diff --git a/ubuntu/xr-usb-serial/xr_usb_serial_hal.c b/ubuntu/xr-usb-serial/xr_usb_serial_hal.c > index f44970995368..bf9d2bf136ac 100644 > --- a/ubuntu/xr-usb-serial/xr_usb_serial_hal.c > +++ b/ubuntu/xr-usb-serial/xr_usb_serial_hal.c > @@ -31,7 +31,7 @@ int xr_usb_serial_set_reg(struct xr_usb_serial *xr_usb_serial,int regnum, int va > { > int result; > int channel = 0; > - dev_dbg(&xr_usb_serial->control->dev, "%s Channel:%d 0x%02x = 0x%02x\n", __func__,channel,regnum, value); > + //dev_info(&xr_usb_serial->control->dev, "%s Channel:%d 0x%02x = 0x%02x\n", __func__,channel,regnum, value); > if((xr_usb_serial->DeviceProduct&0xfff0) == 0x1400) > { > int XR2280xaddr = XR2280x_FUNC_MGR_OFFSET + regnum; > @@ -97,7 +97,7 @@ int xr_usb_serial_set_reg(struct xr_usb_serial *xr_usb_serial,int regnum, int va > result = -1; > } > if(result < 0) > - dev_dbg(&xr_usb_serial->control->dev, "%s Error:%d\n", __func__,result); > + dev_err(&xr_usb_serial->control->dev, "%s Error:%d\n", __func__,result); > return result; > > > @@ -106,7 +106,7 @@ int xr_usb_serial_set_reg_ext(struct xr_usb_serial *xr_usb_serial,int channel,in > { > int result; > int XR2280xaddr = XR2280x_FUNC_MGR_OFFSET + regnum; > - dev_dbg(&xr_usb_serial->control->dev, "%s channel:%d 0x%02x = 0x%02x\n", __func__,channel,regnum, value); > + //dev_info(&xr_usb_serial->control->dev, "%s channel:%d 0x%02x = 0x%02x\n", __func__,channel,regnum, value); > if((xr_usb_serial->DeviceProduct&0xfff0) == 0x1400) > { > result = usb_control_msg(xr_usb_serial->dev, /* usb device */ > @@ -165,7 +165,7 @@ int xr_usb_serial_set_reg_ext(struct xr_usb_serial *xr_usb_serial,int channel,in > result = -1; > } > if(result < 0) > - dev_dbg(&xr_usb_serial->control->dev, "%s Error:%d\n", __func__,result); > + dev_err(&xr_usb_serial->control->dev, "%s Error:%d\n", __func__,result); > return result; > > > @@ -242,9 +242,9 @@ int xr_usb_serial_get_reg(struct xr_usb_serial *xr_usb_serial,int regnum, short > } > > if(result < 0) > - dev_dbg(&xr_usb_serial->control->dev, "%s channel:%d Reg 0x%x Error:%d\n", __func__,channel,regnum,result); > - else > - dev_dbg(&xr_usb_serial->control->dev, "%s channel:%d 0x%x = 0x%04x\n", __func__,channel,regnum, *value); > + dev_err(&xr_usb_serial->control->dev, "%s channel:%d Reg 0x%x Error:%d\n", __func__,channel,regnum,result); > + //else > + //dev_info(&xr_usb_serial->control->dev, "%s channel:%d 0x%x = 0x%04x\n", __func__,channel,regnum, *value); > > return result; > > @@ -285,7 +285,7 @@ int xr_usb_serial_get_reg_ext(struct xr_usb_serial *xr_usb_serial,int channel,in > ®_value, /* data */ > 1, /* size */ > 5000); /* timeout */ > - dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_get_reg_ext reg:%x\n",reg_value); > + //dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_get_reg_ext reg:%x\n",reg_value); > *value = reg_value; > } > else if(xr_usb_serial->DeviceProduct == 0x1411) > @@ -320,9 +320,9 @@ int xr_usb_serial_get_reg_ext(struct xr_usb_serial *xr_usb_serial,int channel,in > } > > if(result < 0) > - dev_dbg(&xr_usb_serial->control->dev, "%s Error:%d\n", __func__,result); > - else > - dev_dbg(&xr_usb_serial->control->dev, "%s channel:%d 0x%x = 0x%04x\n", __func__,channel,regnum, *value); > + dev_err(&xr_usb_serial->control->dev, "%s Error:%d\n", __func__,result); > + //else > + //dev_info(&xr_usb_serial->control->dev, "%s channel:%d 0x%x = 0x%04x\n", __func__,channel,regnum, *value); > > return result; > > @@ -384,7 +384,7 @@ static int xr21v141x_set_baud_rate(struct xr_usb_serial *xr_usb_serial, unsigned > unsigned int tx_mask = xr21v141x_baud_rates[i].tx; > unsigned int rx_mask = (divisor & 1) ? xr21v141x_baud_rates[i].rx1 : xr21v141x_baud_rates[i].rx0; > > - dev_dbg(&xr_usb_serial->control->dev, "Setting baud rate to %d: i=%u div=%u tx=%03x rx=%03x\n", rate, i, divisor, tx_mask, rx_mask); > + //dev_info(&xr_usb_serial->control->dev, "Setting baud rate to %d: i=%u div=%u tx=%03x rx=%03x\n", rate, i, divisor, tx_mask, rx_mask); > > xr_usb_serial_set_reg(xr_usb_serial,UART_CLOCK_DIVISOR_0, (divisor >> 0) & 0xff); > xr_usb_serial_set_reg(xr_usb_serial,UART_CLOCK_DIVISOR_1, (divisor >> 8) & 0xff); > @@ -458,7 +458,7 @@ int xr_usb_serial_set_line(struct xr_usb_serial *xr_usb_serial, struct usb_cdc_l > > if (cflag & CRTSCTS) > { > - dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_set_flow_mode:hardware\n"); > + //dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_set_flow_mode:hardware\n"); > flow = UART_FLOW_MODE_HW; > gpio_mode = UART_GPIO_MODE_SEL_RTS_CTS; > } > @@ -466,7 +466,7 @@ int xr_usb_serial_set_line(struct xr_usb_serial *xr_usb_serial, struct usb_cdc_l > { > unsigned char start_char = START_CHAR(tty); > unsigned char stop_char = STOP_CHAR(tty); > - dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_set_flow_mode:software\n"); > + //dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_set_flow_mode:software\n"); > flow = UART_FLOW_MODE_SW; > gpio_mode = UART_GPIO_MODE_SEL_GPIO; > > @@ -475,23 +475,47 @@ int xr_usb_serial_set_line(struct xr_usb_serial *xr_usb_serial, struct usb_cdc_l > } > else > { > - dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_set_flow_mode:none\n"); > + //dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_set_flow_mode:none\n"); > flow = UART_FLOW_MODE_NONE; > gpio_mode = UART_GPIO_MODE_SEL_GPIO; > } > - // rs485,rs422 FD/HD mode > - if (xr_usb_serial->rs485_422_en) { > - xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_flow_addr, 0x00); > - xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, 0x0B); > - } else { > - //rs232, default mode > - xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_flow_addr, flow); > - xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, gpio_mode); > + > + if((xr_usb_serial->DeviceProduct == 0x1420)|| > + (xr_usb_serial->DeviceProduct == 0x1422)|| > + (xr_usb_serial->DeviceProduct == 0x1424)) > + {//Add support for the TXT and RXT function for 0x1420, 0x1422, 0x1424, by setting GPIO_MODE [9:8] = '11' > + gpio_mode |= 0x300; > + } > + > + if((xr_usb_serial->DeviceProduct == 0x1412)|| > + (xr_usb_serial->DeviceProduct == 0x1414)) > + { > + if(xr_usb_serial->found_smbios_exar_config) > + { > + if((xr_usb_serial->channel_config == 2) > + ||(xr_usb_serial->channel_config == 3)) > + //if find the exar channel config in the smbios, the value can not be changed by the application > + //dev_info(&xr_usb_serial->control->dev, "Sorry, Application can not change the channel gpio&flow mode,because there are config at SMBIOS\n"); > + return 0; > + } > + } > + > + xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_flow_addr, flow); > + > + if((xr_usb_serial->found_smbios_exar_config == 1)&&(xr_usb_serial->channel_config == 1)) > + { > + //dev_info(&xr_usb_serial->control->dev, "Sorry, Application can not change the channel gpio mode,because there are config at SMBIOS\n"); > } > + else > + xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, gpio_mode); > + > return 0; > > > } > + > + > + > > int xr_usb_serial_send_break(struct xr_usb_serial *xr_usb_serial, int state) > { > @@ -516,11 +540,17 @@ int xr_usb_serial_send_break(struct xr_usb_serial *xr_usb_serial, int state) > #define URM_ENABLE_BASE 0x010 > #define URM_ENABLE_0_TX 0x001 > #define URM_ENABLE_0_RX 0x002 > +#define URM_RESET_RX_FIFO_BASE 0x018 > +#define URM_RESET_TX_FIFO_BASE 0x01C > + > + > > int xr_usb_serial_enable(struct xr_usb_serial *xr_usb_serial) > { > int ret = 0; > int channel = xr_usb_serial->channel; > + //dev_info(&xr_usb_serial->control->dev, "xr_usb_serial_enable channel=%d\n",channel); > + if(channel) channel--; > if((xr_usb_serial->DeviceProduct == 0x1410)|| > (xr_usb_serial->DeviceProduct == 0x1412)|| > (xr_usb_serial->DeviceProduct == 0x1414)) > @@ -536,10 +566,31 @@ int xr_usb_serial_enable(struct xr_usb_serial *xr_usb_serial) > > return ret; > } > +int xr_usb_serial_fifo_reset(struct xr_usb_serial *xr_usb_serial) > +{ > + int ret = 0; > + int channel = xr_usb_serial->channel; > + > + if(channel) channel--; > + if((xr_usb_serial->DeviceProduct == 0x1410)|| > + (xr_usb_serial->DeviceProduct == 0x1412)|| > + (xr_usb_serial->DeviceProduct == 0x1414)) > + { > + > + ret = xr_usb_serial_set_reg_ext(xr_usb_serial,URM_REG_BLOCK,URM_RESET_RX_FIFO_BASE + channel,0xff); > + ret |= xr_usb_serial_set_reg_ext(xr_usb_serial,URM_REG_BLOCK,URM_RESET_TX_FIFO_BASE + channel,0xff); > + > + } > + return ret; > +} > + > + > int xr_usb_serial_disable(struct xr_usb_serial *xr_usb_serial) > { > int ret = 0; > int channel = xr_usb_serial->channel; > + //dev_info(&xr_usb_serial->control->dev, "xr_usb_serial_disable channel=%d\n",channel); > + if(channel) channel--; > ret = xr_usb_serial_set_reg(xr_usb_serial,xr_usb_serial->reg_map.uart_enable_addr,0); > if((xr_usb_serial->DeviceProduct == 0x1410)|| > (xr_usb_serial->DeviceProduct == 0x1412)|| > @@ -554,12 +605,81 @@ int xr_usb_serial_set_loopback(struct xr_usb_serial *xr_usb_serial, int channel) > { > int ret = 0; > xr_usb_serial_disable(xr_usb_serial); > - ret = xr_usb_serial_set_reg_ext(xr_usb_serial,channel, > + > + if((xr_usb_serial->DeviceProduct == 0x1410) || > + (xr_usb_serial->DeviceProduct == 0x1412) || > + (xr_usb_serial->DeviceProduct == 0x1414)) > + { > + switch (channel) > + { > + case 0: > + ret = xr_usb_serial_set_reg_ext(xr_usb_serial,channel, > + xr_usb_serial->reg_map.uart_loopback_addr,0x40); > + break; > + case 1: > + ret = xr_usb_serial_set_reg_ext(xr_usb_serial,channel, > + xr_usb_serial->reg_map.uart_loopback_addr,0x41); > + break; > + case 2: > + ret = xr_usb_serial_set_reg_ext(xr_usb_serial,channel, > + xr_usb_serial->reg_map.uart_loopback_addr,0x42); > + break; > + case 3: > + ret = xr_usb_serial_set_reg_ext(xr_usb_serial,channel, > + xr_usb_serial->reg_map.uart_loopback_addr,0x43); > + break; > + default: > + > + break; > + } > + } > + else if((xr_usb_serial->DeviceProduct == 0x1420)|| > + (xr_usb_serial->DeviceProduct == 0x1422)|| > + (xr_usb_serial->DeviceProduct == 0x1424)) > + { > + ret = xr_usb_serial_set_reg_ext(xr_usb_serial,channel, > xr_usb_serial->reg_map.uart_loopback_addr,0x07); > + } > xr_usb_serial_enable(xr_usb_serial); > return ret; > } > > +#define XR21V1414_WIDE_MODE_OFFSET 3 > +#define XR21B142X_WIDE_MODE_TX_OFFSET 0x42 > +#define XR21B142X_WIDE_MODE_RX_OFFSET 0x45 > +int xr_usb_serial_set_wide_mode(struct xr_usb_serial *xr_usb_serial, int preciseflags) > +{ > + int ret = 0; > + int channel = xr_usb_serial->channel; > + xr_usb_serial_disable(xr_usb_serial); > + if((xr_usb_serial->DeviceProduct&0xfff0) == 0x1400) > + { > + > + } > + else if((xr_usb_serial->DeviceProduct == 0x1410)|| > + (xr_usb_serial->DeviceProduct == 0x1412)|| > + (xr_usb_serial->DeviceProduct == 0x1414)) > + { > + > + if(channel) channel--; > + xr_usb_serial_set_reg_ext(xr_usb_serial, 0x66, channel*8 + XR21V1414_WIDE_MODE_OFFSET, preciseflags); > + > + } > + else if(xr_usb_serial->DeviceProduct == 0x1411) > + { > + xr_usb_serial_set_reg(xr_usb_serial,0xd02, preciseflags); > + } > + else if((xr_usb_serial->DeviceProduct == 0x1420)|| > + (xr_usb_serial->DeviceProduct == 0x1422)|| > + (xr_usb_serial->DeviceProduct == 0x1424)) > + { > + xr_usb_serial_set_reg(xr_usb_serial, XR21B142X_WIDE_MODE_TX_OFFSET, preciseflags); > + xr_usb_serial_set_reg(xr_usb_serial, XR21B142X_WIDE_MODE_RX_OFFSET, preciseflags); > + } > + xr_usb_serial_enable(xr_usb_serial); > + return ret; > +} > + > > static int xr_usb_serial_tiocmget(struct xr_usb_serial *xr_usb_serial) > > @@ -567,7 +687,7 @@ static int xr_usb_serial_tiocmget(struct xr_usb_serial *xr_usb_serial) > short data; > int result; > result = xr_usb_serial_get_reg(xr_usb_serial,xr_usb_serial->reg_map.uart_gpio_status_addr, &data); > - dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_tiocmget uart_gpio_status_addr:0x%04x\n",data); > + //dev_info(&xr_usb_serial->control->dev, "xr_usb_serial_tiocmget uart_gpio_status_addr:0x%04x\n",data); > if (result) > return ((data & 0x8) ? 0: TIOCM_DTR) | ((data & 0x20) ? 0:TIOCM_RTS ) | ((data & 0x4) ? 0:TIOCM_DSR) | ((data & 0x1) ? 0 : TIOCM_RI) | ((data & 0x2) ? 0:TIOCM_CD) | ((data & 0x10) ? 0 : TIOCM_CTS); > else > @@ -675,11 +795,12 @@ static void init_xr21b142x_reg_map(void) > xr21b140x_reg_map.uart_custom_driver = 0x60; > xr21b140x_reg_map.uart_low_latency = 0x46; > } > - > +int smbios_check_if_have_exar_config(unsigned char *config0,unsigned char *config1); > int xr_usb_serial_pre_setup(struct xr_usb_serial *xr_usb_serial) > { > int ret = 0; > - > + unsigned char channel1_config = 255; > + unsigned char channel2_config = 255; > init_xr21b140x_reg_map(); > init_xr21b1411_reg_map(); > init_xr21v141x_reg_map(); > @@ -716,9 +837,74 @@ int xr_usb_serial_pre_setup(struct xr_usb_serial *xr_usb_serial) > xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_dir_addr, 0x28); > xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_set_addr, UART_GPIO_SET_DTR | UART_GPIO_SET_RTS); > > + if((xr_usb_serial->DeviceProduct == 0x1412)|| > + (xr_usb_serial->DeviceProduct == 0x1414)) > + { > + xr_usb_serial->found_smbios_exar_config = 0; > + if(smbios_check_if_have_exar_config(&channel1_config,&channel2_config) == 0) > + { > + > + if(xr_usb_serial->channel == 1) > + { > + xr_usb_serial->found_smbios_exar_config = 1; > + xr_usb_serial->channel_config = channel1_config; > + switch (channel1_config) > + { > + case 1://for RS232 Mode > + //dev_info(&xr_usb_serial->control->dev, "SMBIOS Set Channel Mode to RS232\n"); > + xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, 0); > + > + break; > + case 2://RS-485 HALF DUPLEX > + //dev_info(&xr_usb_serial->control->dev, "SMBIOS Set Channel Mode to RS-485 HALF DUPLEX\n"); > + xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, 0x0b); > + xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_flow_addr, 0x00); > + break; > + case 3://RS-485/422 FULL DUPLEX > + //dev_info(&xr_usb_serial->control->dev, "SMBIOS Set Channel Mode to RS-485/422 FULL DUPLEX\n"); > + xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, 0x0b); > + xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_flow_addr, 0x00); > + break; > + default: > + xr_usb_serial->found_smbios_exar_config = 0; > + break; > + } > + > + } > + else if(xr_usb_serial->channel == 2) > + { > + xr_usb_serial->found_smbios_exar_config = 1; > + xr_usb_serial->channel_config = channel2_config; > + switch (channel2_config) > + { > + case 1://for RS232 Mode > + //dev_info(&xr_usb_serial->control->dev, "SMBIOS Set Channel Mode to RS232\n"); > + xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, 0); > + > + break; > + case 2://RS-485 HALF DUPLEX > + //dev_info(&xr_usb_serial->control->dev, "SMBIOS Set Channel Mode to RS-485 HALF DUPLEX\n"); > + xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, 0x0b); > + xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_flow_addr, 0x00); > + break; > + case 3://RS-485/422 FULL DUPLEX > + //dev_info(&xr_usb_serial->control->dev, "SMBIOS Set Channel Mode to RS-485/422 FULL DUPLEX\n"); > + xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, 0x0b); > + xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_flow_addr, 0x00); > + break; > + default: > + xr_usb_serial->found_smbios_exar_config = 0; > + break; > + } > + } > + else > + { > + //Nothing to do > + } > + } > + > + } > return ret; > > } > > - > - > diff --git a/ubuntu/xr-usb-serial/xr_usb_serial_ioctl.h b/ubuntu/xr-usb-serial/xr_usb_serial_ioctl.h > index c28b6bdc0b16..81394aac3290 100644 > --- a/ubuntu/xr-usb-serial/xr_usb_serial_ioctl.h > +++ b/ubuntu/xr-usb-serial/xr_usb_serial_ioctl.h > @@ -24,6 +24,13 @@ > #define XR_USB_SERIAL_SET_PRECISE_FLAGS _IO(XR_USB_SERIAL_IOC_MAGIC, 4) > #define XR_USB_SERIAL_TEST_MODE _IO(XR_USB_SERIAL_IOC_MAGIC, 5) > #define XR_USB_SERIAL_LOOPBACK _IO(XR_USB_SERIAL_IOC_MAGIC, 6) > +#define XR_USB_SERIAL_SET_GPIO_MODE_REG _IO(XR_USB_SERIAL_IOC_MAGIC, 9) > +#define XR_USB_SERIAL_GET_GPIO_MODE_REG _IO(XR_USB_SERIAL_IOC_MAGIC, 10) > +#define XRIOC_SET_ANY_BAUD_RATE _IO(XR_USB_SERIAL_IOC_MAGIC, 11) > +#define XRIOC_SET_PRECISE_FLAGS _IO(XR_USB_SERIAL_IOC_MAGIC, 12) > + > + > + > > #define VZ_ADDRESS_UNICAST_S 0 > #define VZ_ADDRESS_BROADCAST_S 8 >
diff --git a/ubuntu/xr-usb-serial/README.txt b/ubuntu/xr-usb-serial/README.txt index eb88f40f2080..242c8f368039 100644 --- a/ubuntu/xr-usb-serial/README.txt +++ b/ubuntu/xr-usb-serial/README.txt @@ -1,5 +1,8 @@ Exar USB Serial Driver ====================== +Version 1B, 11/6/2015 +Fixed Bug: The conditional logic to support kernel 3.9 was incorrect(line 396 in xr_usb_serial_common.c). + Version 1A, 1/9/2015 This driver will work with any USB UART function in these Exar devices: diff --git a/ubuntu/xr-usb-serial/xr_get_smbios.c b/ubuntu/xr-usb-serial/xr_get_smbios.c new file mode 100644 index 000000000000..05a995f1a957 --- /dev/null +++ b/ubuntu/xr-usb-serial/xr_get_smbios.c @@ -0,0 +1,350 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +static void *smbios_base = 0; +/** SM-BIOS entry point structure */ +struct smbios_entry_point_struct *smbios_entry_point = 0; +/** DMI-BIOS entry point structure */ +struct dmibios_entry_point_struct *dmibios_entry_point = 0; +/** SM-BIOS, resp. DMI-BIOS structures base address; starting point */ +void *smbios_structures_base = 0; +/** enumeration of SM-BIOS, resp. DMI-BIOS types that do have subtypes */ +__u8 smbios_types_with_subtypes[] = { TYPES_WITH_SUBTYPES }; +/** contains the SMBIOS Version, e.g. V2.31 */ +char smbios_version_string[32]; +/** \fn unsigned char smbios_check_entry_point (void * addr) + * \brief checks the entry point structure for correct checksum + * \param addr pointer to the entry point structure + * \return the checksum of the entry point structure, should be '0' + * + * This function checks the entry point structure for correct checksum. + * The checksum is calculated with adding every byte of the structure + * to the checksum byte. The entry point structure is considered correct + * if the checksum byte is 0. + * + * \author Markus Lyra + * \author Thomas Bretthauer + * \date October 2000 + */ + +unsigned char smbios_check_entry_point (void *addr) +{ + unsigned char *i; + unsigned char checksum = 0; + unsigned char length =((struct smbios_entry_point_struct *) addr)->entry_point_length; + /* calculate checksum for entry point structure (should be 0) */ + for (i = (unsigned char *) addr; i < (unsigned char *) addr + length; i++) + checksum += *i; + return checksum; +} + +struct smbios_entry_point_struct * smbios_find_entry_point (void *base) +{ + struct smbios_entry_point_struct *entry_point = 0; /** SM-BIOS entry point */ + unsigned int *temp; /** temp. pointer */ + + + /* search for the magic dword - '_SM_� as DWORD formatted - on paragraph boundaries */ + for (temp = base; + !entry_point && temp < (unsigned int *) base + BIOS_MAP_LENGTH; + temp += 4) + { + /* found the identifier ? */ + if (*temp == SMBIOS_MAGIC_DWORD) + { + /* check if entry point valid (build checksum) */ + if (!(smbios_check_entry_point (temp))) + { + entry_point = (struct smbios_entry_point_struct *) temp; + + /* fix display of Bios version string */ + /* SMBios version is known as 2.1, 2.2, 2.3 and 2.3.1, never as 2.01 (JB) */ + SM_BIOS_DEBUG("SM-BIOS V%d.%d entry point found at 0x%x\n", + entry_point->major_version, entry_point->minor_version, (unsigned int) temp); + + SM_BIOS_DEBUG("V%d.%d\n", entry_point->major_version, entry_point->minor_version); + } + } + } + return entry_point; +} +struct dmibios_entry_point_struct *dmibios_find_entry_point (void *base) +{ + struct dmibios_entry_point_struct *entry_point = 0; /** DMI-BIOS entry point */ + unsigned char *temp = 0; /** temp. pointer */ + unsigned char biossignature[] = /** '_DMI20_NT_' */ + { 0x5f, 0x44, 0x4d, 0x49, 0x32, 0x30, 0x5f, 0x4e, 0x54, 0x5f }; + + /* search for the DMI-BIOS signature on character boundary (hm?) */ + for (temp = base; + !entry_point && + temp < (__u8 *) base + BIOS_MAP_LENGTH - sizeof (biossignature) - 32; + temp++) + { + unsigned long *tempdword = (unsigned long *) temp; + + /* found the identifier '_DMI' ? (beginning of signature) */ + if (*tempdword == DMIBIOS_MAGIC_DWORD) + { + entry_point = (struct dmibios_entry_point_struct *) temp; + + SM_BIOS_DEBUG ("DMI-BIOS revision %d entry point at 0x%x\n", + entry_point->revision, (unsigned int) temp); + + sprintf(smbios_version_string, "V%d\n", entry_point->revision); + + if (memcmp (temp, biossignature, sizeof (biossignature)) == 0) + SM_BIOS_DEBUG ("DMI BIOS successfully identified\n"); + } + } + return entry_point; +} +void dump_smbios_hex(unsigned char *p,int len) +{ + int i; + SM_BIOS_DEBUG("dump_smbios_hex length:%d\n",len); + for(i=0;i<len;i++) + { + if((p[i] == 0xc0)&&(p[i+1]==0x06)) + SM_BIOS_DEBUG("Found 0xc0 at offset:%d 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x \n\t",i,p[i],p[i+1],p[i+2],p[i+3],p[i+4],p[i+5]); + } +} +int smbios_type_has_subtype (unsigned char type) +{ + int i; + + + for (i = 0; i < sizeof (smbios_types_with_subtypes); i++) + if (type == smbios_types_with_subtypes[i]) + return 1; + + return 0; +} + +int smbios_get_struct_length (struct smbios_struct * struct_ptr) +{ + /* jump to string list */ + unsigned char *ptr = (unsigned char *) struct_ptr + struct_ptr->length; + + /* search for the end of string list */ + while (ptr[0] != 0x00 || ptr[1] != 0x00) + ptr++; + ptr += 2; /* terminating 0x0000 should be included */ + + return (int) ptr - (int) struct_ptr; +} + +unsigned int smbios_get_readable_name(char *name, struct smbios_struct *struct_ptr) +{ + switch(struct_ptr->type) + { + case 0: return sprintf (name, "%s", RD_BIOS); + case 1: return sprintf (name, "%s", RD_SYSTEM); + case 2: return sprintf (name, "%s", RD_BASEBOARD); + case 3: return sprintf (name, "%s", RD_ENCLOSURE); + case 4: return sprintf (name, "%s", RD_PROCESSOR); + case 5: return sprintf (name, "%s", RD_MEMCTRL); + case 6: return sprintf (name, "%s", RD_MEMMOD); + case 7: return sprintf (name, "%s", RD_CACHE); + case 8: return sprintf (name, "%s", RD_PORT); + case 9: return sprintf (name, "%s", RD_SLOT); + case 10: return sprintf (name, "%s", RD_ONBOARD); + case 11: return sprintf (name, "%s", RD_OEMSTRINGS); + case 12: return sprintf (name, "%s", RD_SYSTEMCONFIG); + case 13: return sprintf (name, "%s", RD_BIOSLANG); + case 14: return sprintf (name, "%s", RD_GROUPASSOC); + case 15: return sprintf (name, "%s", RD_EVENTLOG); + case 16: return sprintf (name, "%s", RD_MEMARRAY); + case 17: return sprintf (name, "%s", RD_MEMDEV); + case 18: return sprintf (name, "%s", RD_32MEMERR); + case 19: return sprintf (name, "%s", RD_MEMMAPPEDADR); + case 20: return sprintf (name, "%s", RD_MEMMAPPEDDEV); + case 21: return sprintf (name, "%s", RD_POINTINGDEV); + case 22: return sprintf (name, "%s", RD_BATTERY); + case 23: return sprintf (name, "%s", RD_RESET); + case 24: return sprintf (name, "%s", RD_SECURITY); + case 25: return sprintf (name, "%s", RD_PWRCTRL); + case 26: return sprintf (name, "%s", RD_VOLTAGE); + case 27: return sprintf (name, "%s", RD_COOLINGDEV); + case 28: return sprintf (name, "%s", RD_TEMP); + case 29: return sprintf (name, "%s", RD_CURRENT); + case 30: return sprintf (name, "%s", RD_RMTACCESS); + case 31: return sprintf (name, "%s", RD_BIS); + case 32: return sprintf (name, "%s", RD_BOOT_INFO); + case 33: return sprintf (name, "%s", RD_64MEMERR); + case 34: return sprintf (name, "%s", RD_MANAGDEV); + case 35: return sprintf (name, "%s", RD_MANAGDEVCOMP); + case 36: return sprintf (name, "%s", RD_MANAGDEVTHRESH); + case 37: return sprintf (name, "%s", RD_MEMCHANNEL); + case 38: return sprintf (name, "%s", RD_IPMI); + case 39: return sprintf (name, "%s", RD_PWRSUP); + case 126: return sprintf (name, "%s", RD_INACTIVE); + case 127: return sprintf (name, "%s", RD_EOT); + default: return sprintf (name, "%d", struct_ptr->type); + } +} +unsigned int smbios_get_readable_name_ext(char *name, struct smbios_struct *struct_ptr) +{ + return sprintf (name, "%d-%d", struct_ptr->type, struct_ptr->subtype); +} + +int smbios_make_dir_entries (void) +{ + int i; + unsigned int raw_name_length = 0; + char raw_name[12]; /* e.g. 0.0 for structure type 0 , first instance */ + unsigned int readable_name_length = 0; + char readable_name[64]; /* e.g. Bios.0 for structure type 0 , first instance */ + struct smbios_struct *struct_ptr = smbios_structures_base; + /* + * for every SMBIOS structure do ... + */ + for (i = 0; i < smbios_entry_point->no_of_structures; i++) + { + memset(raw_name,0,12); + memset(readable_name,0,64); + /* + * generate an unique name for the file: "type[-subtype].count" + */ + if (smbios_type_has_subtype (((struct smbios_struct *) struct_ptr)->type)) + { + /* name will contain the raw file name, it equals the structure type (e.g. 1 for Type 1). + * readable_name contains the interpreted file name (e.g. System for Type 1) + */ + raw_name_length = sprintf (raw_name, "%d-%d", struct_ptr->type, struct_ptr->subtype); + readable_name_length = smbios_get_readable_name_ext(readable_name, struct_ptr); + //printk(KERN_INFO "[%s] smbios_type_has_subtype[%d] length:%d\n",raw_name,struct_ptr->type,struct_ptr->length); + } + else + { + raw_name_length = sprintf (raw_name, "%d", struct_ptr->type); + readable_name_length = smbios_get_readable_name(readable_name, struct_ptr); + //printk(KERN_INFO "[%s] smbios_type_has type:%d length:%d\n",readable_name,struct_ptr->type,struct_ptr->length); + } + + /* + * go to the next structure + */ + struct_ptr =(struct smbios_struct *) ((unsigned char *) struct_ptr + smbios_get_struct_length(struct_ptr)); + } + + return 0; +} + +int smbios_check_if_have_exar_config(unsigned char *config0,unsigned char *config1) +{ + int i; + int result = -1; + unsigned char *p; + smbios_base = ioremap (BIOS_START_ADDRESS, BIOS_MAP_LENGTH); + if(!smbios_base) + { + SM_BIOS_DEBUG ("ioremap() for entry point failed\n"); + result = -ENXIO; + return result; + } + //printk(KERN_INFO "ioremap bios base at 0x%p\n", smbios_base); + if (!(smbios_entry_point = smbios_find_entry_point (smbios_base))) + { + SM_BIOS_DEBUG ("SM-BIOS entry point not found\n"); + iounmap (smbios_base); + result = -ENXIO; + return result; + + } + /* + * for SM-BIOS: + * check if Pointer to DMI structures exist. + * intermediate_string (_DMI_) is not '\0' terminated, + * so strncmp() with sizeof(DMI_STRING) - 1 is needed. + */ + if (smbios_entry_point) + { + if (strncmp((char *) &(smbios_entry_point->intermediate_string), + DMI_STRING, sizeof (DMI_STRING) - 1)) + { + SM_BIOS_DEBUG ("Pointer to DMI structures not found!\n"); + + } + } + + /* + * map the SM-BIOS structures physical address range. + * the 'real' smbios_structures_base contains the starting + * address, where the instances of dmi structures are located. + */ + if (smbios_entry_point) + { + if (!(smbios_structures_base = + ioremap (smbios_entry_point->struct_table_address, + (unsigned long) smbios_entry_point->struct_table_length))) + { + SM_BIOS_DEBUG("ioremap() for structures table failed\n"); + iounmap (smbios_base); + result = -ENXIO; + return result; + } + } + SM_BIOS_DEBUG(KERN_INFO "smbios_structures_base to 0x%p length %d no_of_structures:%d\n", + smbios_structures_base, + smbios_entry_point->struct_table_length, + smbios_entry_point->no_of_structures); + + //dump_smbios_hex((unsigned char *)smbios_structures_base,smbios_entry_point->struct_table_length); + p = (unsigned char *)smbios_structures_base; + for(i=0;i<smbios_entry_point->struct_table_length;i++) + { + if((p[i] == 0xc0)&&(p[i+1]==0x06)) + { + SM_BIOS_DEBUG("Found 0xc0 at offset:%d 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x \n\t",i,p[i],p[i+1],p[i+2],p[i+3],p[i+4],p[i+5]); + *config0 = p[i+4]; + *config1 = p[i+5]; + result = 0; + break; + } + } + //smbios_make_dir_entries(); + iounmap (smbios_structures_base); + iounmap (smbios_base); + return result; + +} +/* +void dmi_dump_backup(void) +{ + const char *board_vendor, *board_name,*board_serial; + const struct dmi_device *dmi; + struct dmi_dev_onboard *donboard; + board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); + board_name = dmi_get_system_info(DMI_BOARD_NAME); + board_serial = dmi_get_system_info(DMI_BOARD_SERIAL); + printk(KERN_INFO "DMI_BOARD_VENDOR:%s\n",board_vendor); + printk(KERN_INFO "DMI_BOARD_NAME:%s\n",board_name); + printk(KERN_INFO "DMI_BOARD_SERIAL:%s\n",board_serial); + for(i=0;i<256;i++) + { + dmi = NULL; + //printk(KERN_INFO "dmi_find_device<%d>\n",i); + while ((dmi = dmi_find_device(i,NULL, dmi)) != NULL) + { + //donboard = dmi->device_data; + printk(KERN_INFO "<%d>Found name:%s type:%d \n",i,dmi->name,dmi->type); + } + } + +} +*/ + diff --git a/ubuntu/xr-usb-serial/xr_get_smbios.h b/ubuntu/xr-usb-serial/xr_get_smbios.h new file mode 100644 index 000000000000..f56b33084dab --- /dev/null +++ b/ubuntu/xr-usb-serial/xr_get_smbios.h @@ -0,0 +1,237 @@ +/* Copyright (C) 2001-2001 Fujitsu Siemens Computers + Joachim Braeuer + This file is part of smbios + + smbios is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + smbios is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with smbios; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* $Id: bios.h,v 1.2 2002/09/03 10:33:12 bretthauert Exp $ + * + * $Log: bios.h,v $ + * Revision 1.2 2002/09/03 10:33:12 bretthauert + * fixed a bug with 2.4 kernels (changed kmalloc parameter from + * GFP_BUFFER to GFP_KERNEL + * + * Revision 1.1 2001/09/15 14:52:43 bretthauert + * initial release + * + */ + +/** \file bios.h + * declarations and prototypes of DMI-BIOS and SM-BIOS stuff + * + * \author Markus Lyra + * \author Thomas Bretthauer + * \author Joachim Braeuer + * \version 0.11 + * \date January 2001 + */ + +#ifndef __SM_BIOS_H__ +#define __SM_BIOS_H__ + +#include <linux/types.h> +//#define _EN_DEBUG_ 1 +#ifdef _EN_DEBUG_ +# define SM_BIOS_DEBUG(fmt, args...) printk( KERN_DEBUG "smbios: " fmt, ## args) +#else +# define SM_BIOS_DEBUG(fmt, args...) /* not debugging: nothing */ +#endif +/* + * Magic numbers + */ + +/** start address of BIOS segment to scanned for SM-BIOS and DMI-BIOS */ +#define BIOS_START_ADDRESS 0xF0000 +/** length of the scanned BIOS area for SM-BIOS and DMI-BIOS */ +#define BIOS_MAP_LENGTH 0x10000 +/** magic 4 bytes to identify SM-BIOS entry point, paragraph boundary */ +#define SMBIOS_MAGIC_DWORD 0x5F4D535F /* anchor string "_SM_" */ +/** magic 4 bytes to identify DMI-BIOS entry point, byte boundary */ +#define DMIBIOS_MAGIC_DWORD 0x494d445f /* anchor string "_DMI" */ +/** identifier for SM-BIOS structures within SM-BIOS entry point */ +#define DMI_STRING "_DMI_" +/** list of types which are known to have subtyes; expandable! */ +#define TYPES_WITH_SUBTYPES 185, 187, 208, 209, 210, 211, 212, 254 +/** maximum block size for proc read function */ +#define PROC_BLOCK_SIZE (3*1024) + + +/** mode raw/cooked */ +#define FILE_MODE_RAW 0 +#define FILE_MODE_COOKED 1 + +/* + * Structures + */ + +/** SM-BIOS entry point structure + * the SMBIOS Entry Point structure described below can be located by + * application software by searching for the anchor string on paragraph + * (16 byte) boundaries within the physical memory address range 000F0000h to + * 000FFFFFh. This entry point encapsulates an intermediate anchor string + * that is used by some existing DMI browsers. + * + * @note While the SMBIOS Major and Minor Versions (offsets 06h and 07h) + * currently duplicate the information present in the SMBIOS BCD Revision + * (offset 1Dh), they provide a path for future growth in this specification. + * The BCD Revision, for example, provides only a single digit for each of + * the major and minor version numbers. + */ +struct smbios_entry_point_struct +{ + /** "_SM_", specified as four ASCII characters (5F 53 4D 5F) */ + __u32 anchor_string; + /** checksum of the Entry Point Structure (EPS). This value, when added to + * all other bytes in the EPS, will result in the value 00h (using 8 bit + * addition calculations). Values in the EPS are summed starting at offset + * 00h, for Entry Point Length bytes.*/ + __u8 entry_point_checksum; + /** Length of the Entry Point Structure, starting with the Anchor String + * field, in bytes, currently 1Fh. */ + __u8 entry_point_length; + /** identifies the major version of this specification implemented in + * the table structures, e.g. the value will be 0Ah for revision 10.22 + * and 02h for revision 2.1 */ + __u8 major_version; + /** identifies the minor version of this specification implemented in + * the table structures, e.g. the value will be 16h for revision 10.22 + * and 01h for revision 2.1 */ + __u8 minor_version; + /** size of the largest SMBIOS structure, in bytes, and encompasses the + * structure's formatted area and text strings. This is the value returned + * as StructureSize from the Plug-n-Play 'Get SMBIOS Information' function */ + __u16 max_struct_size; + /** identifies the EPS revision implemented in this structure and identifies + * the formatting of offsets 0Bh to 0Fh, one of: + * 00h Entry Point based on SMBIOS 2.1 definition; formatted area is + * reserved and set to all 00h. + * 01h-FFh reserved for assignment via this specification */ + __u8 revision; + /** the value present in the Entry Point Revision field defines the + * interpretation to be placed upon these5 bytes. */ + __u8 formated_area[5]; + /** "_DMI_", specified as five ASCII characters (5F 44 4D 49 5F) */ + __u8 intermediate_string[5]; + /** checksum of the Intermediate Entry Point Structure (IEPS). This value, + * when added to all other bytes in the IEPS, will result in the value 00h + * (using 8 bit addition calculations). Values in the IEPS are summed + * starting at offset 10h, for 0Fh bytes */ + __u8 intermediate_checksum; + /** the 32 bit physical starting address of the read-only SMBIOS Structure + * Table, that can start at any 32 bit address. This area contains all of the + * SMBIOS structures fully packed together. These structures can then be + * parsed to produce exactly the same format as that returned from a 'Get + * SMBIOS Structure' function call. */ + __u16 struct_table_length; + __u32 struct_table_address; + __u16 no_of_structures; + __u8 bcd_revision; +}__attribute__ ((packed)); + +/** SM-BIOS and DMI-BIOS structure header */ +struct smbios_struct +{ + __u8 type ; + __u8 length ; + __u16 handle ; + __u8 subtype; + /* ... other fields are structure dependend ... */ +} __attribute__ ((packed)); + +/** DMI-BIOS structure header */ +struct dmibios_table_entry_struct +{ + __u16 size; + __u16 handle; + __u32 procedure; +}__attribute__ ((packed)); + +/** DMI-BIOS entry point structure */ +struct dmibios_entry_point_struct +{ + __u8 signature[10]; + __u8 revision; + struct dmibios_table_entry_struct entry[1]; +}__attribute__ ((packed)); + +/** readable names for smbios structures, they serve as filenames in the /proc file system */ +#define RD_BIOS "bios" +#define RD_SYSTEM "system" +#define RD_BASEBOARD "baseboard" +#define RD_ENCLOSURE "enclosure" +#define RD_PROCESSOR "processor" +#define RD_MEMCTRL "memory_controller" +#define RD_MEMMOD "memory_module" +#define RD_CACHE "cache" +#define RD_PORT "port_connector" +#define RD_SLOT "system_slot" +#define RD_ONBOARD "onboard_device" +#define RD_OEMSTRINGS "oem_strings" +#define RD_SYSTEMCONFIG "system_configuration" +#define RD_BIOSLANG "bios_language" +#define RD_GROUPASSOC "group_association" +#define RD_EVENTLOG "system_event_log" +#define RD_MEMARRAY "physical_memory_array" +#define RD_MEMDEV "physical_memory_device" +#define RD_32MEMERR "32bit_memory_error_information" +#define RD_MEMMAPPEDADR "memory_array_mapped_address" +#define RD_MEMMAPPEDDEV "memory_device_mapped_address" +#define RD_POINTINGDEV "pointing_device" +#define RD_BATTERY "portable_battery" +#define RD_RESET "system_reset" +#define RD_SECURITY "hardware_security" +#define RD_PWRCTRL "system_power_controls" +#define RD_VOLTAGE "voltage_probe" +#define RD_COOLINGDEV "cooling_device" +#define RD_TEMP "temperature_probe" +#define RD_CURRENT "current_probe" +#define RD_RMTACCESS "out_of_band_remote_access" +#define RD_BIS "boot_integrity_services" +#define RD_BOOT_INFO "system_boot_information" +#define RD_64MEMERR "64bit_memory_error_information" +#define RD_MANAGDEV "management_device" +#define RD_MANAGDEVCOMP "management_device_component" +#define RD_MANAGDEVTHRESH "management_device_thresholds" +#define RD_MEMCHANNEL "memory_channel" +#define RD_IPMI "ipmi_information" +#define RD_PWRSUP "system_power_supply" +#define RD_INACTIVE "inactive" +#define RD_EOT "end_of_table" + + +//extern smbios_entry_point_struct * smbios_entry_point; /* start of SMBIOS within the F-Segment */ +//extern dmibios_entry_point_struct * dmibios_entry_point; /* start of DMIBIOS within the F-Segment */ +extern void * smbios_structures_base; /* base of SMBIOS raw structures */ +extern unsigned char smbios_types_with_subtypes[]; +extern char smbios_version_string[32]; /* e.g. V2.31 */ +/* + * Functions + */ + +/* for the description see the implementation file */ +struct smbios_entry_point_struct * smbios_find_entry_point(void * base); +struct dmibios_entry_point_struct * dmibios_find_entry_point(void * base); +unsigned char smbios_check_entry_point(void * addr); +int smbios_type_has_subtype(unsigned char type); +int smbios_get_struct_length(struct smbios_struct * struct_ptr); +int dmibios_get_struct_length(struct smbios_struct * struct_ptr); +unsigned int smbios_get_readable_name_ext(char *readable_name, struct smbios_struct *struct_ptr); +unsigned int smbios_get_readable_name(char *readable_name, struct smbios_struct *struct_ptr); +int smbios_check_if_have_exar_config(unsigned char *config0,unsigned char *config1); + + +#endif /* __BIOS_H__ */ diff --git a/ubuntu/xr-usb-serial/xr_usb_serial_common.c b/ubuntu/xr-usb-serial/xr_usb_serial_common.c index d16f072613b1..5d049855fb1a 100644 --- a/ubuntu/xr-usb-serial/xr_usb_serial_common.c +++ b/ubuntu/xr-usb-serial/xr_usb_serial_common.c @@ -28,12 +28,12 @@ * from www.exar.com that will work with kernel versions 2.6.18 to 3.4.x. * * ChangeLog: - * Version 1A - Initial released version. + * Version 1B - Initial released version. */ -//#undef DEBUG +#undef DEBUG #undef VERBOSE_DEBUG - +#include <linux/gpio.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/init.h> @@ -47,15 +47,20 @@ #include <linux/uaccess.h> #include <linux/usb.h> #include <linux/usb/cdc.h> +#include <linux/dmi.h> #include <asm/byteorder.h> #include <asm/unaligned.h> #include <linux/list.h> +#include <linux/delay.h> +#include <asm/io.h> /* ioremap() */ #include "linux/version.h" +#include "xr_get_smbios.h" #include "xr_usb_serial_common.h" #include "xr_usb_serial_ioctl.h" + #define DRIVER_AUTHOR "<uarttechsupport@exar.com>" #define DRIVER_DESC "Exar USB UART (serial port) driver" @@ -65,6 +70,10 @@ static struct xr_usb_serial *xr_usb_serial_table[XR_USB_SERIAL_TTY_MINORS]; static DEFINE_MUTEX(xr_usb_serial_table_lock); + + + + /* * xr_usb_serial_table accessors */ @@ -137,6 +146,7 @@ static int xr_usb_serial_ctrl_msg(struct xr_usb_serial *xr_usb_serial, int reque return retval < 0 ? retval : 0; } +#include "xr_get_smbios.c" #include "xr_usb_serial_hal.c" @@ -249,46 +259,6 @@ static ssize_t show_country_rel_date } static DEVICE_ATTR(iCountryCodeRelDate, S_IRUGO, show_country_rel_date, NULL); - -static ssize_t set_rs485_422_en(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - struct usb_interface *intf = to_usb_interface(dev); - struct xr_usb_serial *xr_usb_serial = usb_get_intfdata(intf); - int error, value = 0; - - error = kstrtoint(buf, 0, &value); - if (error) - return error; - - if (value == 0) { - xr_usb_serial->rs485_422_en = false; - } else if (value == 1) { - // RS485,RS422 HD/FD mode - xr_usb_serial->rs485_422_en = true; - } - - return count; -} - -static ssize_t show_rs485_422_en(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct usb_interface *intf = to_usb_interface(dev); - struct xr_usb_serial *xr_usb_serial = usb_get_intfdata(intf); - - if (xr_usb_serial->rs485_422_en == false) { - return sprintf(buf, "0"); - } else if (xr_usb_serial->rs485_422_en == true) { - // RS485,RS422 HD/FD mode - return sprintf(buf, "1"); - } - return 0; -} - -static DEVICE_ATTR(bRS485_422_en, 0644, show_rs485_422_en, set_rs485_422_en); - /* * Interrupt handlers for various XR_USB_SERIAL device responses */ @@ -298,7 +268,10 @@ static void xr_usb_serial_ctrl_irq(struct urb *urb) { struct xr_usb_serial *xr_usb_serial = urb->context; struct usb_cdc_notification *dr = urb->transfer_buffer; - struct tty_struct *tty; +#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 9, 0) +#else + struct tty_struct *tty; +#endif unsigned char *data; int newctrl; int retval; @@ -309,10 +282,11 @@ static void xr_usb_serial_ctrl_irq(struct urb *urb) switch (status) { case 0: p = (unsigned char *)(urb->transfer_buffer); + /* for(i=0;i<urb->actual_length;i++) { dev_dbg(&xr_usb_serial->control->dev,"0x%02x\n",p[i]); - } + }*/ /* success */ break; case -ECONNRESET: @@ -362,7 +336,7 @@ static void xr_usb_serial_ctrl_irq(struct urb *urb) } #endif xr_usb_serial->ctrlin = newctrl; - + #if 0 dev_dbg(&xr_usb_serial->control->dev, "%s - input control lines: dcd%c dsr%c break%c " "ring%c framing%c parity%c overrun%c\n", @@ -374,6 +348,7 @@ static void xr_usb_serial_ctrl_irq(struct urb *urb) xr_usb_serial->ctrlin & XR_USB_SERIAL_CTRL_FRAMING ? '+' : '-', xr_usb_serial->ctrlin & XR_USB_SERIAL_CTRL_PARITY ? '+' : '-', xr_usb_serial->ctrlin & XR_USB_SERIAL_CTRL_OVERRUN ? '+' : '-'); + #endif break; default: @@ -399,7 +374,7 @@ static int xr_usb_serial_submit_read_urb(struct xr_usb_serial *xr_usb_serial, in if (!test_and_clear_bit(index, &xr_usb_serial->read_urbs_free)) return 0; - dev_vdbg(&xr_usb_serial->data->dev, "%s - urb %d\n", __func__, index); + //dev_vdbg(&xr_usb_serial->data->dev, "%s - urb %d\n", __func__, index); res = usb_submit_urb(xr_usb_serial->read_urbs[index], mem_flags); if (res) { @@ -430,10 +405,75 @@ static int xr_usb_serial_submit_read_urbs(struct xr_usb_serial *xr_usb_serial, g } static void xr_usb_serial_process_read_urb(struct xr_usb_serial *xr_usb_serial, struct urb *urb) { - struct tty_struct *tty; +#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 9, 0) +#else + struct tty_struct *tty; +#endif + int preciseflags = xr_usb_serial->preciseflags; + int have_extra_byte; + int length; + if (!urb->actual_length) return; -#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 9, 0) + + if (preciseflags) + { + char *dp = urb->transfer_buffer; + int i, ch, ch_flags; + + length = urb->actual_length; + length = length + (xr_usb_serial->have_extra_byte ? 1 : 0); + have_extra_byte = (preciseflags && (length & 1)); + length = (preciseflags) ? (length / 2) : length; + for (i = 0; i < length; ++i) + { + char tty_flag; + if (i == 0) + { + if (xr_usb_serial->have_extra_byte) + { + ch = xr_usb_serial->extra_byte; + } + else + { + ch = *dp++; + } + } + else + { + ch = *dp++; + } + ch_flags = *dp++; + if (ch_flags & RAMCTL_BUFFER_PARITY) + tty_flag = TTY_PARITY; + else if (ch_flags & RAMCTL_BUFFER_BREAK) + tty_flag = TTY_BREAK; + else if (ch_flags & RAMCTL_BUFFER_FRAME) + tty_flag = TTY_FRAME; + else if (ch_flags & RAMCTL_BUFFER_OVERRUN) + tty_flag = TTY_OVERRUN; + else + tty_flag = TTY_NORMAL; + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) + tty_insert_flip_char(&xr_usb_serial->port, ch, tty_flag); + tty_flip_buffer_push(&xr_usb_serial->port); +#else + tty = tty_port_tty_get(&xr_usb_serial->port); + if (!tty) + return; + tty_insert_flip_char(&xr_usb_serial->port, ch, tty_flag); + tty_flip_buffer_push(tty); + + tty_kref_put(tty); +#endif + + } + } + else + { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) tty_insert_flip_string(&xr_usb_serial->port, urb->transfer_buffer, urb->actual_length); tty_flip_buffer_push(&xr_usb_serial->port); @@ -446,6 +486,7 @@ static void xr_usb_serial_process_read_urb(struct xr_usb_serial *xr_usb_serial, tty_kref_put(tty); #endif + } } static void xr_usb_serial_read_bulk_callback(struct urb *urb) @@ -453,9 +494,10 @@ static void xr_usb_serial_read_bulk_callback(struct urb *urb) struct xr_usb_serial_rb *rb = urb->context; struct xr_usb_serial *xr_usb_serial = rb->instance; unsigned long flags; - + /* dev_vdbg(&xr_usb_serial->data->dev, "%s - urb %d, len %d\n", __func__, - rb->index, urb->actual_length); + rb->index, urb->actual_length);*/ + set_bit(rb->index, &xr_usb_serial->read_urbs_free); if (!xr_usb_serial->dev) { @@ -467,7 +509,7 @@ static void xr_usb_serial_read_bulk_callback(struct urb *urb) if (urb->status) { dev_dbg(&xr_usb_serial->data->dev, "%s - non-zero urb status: %d\n", __func__, urb->status); - return; + //return; } xr_usb_serial_process_read_urb(xr_usb_serial, urb); @@ -505,9 +547,13 @@ static void xr_usb_serial_write_bulk(struct urb *urb) static void xr_usb_serial_softint(struct work_struct *work) { struct xr_usb_serial *xr_usb_serial = container_of(work, struct xr_usb_serial, work); - struct tty_struct *tty; +#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 9, 0) +#else + struct tty_struct *tty; +#endif + - dev_vdbg(&xr_usb_serial->data->dev, "%s\n", __func__); + //dev_vdbg(&xr_usb_serial->data->dev, "%s\n", __func__); #if LINUX_VERSION_CODE > KERNEL_VERSION(3, 9, 0) tty_port_tty_wakeup(&xr_usb_serial->port); #else @@ -528,7 +574,7 @@ static int xr_usb_serial_tty_install(struct tty_driver *driver, struct tty_struc struct xr_usb_serial *xr_usb_serial; int retval; - dev_dbg(tty->dev, "%s\n", __func__); + //dev_dbg(tty->dev, "%s\n", __func__); xr_usb_serial = xr_usb_serial_get_by_index(tty->index); if (!xr_usb_serial) @@ -550,9 +596,10 @@ static int xr_usb_serial_tty_install(struct tty_driver *driver, struct tty_struc static int xr_usb_serial_tty_open(struct tty_struct *tty, struct file *filp) { struct xr_usb_serial *xr_usb_serial = tty->driver_data; - - dev_dbg(tty->dev, "%s\n", __func__); - + int result; + result = xr_usb_serial_fifo_reset(xr_usb_serial); + //dev_dbg(tty->dev, "%s\n", __func__); + return tty_port_open(&xr_usb_serial->port, tty, filp); } @@ -561,7 +608,7 @@ static int xr_usb_serial_port_activate(struct tty_port *port, struct tty_struct struct xr_usb_serial *xr_usb_serial = container_of(port, struct xr_usb_serial, port); int retval = -ENODEV; - dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); + //dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); mutex_lock(&xr_usb_serial->mutex); if (xr_usb_serial->disconnected) @@ -624,14 +671,18 @@ static void xr_usb_serial_port_destruct(struct tty_port *port) { struct xr_usb_serial *xr_usb_serial = container_of(port, struct xr_usb_serial, port); - dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); + //dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0) tty_unregister_device(xr_usb_serial_tty_driver, xr_usb_serial->minor); #endif +#ifdef CONFIG_GPIOLIB + gpiochip_remove(&xr_usb_serial->xr_usb_gpio); +#endif xr_usb_serial_release_minor(xr_usb_serial); usb_put_intf(xr_usb_serial->control); kfree(xr_usb_serial->country_codes); kfree(xr_usb_serial); + } static void xr_usb_serial_port_shutdown(struct tty_port *port) @@ -639,7 +690,7 @@ static void xr_usb_serial_port_shutdown(struct tty_port *port) struct xr_usb_serial *xr_usb_serial = container_of(port, struct xr_usb_serial, port); int i; - dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); + //dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); mutex_lock(&xr_usb_serial->mutex); if (!xr_usb_serial->disconnected) { @@ -659,21 +710,21 @@ static void xr_usb_serial_port_shutdown(struct tty_port *port) static void xr_usb_serial_tty_cleanup(struct tty_struct *tty) { struct xr_usb_serial *xr_usb_serial = tty->driver_data; - dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); + //dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); tty_port_put(&xr_usb_serial->port); } static void xr_usb_serial_tty_hangup(struct tty_struct *tty) { struct xr_usb_serial *xr_usb_serial = tty->driver_data; - dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); + //dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); tty_port_hangup(&xr_usb_serial->port); } static void xr_usb_serial_tty_close(struct tty_struct *tty, struct file *filp) { struct xr_usb_serial *xr_usb_serial = tty->driver_data; - dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); + //dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); tty_port_close(&xr_usb_serial->port, tty, filp); } @@ -689,7 +740,7 @@ static int xr_usb_serial_tty_write(struct tty_struct *tty, if (!count) return 0; - dev_vdbg(&xr_usb_serial->data->dev, "%s - count %d\n", __func__, count); + //dev_vdbg(&xr_usb_serial->data->dev, "%s - count %d\n", __func__, count); spin_lock_irqsave(&xr_usb_serial->write_lock, flags); wbn = xr_usb_serial_wb_alloc(xr_usb_serial); @@ -706,7 +757,7 @@ static int xr_usb_serial_tty_write(struct tty_struct *tty, } count = (count > xr_usb_serial->writesize) ? xr_usb_serial->writesize : count; - dev_vdbg(&xr_usb_serial->data->dev, "%s - write %d\n", __func__, count); + //dev_vdbg(&xr_usb_serial->data->dev, "%s - write %d\n", __func__, count); memcpy(wb->buf, buf, count); wb->len = count; @@ -785,7 +836,7 @@ static int xr_usb_serial_tty_break_ctl(struct tty_struct *tty, int state) retval = xr_usb_serial_send_break(xr_usb_serial, state ? 0xffff : 0); if (retval < 0) - dev_dbg(&xr_usb_serial->control->dev, "%s - send break failed\n", + dev_err(&xr_usb_serial->control->dev, "%s - send break failed\n", __func__); return retval; } @@ -793,7 +844,7 @@ static int xr_usb_serial_tty_break_ctl(struct tty_struct *tty, int state) static int xr_usb_serial_tty_tiocmget(struct tty_struct *tty) { struct xr_usb_serial *xr_usb_serial = tty->driver_data; - dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_tty_tiocmget\n"); + //dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_tty_tiocmget\n"); return xr_usb_serial_tiocmget(xr_usb_serial); } @@ -802,7 +853,7 @@ static int xr_usb_serial_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct xr_usb_serial *xr_usb_serial = tty->driver_data; - dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_tty_tiocmset set=0x%x clear=0x%x\n",set,clear); + //dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_tty_tiocmset set=0x%x clear=0x%x\n",set,clear); return xr_usb_serial_tiocmset(xr_usb_serial,set,clear); } @@ -865,8 +916,9 @@ static int xr_usb_serial_tty_ioctl(struct tty_struct *tty, { struct xr_usb_serial *xr_usb_serial = tty->driver_data; int rv = -ENOIOCTLCMD; - unsigned int channel, reg, val; - + unsigned int channel, reg, val,preciseflags; + int baud_rate = 0; + struct usb_cdc_line_coding newline; short *data; switch (cmd) { case TIOCGSERIAL: /* gets serial port data */ @@ -895,7 +947,8 @@ static int xr_usb_serial_tty_ioctl(struct tty_struct *tty, { rv = xr_usb_serial_get_reg_ext(xr_usb_serial,channel,reg, data); } - if (rv != 1) { + if (rv < 0) + { dev_err(&xr_usb_serial->control->dev, "Cannot get register (%d)\n", rv); kfree(data); return -EFAULT; @@ -941,6 +994,93 @@ static int xr_usb_serial_tty_ioctl(struct tty_struct *tty, return -EFAULT; rv = 0; break; + case XR_USB_SERIAL_SET_GPIO_MODE_REG: + xr_usb_serial_disable(xr_usb_serial); + if (get_user(channel, (int __user *)arg)) + return -EFAULT; + if (get_user(val, (int __user *)(arg + sizeof(int)))) + return -EFAULT; + if (channel == -1) + { + //block = portdata->block; + rv = xr_usb_serial_set_reg(xr_usb_serial,xr_usb_serial->reg_map.uart_gpio_mode_addr, val); + } + else + { + rv = xr_usb_serial_set_reg_ext(xr_usb_serial,channel,xr_usb_serial->reg_map.uart_gpio_mode_addr, val); + } + + dev_dbg(&xr_usb_serial->control->dev, "XR_USB_SERIAL_SET_GPIO_MODE_REG 0x%x val:0x%x \n", xr_usb_serial->reg_map.uart_gpio_mode_addr,val); + xr_usb_serial_enable(xr_usb_serial); + if (rv < 0) + return -EFAULT; + break; + case XR_USB_SERIAL_GET_GPIO_MODE_REG: + xr_usb_serial_disable(xr_usb_serial); + if (get_user(channel, (int __user *)arg)) + return -EFAULT; + + data = kmalloc(2, GFP_KERNEL); + if (data == NULL) { + dev_err(&xr_usb_serial->control->dev, "%s - Cannot allocate USB buffer.\n", __func__); + return -ENOMEM; + } + + if (channel == -1) + { + rv = xr_usb_serial_get_reg(xr_usb_serial,xr_usb_serial->reg_map.uart_gpio_mode_addr, data); + } + else + { + rv = xr_usb_serial_get_reg_ext(xr_usb_serial,channel,xr_usb_serial->reg_map.uart_gpio_mode_addr,data); + } + + xr_usb_serial_enable(xr_usb_serial); + + dev_dbg(&xr_usb_serial->control->dev, "XR_USB_SERIAL_GET_GPIO_MODE_REG 0x%x val:0x%x \n", xr_usb_serial->reg_map.uart_gpio_mode_addr,*data); + + if (rv < 0 ) { + dev_err(&xr_usb_serial->control->dev, "Cannot get register (%d) channel=%d \n", rv,channel); + kfree(data); + return -EFAULT; + } + + if (put_user(data[0], (int __user *)(arg + sizeof(int)))) { + dev_err(&xr_usb_serial->control->dev, "Cannot put user result\n"); + kfree(data); + return -EFAULT; + } + + kfree(data); + break; + case XRIOC_SET_ANY_BAUD_RATE: + + if (get_user(baud_rate, (int __user *)arg)) { + dev_dbg(&xr_usb_serial->control->dev, "get_user errot \n"); + return -EFAULT; + } + xr_usb_serial->line.dwDTERate = baud_rate; + memcpy(&newline,&(xr_usb_serial->line),sizeof(struct usb_cdc_line_coding)); + xr_usb_serial_disable(xr_usb_serial); + rv = xr_usb_serial_set_line(xr_usb_serial,&newline); + xr_usb_serial_enable(xr_usb_serial); + dev_dbg(&xr_usb_serial->control->dev, "XRIOC_SET_ANY_BAUD_RATE set baud_rate:%d ret=%d\n", baud_rate,rv); + break; + case XRIOC_SET_PRECISE_FLAGS: + preciseflags = arg; + dev_dbg(&xr_usb_serial->control->dev, "%s VIOC_SET_PRECISE_FLAGS %d\n", __func__, preciseflags); + xr_usb_serial_disable(xr_usb_serial); + if (preciseflags) + { + xr_usb_serial->preciseflags = 1; + } + else + { + xr_usb_serial->preciseflags = 0; + } + xr_usb_serial_set_wide_mode(xr_usb_serial,xr_usb_serial->preciseflags); + xr_usb_serial_enable(xr_usb_serial); + break; } @@ -965,9 +1105,11 @@ static void xr_usb_serial_tty_set_termios(struct tty_struct *tty, newline.bParityType = termios->c_cflag & PARENB ? (termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & CMSPAR ? 2 : 0) : 0; + xr_usb_serial->trans9 = 0; switch (termios->c_cflag & CSIZE) { case CS5:/*using CS5 replace of the 9 bit data mode*/ newline.bDataBits = 9; + xr_usb_serial->trans9 =1; break; case CS6: newline.bDataBits = 6; @@ -993,15 +1135,27 @@ static void xr_usb_serial_tty_set_termios(struct tty_struct *tty, xr_usb_serial_set_control(xr_usb_serial, xr_usb_serial->ctrlout = newctrl); xr_usb_serial_set_flow_mode(xr_usb_serial,tty,cflag);/*set the serial flow mode*/ - + if (xr_usb_serial->trans9) + { + /* Turn on wide mode if we're 9-bit transparent. */ + xr_usb_serial_set_wide_mode(xr_usb_serial,1); + } + else if (!xr_usb_serial->preciseflags) + { + xr_usb_serial_set_wide_mode(xr_usb_serial,0); + } + + if (memcmp(&xr_usb_serial->line, &newline, sizeof newline)) { memcpy(&xr_usb_serial->line, &newline, sizeof newline); + /* dev_dbg(&xr_usb_serial->control->dev, "%s - set line: %d %d %d %d\n", __func__, le32_to_cpu(newline.dwDTERate), newline.bCharFormat, newline.bParityType, - newline.bDataBits); + newline.bDataBits);*/ + xr_usb_serial_set_line(xr_usb_serial, &xr_usb_serial->line); } xr_usb_serial_enable(xr_usb_serial); @@ -1060,6 +1214,36 @@ static int xr_usb_serial_write_buffers_alloc(struct xr_usb_serial *xr_usb_serial return 0; } +#ifdef CONFIG_GPIOLIB +static int xr_usb_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct xr_usb_serial *xr_usb_serial = container_of(chip, struct xr_usb_serial, xr_usb_gpio); + dev_dbg(chip->dev, "xr_usb_gpio_get offset = %d channel = %d\n",offset,xr_usb_serial->channel); + return 0; +} + +static void xr_usb_gpio_set(struct gpio_chip *chip, unsigned offset, int val) +{ + struct xr_usb_serial *xr_usb_serial = container_of(chip, struct xr_usb_serial, xr_usb_gpio); + dev_dbg(chip->dev, "xr_usb_gpio_set offset =%d val=%d channel = %d\n",offset,val,xr_usb_serial->channel); +} + +static int xr_usb_gpio_direction_input(struct gpio_chip *chip,unsigned offset) +{ + struct xr_usb_serial *xr_usb_serial = container_of(chip, struct xr_usb_serial, xr_usb_gpio); + dev_dbg(chip->dev, "xr_usb_gpio_direction_input offset =%d channel = %d\n",offset,xr_usb_serial->channel); + return 0; +} + +static int xr_usb_gpio_direction_output(struct gpio_chip *chip, + unsigned offset, int val) +{ + struct xr_usb_serial *xr_usb_serial = container_of(chip, struct xr_usb_serial, xr_usb_gpio); + dev_dbg(chip->dev, "xr_usb_gpio_direction_output offset =%d val=%d channel:%d\n",offset,val,xr_usb_serial->channel); + return 0; +} +#endif + static int xr_usb_serial_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -1096,7 +1280,7 @@ static int xr_usb_serial_probe(struct usb_interface *intf, num_rx_buf = (quirks == SINGLE_RX_URB) ? 1 : XR_USB_SERIAL_NR; - dev_dbg(&intf->dev, "USB_device_id idVendor:%04x, idProduct %04x\n",id->idVendor,id->idProduct); + //dev_dbg(&intf->dev, "USB_device_id idVendor:%04x, idProduct %04x\n",id->idVendor,id->idProduct); /* handle quirks deadly to normal probing*/ if (quirks == NO_UNION_NORMAL) { @@ -1337,7 +1521,7 @@ static int xr_usb_serial_probe(struct usb_interface *intf, } #else xr_usb_serial->channel = epwrite->bEndpointAddress; - dev_dbg(&intf->dev, "epwrite->bEndpointAddress =%d\n",epwrite->bEndpointAddress); + //dev_dbg(&intf->dev, "epwrite->bEndpointAddress =%d\n",epwrite->bEndpointAddress); #endif buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &xr_usb_serial->ctrl_dma); if (!buf) { @@ -1424,14 +1608,9 @@ static int xr_usb_serial_probe(struct usb_interface *intf, usb_set_intfdata(intf, xr_usb_serial); - xr_usb_serial->rs485_422_en = false; //default enable rs232 - i = device_create_file(&intf->dev, &dev_attr_bRS485_422_en); - if (i < 0) - goto alloc_fail7; - i = device_create_file(&intf->dev, &dev_attr_bmCapabilities); if (i < 0) - goto alloc_fail8; + goto alloc_fail7; if (cfd) { /* export the country data */ xr_usb_serial->country_codes = kmalloc(cfd->bLength - 4, GFP_KERNEL); @@ -1470,7 +1649,7 @@ static int xr_usb_serial_probe(struct usb_interface *intf, xr_usb_serial->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; xr_usb_serial->ctrlurb->transfer_dma = xr_usb_serial->ctrl_dma; - dev_info(&intf->dev, "ttyXR_USB_SERIAL%d: USB XR_USB_SERIAL device\n", minor); + //dev_info(&intf->dev, "ttyXR_USB_SERIAL%d: USB XR_USB_SERIAL device channel:%d\n", minor,xr_usb_serial->channel); xr_usb_serial_pre_setup(xr_usb_serial); @@ -1491,12 +1670,26 @@ static int xr_usb_serial_probe(struct usb_interface *intf, &control_interface->dev); if (IS_ERR(tty_dev)) { rv = PTR_ERR(tty_dev); - goto alloc_fail9; + goto alloc_fail8; } #endif - +#ifdef CONFIG_GPIOLIB + /* Setup GPIO cotroller */ + xr_usb_serial->xr_usb_gpio.owner = THIS_MODULE; + xr_usb_serial->xr_usb_gpio.dev = &control_interface->dev; + xr_usb_serial->xr_usb_gpio.label = dev_name(&control_interface->dev); + xr_usb_serial->xr_usb_gpio.direction_input = xr_usb_gpio_direction_input; + xr_usb_serial->xr_usb_gpio.get = xr_usb_gpio_get; + xr_usb_serial->xr_usb_gpio.direction_output = xr_usb_gpio_direction_output; + xr_usb_serial->xr_usb_gpio.set = xr_usb_gpio_set; + xr_usb_serial->xr_usb_gpio.base = 100 + xr_usb_serial->channel*10; + xr_usb_serial->xr_usb_gpio.ngpio = 4; + xr_usb_serial->xr_usb_gpio.can_sleep = 1; + rv = gpiochip_add(&xr_usb_serial->xr_usb_gpio); + dev_dbg(&xr_usb_serial->control->dev, "gpiochip_add %d\n",rv); +#endif return 0; -alloc_fail9: +alloc_fail8: if (xr_usb_serial->country_codes) { device_remove_file(&xr_usb_serial->control->dev, &dev_attr_wCountryCodes); @@ -1504,8 +1697,6 @@ static int xr_usb_serial_probe(struct usb_interface *intf, &dev_attr_iCountryCodeRelDate); } device_remove_file(&xr_usb_serial->control->dev, &dev_attr_bmCapabilities); -alloc_fail8: - device_remove_file(&xr_usb_serial->control->dev, &dev_attr_bRS485_422_en); alloc_fail7: usb_set_intfdata(intf, NULL); for (i = 0; i < XR_USB_SERIAL_NW; i++) @@ -1530,7 +1721,7 @@ static void stop_data_traffic(struct xr_usb_serial *xr_usb_serial) { int i; - dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); + //dev_dbg(&xr_usb_serial->control->dev, "%s\n", __func__); usb_kill_urb(xr_usb_serial->ctrlurb); for (i = 0; i < XR_USB_SERIAL_NW; i++) @@ -1548,7 +1739,7 @@ static void xr_usb_serial_disconnect(struct usb_interface *intf) struct tty_struct *tty; int i; - dev_dbg(&intf->dev, "%s\n", __func__); + //dev_dbg(&intf->dev, "%s\n", __func__); /* sibling interface is already cleaning up */ if (!xr_usb_serial) @@ -1563,7 +1754,6 @@ static void xr_usb_serial_disconnect(struct usb_interface *intf) &dev_attr_iCountryCodeRelDate); } device_remove_file(&xr_usb_serial->control->dev, &dev_attr_bmCapabilities); - device_remove_file(&xr_usb_serial->control->dev, &dev_attr_bRS485_422_en); usb_set_intfdata(xr_usb_serial->control, NULL); usb_set_intfdata(xr_usb_serial->data, NULL); mutex_unlock(&xr_usb_serial->mutex); @@ -1631,7 +1821,9 @@ static int xr_usb_serial_resume(struct usb_interface *intf) struct xr_usb_serial_wb *wb; int rv = 0; int cnt; - + + xr_usb_serial_pre_setup(xr_usb_serial); + spin_lock_irq(&xr_usb_serial->read_lock); xr_usb_serial->susp_count -= 1; cnt = xr_usb_serial->susp_count; @@ -1670,7 +1862,10 @@ static int xr_usb_serial_resume(struct usb_interface *intf) static int xr_usb_serial_reset_resume(struct usb_interface *intf) { struct xr_usb_serial *xr_usb_serial = usb_get_intfdata(intf); - struct tty_struct *tty; +#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 9, 0) +#else + struct tty_struct *tty; +#endif if (test_bit(ASYNCB_INITIALIZED, &xr_usb_serial->port.flags)){ #if LINUX_VERSION_CODE > KERNEL_VERSION(3, 9, 0) tty_port_tty_hangup(&xr_usb_serial->port, false); @@ -1745,14 +1940,11 @@ static const struct tty_operations xr_usb_serial_ops = { .tiocmget = xr_usb_serial_tty_tiocmget, .tiocmset = xr_usb_serial_tty_tiocmset, }; - -/* - * Init / exit. - */ - static int __init xr_usb_serial_init(void) { int retval; + int i; + xr_usb_serial_tty_driver = alloc_tty_driver(XR_USB_SERIAL_TTY_MINORS); if (!xr_usb_serial_tty_driver) return -ENOMEM; @@ -1780,17 +1972,17 @@ static int __init xr_usb_serial_init(void) put_tty_driver(xr_usb_serial_tty_driver); return retval; } - + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); return 0; } - static void __exit xr_usb_serial_exit(void) { usb_deregister(&xr_usb_serial_driver); tty_unregister_driver(xr_usb_serial_tty_driver); put_tty_driver(xr_usb_serial_tty_driver); + } module_init(xr_usb_serial_init); diff --git a/ubuntu/xr-usb-serial/xr_usb_serial_common.h b/ubuntu/xr-usb-serial/xr_usb_serial_common.h index fe3460c57adf..97e902425794 100644 --- a/ubuntu/xr-usb-serial/xr_usb_serial_common.h +++ b/ubuntu/xr-usb-serial/xr_usb_serial_common.h @@ -70,6 +70,11 @@ #define XR_USB_SERIAL_NW 16 #define XR_USB_SERIAL_NR 16 +#define RAMCTL_BUFFER_PARITY 0x1 +#define RAMCTL_BUFFER_BREAK 0x2 +#define RAMCTL_BUFFER_FRAME 0x4 +#define RAMCTL_BUFFER_OVERRUN 0x8 + struct xr_usb_serial_wb { unsigned char *buf; dma_addr_t dmah; @@ -144,10 +149,19 @@ struct xr_usb_serial { u8 bInterval; struct xr_usb_serial_wb *delayed_wb; /* write queued for a device about to be woken */ unsigned int channel; + int preciseflags; /* USB: wide mode, TTY: flags per character */ + int trans9; /* USB: wide mode, serial 9N1 */ + int have_extra_byte; + int extra_byte; + unsigned short DeviceVendor; unsigned short DeviceProduct; +#ifdef CONFIG_GPIOLIB + struct gpio_chip xr_usb_gpio; +#endif struct reg_addr_map reg_map; - bool rs485_422_en; + int found_smbios_exar_config; + unsigned char channel_config; }; #define CDC_DATA_INTERFACE_TYPE 0x0a diff --git a/ubuntu/xr-usb-serial/xr_usb_serial_hal.c b/ubuntu/xr-usb-serial/xr_usb_serial_hal.c index f44970995368..bf9d2bf136ac 100644 --- a/ubuntu/xr-usb-serial/xr_usb_serial_hal.c +++ b/ubuntu/xr-usb-serial/xr_usb_serial_hal.c @@ -31,7 +31,7 @@ int xr_usb_serial_set_reg(struct xr_usb_serial *xr_usb_serial,int regnum, int va { int result; int channel = 0; - dev_dbg(&xr_usb_serial->control->dev, "%s Channel:%d 0x%02x = 0x%02x\n", __func__,channel,regnum, value); + //dev_info(&xr_usb_serial->control->dev, "%s Channel:%d 0x%02x = 0x%02x\n", __func__,channel,regnum, value); if((xr_usb_serial->DeviceProduct&0xfff0) == 0x1400) { int XR2280xaddr = XR2280x_FUNC_MGR_OFFSET + regnum; @@ -97,7 +97,7 @@ int xr_usb_serial_set_reg(struct xr_usb_serial *xr_usb_serial,int regnum, int va result = -1; } if(result < 0) - dev_dbg(&xr_usb_serial->control->dev, "%s Error:%d\n", __func__,result); + dev_err(&xr_usb_serial->control->dev, "%s Error:%d\n", __func__,result); return result; @@ -106,7 +106,7 @@ int xr_usb_serial_set_reg_ext(struct xr_usb_serial *xr_usb_serial,int channel,in { int result; int XR2280xaddr = XR2280x_FUNC_MGR_OFFSET + regnum; - dev_dbg(&xr_usb_serial->control->dev, "%s channel:%d 0x%02x = 0x%02x\n", __func__,channel,regnum, value); + //dev_info(&xr_usb_serial->control->dev, "%s channel:%d 0x%02x = 0x%02x\n", __func__,channel,regnum, value); if((xr_usb_serial->DeviceProduct&0xfff0) == 0x1400) { result = usb_control_msg(xr_usb_serial->dev, /* usb device */ @@ -165,7 +165,7 @@ int xr_usb_serial_set_reg_ext(struct xr_usb_serial *xr_usb_serial,int channel,in result = -1; } if(result < 0) - dev_dbg(&xr_usb_serial->control->dev, "%s Error:%d\n", __func__,result); + dev_err(&xr_usb_serial->control->dev, "%s Error:%d\n", __func__,result); return result; @@ -242,9 +242,9 @@ int xr_usb_serial_get_reg(struct xr_usb_serial *xr_usb_serial,int regnum, short } if(result < 0) - dev_dbg(&xr_usb_serial->control->dev, "%s channel:%d Reg 0x%x Error:%d\n", __func__,channel,regnum,result); - else - dev_dbg(&xr_usb_serial->control->dev, "%s channel:%d 0x%x = 0x%04x\n", __func__,channel,regnum, *value); + dev_err(&xr_usb_serial->control->dev, "%s channel:%d Reg 0x%x Error:%d\n", __func__,channel,regnum,result); + //else + //dev_info(&xr_usb_serial->control->dev, "%s channel:%d 0x%x = 0x%04x\n", __func__,channel,regnum, *value); return result; @@ -285,7 +285,7 @@ int xr_usb_serial_get_reg_ext(struct xr_usb_serial *xr_usb_serial,int channel,in ®_value, /* data */ 1, /* size */ 5000); /* timeout */ - dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_get_reg_ext reg:%x\n",reg_value); + //dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_get_reg_ext reg:%x\n",reg_value); *value = reg_value; } else if(xr_usb_serial->DeviceProduct == 0x1411) @@ -320,9 +320,9 @@ int xr_usb_serial_get_reg_ext(struct xr_usb_serial *xr_usb_serial,int channel,in } if(result < 0) - dev_dbg(&xr_usb_serial->control->dev, "%s Error:%d\n", __func__,result); - else - dev_dbg(&xr_usb_serial->control->dev, "%s channel:%d 0x%x = 0x%04x\n", __func__,channel,regnum, *value); + dev_err(&xr_usb_serial->control->dev, "%s Error:%d\n", __func__,result); + //else + //dev_info(&xr_usb_serial->control->dev, "%s channel:%d 0x%x = 0x%04x\n", __func__,channel,regnum, *value); return result; @@ -384,7 +384,7 @@ static int xr21v141x_set_baud_rate(struct xr_usb_serial *xr_usb_serial, unsigned unsigned int tx_mask = xr21v141x_baud_rates[i].tx; unsigned int rx_mask = (divisor & 1) ? xr21v141x_baud_rates[i].rx1 : xr21v141x_baud_rates[i].rx0; - dev_dbg(&xr_usb_serial->control->dev, "Setting baud rate to %d: i=%u div=%u tx=%03x rx=%03x\n", rate, i, divisor, tx_mask, rx_mask); + //dev_info(&xr_usb_serial->control->dev, "Setting baud rate to %d: i=%u div=%u tx=%03x rx=%03x\n", rate, i, divisor, tx_mask, rx_mask); xr_usb_serial_set_reg(xr_usb_serial,UART_CLOCK_DIVISOR_0, (divisor >> 0) & 0xff); xr_usb_serial_set_reg(xr_usb_serial,UART_CLOCK_DIVISOR_1, (divisor >> 8) & 0xff); @@ -458,7 +458,7 @@ int xr_usb_serial_set_line(struct xr_usb_serial *xr_usb_serial, struct usb_cdc_l if (cflag & CRTSCTS) { - dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_set_flow_mode:hardware\n"); + //dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_set_flow_mode:hardware\n"); flow = UART_FLOW_MODE_HW; gpio_mode = UART_GPIO_MODE_SEL_RTS_CTS; } @@ -466,7 +466,7 @@ int xr_usb_serial_set_line(struct xr_usb_serial *xr_usb_serial, struct usb_cdc_l { unsigned char start_char = START_CHAR(tty); unsigned char stop_char = STOP_CHAR(tty); - dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_set_flow_mode:software\n"); + //dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_set_flow_mode:software\n"); flow = UART_FLOW_MODE_SW; gpio_mode = UART_GPIO_MODE_SEL_GPIO; @@ -475,23 +475,47 @@ int xr_usb_serial_set_line(struct xr_usb_serial *xr_usb_serial, struct usb_cdc_l } else { - dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_set_flow_mode:none\n"); + //dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_set_flow_mode:none\n"); flow = UART_FLOW_MODE_NONE; gpio_mode = UART_GPIO_MODE_SEL_GPIO; } - // rs485,rs422 FD/HD mode - if (xr_usb_serial->rs485_422_en) { - xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_flow_addr, 0x00); - xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, 0x0B); - } else { - //rs232, default mode - xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_flow_addr, flow); - xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, gpio_mode); + + if((xr_usb_serial->DeviceProduct == 0x1420)|| + (xr_usb_serial->DeviceProduct == 0x1422)|| + (xr_usb_serial->DeviceProduct == 0x1424)) + {//Add support for the TXT and RXT function for 0x1420, 0x1422, 0x1424, by setting GPIO_MODE [9:8] = '11' + gpio_mode |= 0x300; + } + + if((xr_usb_serial->DeviceProduct == 0x1412)|| + (xr_usb_serial->DeviceProduct == 0x1414)) + { + if(xr_usb_serial->found_smbios_exar_config) + { + if((xr_usb_serial->channel_config == 2) + ||(xr_usb_serial->channel_config == 3)) + //if find the exar channel config in the smbios, the value can not be changed by the application + //dev_info(&xr_usb_serial->control->dev, "Sorry, Application can not change the channel gpio&flow mode,because there are config at SMBIOS\n"); + return 0; + } + } + + xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_flow_addr, flow); + + if((xr_usb_serial->found_smbios_exar_config == 1)&&(xr_usb_serial->channel_config == 1)) + { + //dev_info(&xr_usb_serial->control->dev, "Sorry, Application can not change the channel gpio mode,because there are config at SMBIOS\n"); } + else + xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, gpio_mode); + return 0; } + + + int xr_usb_serial_send_break(struct xr_usb_serial *xr_usb_serial, int state) { @@ -516,11 +540,17 @@ int xr_usb_serial_send_break(struct xr_usb_serial *xr_usb_serial, int state) #define URM_ENABLE_BASE 0x010 #define URM_ENABLE_0_TX 0x001 #define URM_ENABLE_0_RX 0x002 +#define URM_RESET_RX_FIFO_BASE 0x018 +#define URM_RESET_TX_FIFO_BASE 0x01C + + int xr_usb_serial_enable(struct xr_usb_serial *xr_usb_serial) { int ret = 0; int channel = xr_usb_serial->channel; + //dev_info(&xr_usb_serial->control->dev, "xr_usb_serial_enable channel=%d\n",channel); + if(channel) channel--; if((xr_usb_serial->DeviceProduct == 0x1410)|| (xr_usb_serial->DeviceProduct == 0x1412)|| (xr_usb_serial->DeviceProduct == 0x1414)) @@ -536,10 +566,31 @@ int xr_usb_serial_enable(struct xr_usb_serial *xr_usb_serial) return ret; } +int xr_usb_serial_fifo_reset(struct xr_usb_serial *xr_usb_serial) +{ + int ret = 0; + int channel = xr_usb_serial->channel; + + if(channel) channel--; + if((xr_usb_serial->DeviceProduct == 0x1410)|| + (xr_usb_serial->DeviceProduct == 0x1412)|| + (xr_usb_serial->DeviceProduct == 0x1414)) + { + + ret = xr_usb_serial_set_reg_ext(xr_usb_serial,URM_REG_BLOCK,URM_RESET_RX_FIFO_BASE + channel,0xff); + ret |= xr_usb_serial_set_reg_ext(xr_usb_serial,URM_REG_BLOCK,URM_RESET_TX_FIFO_BASE + channel,0xff); + + } + return ret; +} + + int xr_usb_serial_disable(struct xr_usb_serial *xr_usb_serial) { int ret = 0; int channel = xr_usb_serial->channel; + //dev_info(&xr_usb_serial->control->dev, "xr_usb_serial_disable channel=%d\n",channel); + if(channel) channel--; ret = xr_usb_serial_set_reg(xr_usb_serial,xr_usb_serial->reg_map.uart_enable_addr,0); if((xr_usb_serial->DeviceProduct == 0x1410)|| (xr_usb_serial->DeviceProduct == 0x1412)|| @@ -554,12 +605,81 @@ int xr_usb_serial_set_loopback(struct xr_usb_serial *xr_usb_serial, int channel) { int ret = 0; xr_usb_serial_disable(xr_usb_serial); - ret = xr_usb_serial_set_reg_ext(xr_usb_serial,channel, + + if((xr_usb_serial->DeviceProduct == 0x1410) || + (xr_usb_serial->DeviceProduct == 0x1412) || + (xr_usb_serial->DeviceProduct == 0x1414)) + { + switch (channel) + { + case 0: + ret = xr_usb_serial_set_reg_ext(xr_usb_serial,channel, + xr_usb_serial->reg_map.uart_loopback_addr,0x40); + break; + case 1: + ret = xr_usb_serial_set_reg_ext(xr_usb_serial,channel, + xr_usb_serial->reg_map.uart_loopback_addr,0x41); + break; + case 2: + ret = xr_usb_serial_set_reg_ext(xr_usb_serial,channel, + xr_usb_serial->reg_map.uart_loopback_addr,0x42); + break; + case 3: + ret = xr_usb_serial_set_reg_ext(xr_usb_serial,channel, + xr_usb_serial->reg_map.uart_loopback_addr,0x43); + break; + default: + + break; + } + } + else if((xr_usb_serial->DeviceProduct == 0x1420)|| + (xr_usb_serial->DeviceProduct == 0x1422)|| + (xr_usb_serial->DeviceProduct == 0x1424)) + { + ret = xr_usb_serial_set_reg_ext(xr_usb_serial,channel, xr_usb_serial->reg_map.uart_loopback_addr,0x07); + } xr_usb_serial_enable(xr_usb_serial); return ret; } +#define XR21V1414_WIDE_MODE_OFFSET 3 +#define XR21B142X_WIDE_MODE_TX_OFFSET 0x42 +#define XR21B142X_WIDE_MODE_RX_OFFSET 0x45 +int xr_usb_serial_set_wide_mode(struct xr_usb_serial *xr_usb_serial, int preciseflags) +{ + int ret = 0; + int channel = xr_usb_serial->channel; + xr_usb_serial_disable(xr_usb_serial); + if((xr_usb_serial->DeviceProduct&0xfff0) == 0x1400) + { + + } + else if((xr_usb_serial->DeviceProduct == 0x1410)|| + (xr_usb_serial->DeviceProduct == 0x1412)|| + (xr_usb_serial->DeviceProduct == 0x1414)) + { + + if(channel) channel--; + xr_usb_serial_set_reg_ext(xr_usb_serial, 0x66, channel*8 + XR21V1414_WIDE_MODE_OFFSET, preciseflags); + + } + else if(xr_usb_serial->DeviceProduct == 0x1411) + { + xr_usb_serial_set_reg(xr_usb_serial,0xd02, preciseflags); + } + else if((xr_usb_serial->DeviceProduct == 0x1420)|| + (xr_usb_serial->DeviceProduct == 0x1422)|| + (xr_usb_serial->DeviceProduct == 0x1424)) + { + xr_usb_serial_set_reg(xr_usb_serial, XR21B142X_WIDE_MODE_TX_OFFSET, preciseflags); + xr_usb_serial_set_reg(xr_usb_serial, XR21B142X_WIDE_MODE_RX_OFFSET, preciseflags); + } + xr_usb_serial_enable(xr_usb_serial); + return ret; +} + static int xr_usb_serial_tiocmget(struct xr_usb_serial *xr_usb_serial) @@ -567,7 +687,7 @@ static int xr_usb_serial_tiocmget(struct xr_usb_serial *xr_usb_serial) short data; int result; result = xr_usb_serial_get_reg(xr_usb_serial,xr_usb_serial->reg_map.uart_gpio_status_addr, &data); - dev_dbg(&xr_usb_serial->control->dev, "xr_usb_serial_tiocmget uart_gpio_status_addr:0x%04x\n",data); + //dev_info(&xr_usb_serial->control->dev, "xr_usb_serial_tiocmget uart_gpio_status_addr:0x%04x\n",data); if (result) return ((data & 0x8) ? 0: TIOCM_DTR) | ((data & 0x20) ? 0:TIOCM_RTS ) | ((data & 0x4) ? 0:TIOCM_DSR) | ((data & 0x1) ? 0 : TIOCM_RI) | ((data & 0x2) ? 0:TIOCM_CD) | ((data & 0x10) ? 0 : TIOCM_CTS); else @@ -675,11 +795,12 @@ static void init_xr21b142x_reg_map(void) xr21b140x_reg_map.uart_custom_driver = 0x60; xr21b140x_reg_map.uart_low_latency = 0x46; } - +int smbios_check_if_have_exar_config(unsigned char *config0,unsigned char *config1); int xr_usb_serial_pre_setup(struct xr_usb_serial *xr_usb_serial) { int ret = 0; - + unsigned char channel1_config = 255; + unsigned char channel2_config = 255; init_xr21b140x_reg_map(); init_xr21b1411_reg_map(); init_xr21v141x_reg_map(); @@ -716,9 +837,74 @@ int xr_usb_serial_pre_setup(struct xr_usb_serial *xr_usb_serial) xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_dir_addr, 0x28); xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_set_addr, UART_GPIO_SET_DTR | UART_GPIO_SET_RTS); + if((xr_usb_serial->DeviceProduct == 0x1412)|| + (xr_usb_serial->DeviceProduct == 0x1414)) + { + xr_usb_serial->found_smbios_exar_config = 0; + if(smbios_check_if_have_exar_config(&channel1_config,&channel2_config) == 0) + { + + if(xr_usb_serial->channel == 1) + { + xr_usb_serial->found_smbios_exar_config = 1; + xr_usb_serial->channel_config = channel1_config; + switch (channel1_config) + { + case 1://for RS232 Mode + //dev_info(&xr_usb_serial->control->dev, "SMBIOS Set Channel Mode to RS232\n"); + xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, 0); + + break; + case 2://RS-485 HALF DUPLEX + //dev_info(&xr_usb_serial->control->dev, "SMBIOS Set Channel Mode to RS-485 HALF DUPLEX\n"); + xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, 0x0b); + xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_flow_addr, 0x00); + break; + case 3://RS-485/422 FULL DUPLEX + //dev_info(&xr_usb_serial->control->dev, "SMBIOS Set Channel Mode to RS-485/422 FULL DUPLEX\n"); + xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, 0x0b); + xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_flow_addr, 0x00); + break; + default: + xr_usb_serial->found_smbios_exar_config = 0; + break; + } + + } + else if(xr_usb_serial->channel == 2) + { + xr_usb_serial->found_smbios_exar_config = 1; + xr_usb_serial->channel_config = channel2_config; + switch (channel2_config) + { + case 1://for RS232 Mode + //dev_info(&xr_usb_serial->control->dev, "SMBIOS Set Channel Mode to RS232\n"); + xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, 0); + + break; + case 2://RS-485 HALF DUPLEX + //dev_info(&xr_usb_serial->control->dev, "SMBIOS Set Channel Mode to RS-485 HALF DUPLEX\n"); + xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, 0x0b); + xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_flow_addr, 0x00); + break; + case 3://RS-485/422 FULL DUPLEX + //dev_info(&xr_usb_serial->control->dev, "SMBIOS Set Channel Mode to RS-485/422 FULL DUPLEX\n"); + xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, 0x0b); + xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_flow_addr, 0x00); + break; + default: + xr_usb_serial->found_smbios_exar_config = 0; + break; + } + } + else + { + //Nothing to do + } + } + + } return ret; } - - diff --git a/ubuntu/xr-usb-serial/xr_usb_serial_ioctl.h b/ubuntu/xr-usb-serial/xr_usb_serial_ioctl.h index c28b6bdc0b16..81394aac3290 100644 --- a/ubuntu/xr-usb-serial/xr_usb_serial_ioctl.h +++ b/ubuntu/xr-usb-serial/xr_usb_serial_ioctl.h @@ -24,6 +24,13 @@ #define XR_USB_SERIAL_SET_PRECISE_FLAGS _IO(XR_USB_SERIAL_IOC_MAGIC, 4) #define XR_USB_SERIAL_TEST_MODE _IO(XR_USB_SERIAL_IOC_MAGIC, 5) #define XR_USB_SERIAL_LOOPBACK _IO(XR_USB_SERIAL_IOC_MAGIC, 6) +#define XR_USB_SERIAL_SET_GPIO_MODE_REG _IO(XR_USB_SERIAL_IOC_MAGIC, 9) +#define XR_USB_SERIAL_GET_GPIO_MODE_REG _IO(XR_USB_SERIAL_IOC_MAGIC, 10) +#define XRIOC_SET_ANY_BAUD_RATE _IO(XR_USB_SERIAL_IOC_MAGIC, 11) +#define XRIOC_SET_PRECISE_FLAGS _IO(XR_USB_SERIAL_IOC_MAGIC, 12) + + + #define VZ_ADDRESS_UNICAST_S 0 #define VZ_ADDRESS_BROADCAST_S 8