Windows CE Developer Guide for Exar PCI UARTs

 

Revision: 1.5 – April 2005.

 

The Windows CE.Net driver support for Exar’s PCI UART family of devices (XR17C152/154/158 and XR17D152/154/158) is achieved by 3 sets of .dlls, viz, xrpci.dll, xrserial.dll and xrisr.dll. (In Windows CE, the drivers contain the extension as .dll.)

 

Xrpci.dll:

This is a kind of class driver which loads for the card and depending on the device like 152, 154, or 158 loads the required number of  xrserial.dll, each per port available and also requests and allocates the required memory and interrupt resources for each port. The initialization of this driver thus loads the xrserial.dll and the de-initialization closes and clears all the resources that were acquired during the init.

 

Xrserial.dll:

This driver is loaded for each port in the card as a separated instance with unique resources and memory area. This driver follows the standard Windows CE serial interface with standard MDD (Model Device Driver) interface exposed to the user level and has Exar specific Platform Dependent Driver interface that is specific to Exar UARTs. This driver connects or attaches the ISR for its System Interrupt. Thus each xrserial.dll driver will load its own instance of xrisr.dll.

 

Xrisr.dll:

This is the Interrupt Service Routine driver for the UARTs. This driver follows the same conventions of CE’s standard ISR driver.

 

Implementation through Platform Builder:

The developer should follow these steps for incorporating the driver into his platform. These steps are tested with Windows Platform Builder 4.20.

Create XRPCI driver in the existing platform:

  1. Select File->New Project or File…in the platform Builder
  2. In the Projects tab of  New Project or File dialog, select WCE Dynamic-Link Library.
  3. Type ‘XRPCI’ in the project name: edit box and select OK.
  4. In the next New Project Wizard step 1 of 1, select ‘An Empty Project’ and then Finish.
  5. Copy the 3 xrpci.xxx files from Exar provided files into newly created “xrpci” folder under your platform.
  6. Select FileView of Workspace window and choose XRPCI. Right click on “Header Files” folder and select Add Files to folder menu. In the next File open dialog box, chose xrpci folder under your platform and select xrpci.h
  7. Just like the above step, add xrpci.c and xrpci.def  to the “Source Files” folder.
  8. Select FeatureView of Workspace window and right click on XRPCI.pbp under “User features” tree, and select “Settings” in the drop down menu.
  9. In the “BIB Info” tab select “Files Section” radio button.
  10. Build the driver.

 

Create XRSERIAL driver in the platform:

  1. Select File->New Project or File…in the platform Builder
  2. In the Projects tab of  New Project or File dialog, select WCE Dynamic-Link Library.
  3. Type ‘XRSERIAL’ in the project name: edit box and select OK.
  4. In the next New Project Wizard step 1 of 1, select ‘An Empty Project’ and then Finish.
  5. Copy all the files under xrserial folder from the Exar provided files into newly created “XRSERIAL” folder under your platform.
  6. Select FileView of Workspace window and chose XRSERIAL. Right click on “Header Files” folder and select Add Files to folder menu. In the next File open dialog box, chose XRSERIAL folder under your platform and select xrser16550.h. Repeat the same for xrcom16550.h and xrserpriv.h.
  7. Just like the above step, add xrcom16550.c, xrmdd.c, xrser16550.c and xrcom16550.def to the “Source Files” folder.
  8. Select FileView of Workspace and right click on XRSERIAL, then chose settings. In the “Link” tab of Project Settings dialog, add ‘ceddk.lib’ in the object/library modules edit box while ‘General’ Category is selected.
  9. Select C/C++ tab in the same Settings dialog box, and edit ‘Preprocessor definitions’ adding “USE_NEW_SERIAL_MODEL” while ‘General’ Category is selected.
  10. Select FeatureView of Workspace window and right click on XRSERIAL.pbp under “User features” tree, and select “Settings” in the drop down menu.
  11. In the “BIB Info” tab select “Files Section” radio button.
  12. Build the driver.

 

Create XRISR driver  in the platform:

  1. Select File->New Project or File…in the platform Builder
  2. In the Projects tab of  New Project or File dialog, select WCE Dynamic-Link Library.
  3. Type ‘XRISR’ in the project name: edit box and select OK.
  4. In the next New Project Wizard step 1 of 1, select ‘An Empty Project’ and then Finish.
  5. Copy all the files under XRISR folder from the Exar provided files into newly created “XRISR” folder under your platform.
  6. Select FileView of Workspace window and chose XRISR. Right click on “Header Files” folder and select Add Files to folder menu. In the next File open dialog box, chose XRISR folder under your platform and select xrisr.h.
  7. Just like the above step, add xrisr.c and xrisr.def to the “Source Files” folder.
  8. Select FileView of Workspace and right click on xrisr, then chose settings. In the “Link” tab of Project Settings dialog, type ‘ddk_io.lib fulllibc.lib’ in the object/library modules edit box while ‘General’ Category is selected.
  9. Select “Output”  Category in the same window and replace the Entry-point Symbol with “DllEntry”. These 8 and 9 steps should be repeated for both Release and Debug mode.
  10. Select FeatureView of Workspace window and right click on XRISR.pbp under “User features” tree, and select “Settings” in the drop down menu.
  11. In the “BIB Info” tab select “Files Section” radio button.
  12. Build the driver.

 

After the above steps, before “Build Platform”, the “PROJECT.REG” file needs to be updated. So, open project.reg from the ParameterView of Workspace window. In the end of the file add the below registry entries.

 

;BEGIN for XRPCI

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\PCI\Template\xrpci]

   "Dll"="xrpci.dll"

   "Class"=dword:07

   "SubClass"=dword:00

   "ProgIF"=dword:02

   "VendorID"=multi_sz:"13A8","13A8","13A8"

   "DeviceID"=multi_sz:"0158","0154","0152"

   "Prefix"="XRP"

   "DeviceArrayIndex"=dword:0

   "DeviceType"=dword:0

   "FriendlyName"="EXAR PCI Card"

   "DevConfig"=hex: 10,00, 00,00, 05,00,00,00, 10,01,00,00, 00,4B,00,00

;END – for XRPCI

 

The above entries will load the EXARPCI class driver into the system.

 

Now to load the xrserial.dll, append the following entries into the same ‘project.reg’ file and then save.

 

;BEGIN – for upto 8 ports.

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\PCI\Template\xrserial0]

            "Dll"="xrserial.dll"

            "Prefix"="COM"

            "ioctl"=dword:4

            "DeviceArrayIndex"=dword:0

 

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\PCI\Template\xrserial1]

            "Dll"="xrserial.dll"

            "Prefix"="COM"

"ioctl"=dword:4

            "DeviceArrayIndex"=dword:1

 

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\PCI\Template\xrserial2]

            "Dll"="xrserial.dll"

            "Prefix"="COM"

            "ioctl"=dword:4

            "DeviceArrayIndex"=dword:2

 

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\PCI\Template\xrserial3]

            "Dll"="xrserial.dll"

            "Prefix"="COM"

            "ioctl"=dword:4

"DeviceArrayIndex"=dword:3

 

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\PCI\Template\xrserial4]

            "Dll"="xrserial.dll"

            "Prefix"="COM"

            "ioctl"=dword:4

            "DeviceArrayIndex"=dword:4

 

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\PCI\Template\xrserial5]

            "Dll"="xrserial.dll"

            "Prefix"="COM"

            "ioctl"=dword:4

            "DeviceArrayIndex"=dword:5

           

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\PCI\Template\xrserial6]

            "Dll"="xrserial.dll"

            "Prefix"="COM"

            "ioctl"=dword:4

            "DeviceArrayIndex"=dword:6

 

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\PCI\Template\xrserial7]

            "Dll"="xrserial.dll"

            "Prefix"="COM"

            "ioctl"=dword:4

            "DeviceArrayIndex"=dword:7

;END – for 8 ports

 

NOTE: The DeviceArrayIndex in xrserial0 starts with 0. The developer needs to check this with his/her project.reg settings, and this should not collide with any other serial devices.

 

The XRISR driver is loaded programmatically in the xrserial.dll driver.

 

If all the above steps are done successfully, the platform can be built by “Build Platform” option. With this newly created image file, the system will find the Exar card and all the ports should be enumerated. User should check the registry to check the “COMx:” for the proper value to open the ports through CreateFile API in the user level. To check whether the ports are working are not, the user can use the Exar supplied XRSerComm.exe tool.

 

 

IOCTL support in driver for special features:

 

Revision 1.5 and later of the PCI UART Driver set has support for special features in the form of IOCTLs which can be accessed from applications using Windows CE API DeviceIoControl. The supported IOCTLs are;

 

IOCTL_XR17C15X_ENABLE_HWFLOWCONTROL

IOCTL_XR17C15X_DISABLE_HWFLOWCONTROL

IOCTL_XR17C15X_ENABLE_SWFLOWCONTROL        

IOCTL_XR17C15X_DISABLE_SWFLOWCONTROL

IOCTL_XR17C15X_ENABLE_IR                                        

IOCTL_XR17C15X_DISABLE_IR               

IOCTL_XR17C15X_ENABLE_SLEEPMODE

IOCTL_XR17C15X_DISABLE_SLEEPMODE

IOCTL_XR17C15X_ENABLE_INTERNAL_LOOPBACK

IOCTL_XR17C15X_DISABLE_INTERNAL_LOOPBACK

IOCTL_XR17C15X_ENABLE_AUTORS485

IOCTL_XR17C15X_DISABLE_AUTORS485

IOCTL_XR17C15X_CONFIG_REG_READ            

IOCTL_XR17C15X_CONFIG_REG_WRITE

 

The sample code to use these IOCTLs in an application:

 

Step 1: Include the declarations below in an appropriate header file.

 

// All Windows CE specific EXAR IOCTL codes and the related data types are defined here

// the IOCTL index starts from 50 (in pegdser.h the last ioctl index ends at 25)

#define IOCTL_XR17C15X_ENABLE_HWFLOWCONTROL                    CTL_CODE(FILE_DEVICE_SERIAL_PORT,50,METHOD_BUFFERED,FILE_ANY_ACCESS)

#define IOCTL_XR17C15X_DISABLE_HWFLOWCONTROL                   CTL_CODE(FILE_DEVICE_SERIAL_PORT,51,METHOD_BUFFERED,FILE_ANY_ACCESS)

#define IOCTL_XR17C15X_ENABLE_SWFLOWCONTROL                     CTL_CODE(FILE_DEVICE_SERIAL_PORT,52,METHOD_BUFFERED,FILE_ANY_ACCESS)

#define IOCTL_XR17C15X_DISABLE_SWFLOWCONTROL                    CTL_CODE(FILE_DEVICE_SERIAL_PORT,53,METHOD_BUFFERED,FILE_ANY_ACCESS)

#define IOCTL_XR17C15X_ENABLE_IR                                                     CTL_CODE(FILE_DEVICE_SERIAL_PORT,54,METHOD_BUFFERED,FILE_ANY_ACCESS)

#define IOCTL_XR17C15X_DISABLE_IR                                                    CTL_CODE(FILE_DEVICE_SERIAL_PORT,55,METHOD_BUFFERED,FILE_ANY_ACCESS)

#define IOCTL_XR17C15X_ENABLE_SLEEPMODE                                  CTL_CODE(FILE_DEVICE_SERIAL_PORT,56,METHOD_BUFFERED,FILE_ANY_ACCESS)

#define IOCTL_XR17C15X_DISABLE_SLEEPMODE                                 CTL_CODE(FILE_DEVICE_SERIAL_PORT,57,METHOD_BUFFERED,FILE_ANY_ACCESS)

#define IOCTL_XR17C15X_ENABLE_INTERNAL_LOOPBACK             CTL_CODE(FILE_DEVICE_SERIAL_PORT,58,METHOD_BUFFERED,FILE_ANY_ACCESS)

#define IOCTL_XR17C15X_DISABLE_INTERNAL_LOOPBACK             CTL_CODE(FILE_DEVICE_SERIAL_PORT,59,METHOD_BUFFERED,FILE_ANY_ACCESS)

#define IOCTL_XR17C15X_ENABLE_AUTORS485                                   CTL_CODE(FILE_DEVICE_SERIAL_PORT,60,METHOD_BUFFERED,FILE_ANY_ACCESS)

#define IOCTL_XR17C15X_DISABLE_AUTORS485                                  CTL_CODE(FILE_DEVICE_SERIAL_PORT,61,METHOD_BUFFERED,FILE_ANY_ACCESS)

#define IOCTL_XR17C15X_CONFIG_REG_READ                                                 CTL_CODE(FILE_DEVICE_SERIAL_PORT,62,METHOD_BUFFERED,FILE_ANY_ACCESS)

#define IOCTL_XR17C15X_CONFIG_REG_WRITE                                               CTL_CODE(FILE_DEVICE_SERIAL_PORT,63,METHOD_BUFFERED,FILE_ANY_ACCESS)

 

typedef struct          /* Software Flow Control Enable Options*/

{

            BOOL custom; /* if YES, please specify Xon/Xoff chars */

            BYTE One_or_Two_Char;      /* if 1 - and custom-Yes, specify Xon1 and Xoff1 chars. If 2 and custom-Yes, specify both Xon1/Xoff1 and Xon2 and Xon2 */

            BYTE Xon1;

            BYTE Xoff1;

            BYTE Xon2;

            BYTE Xoff2;

} SW_FLOW_CONTROL_PARAMS;

 

typedef struct

{

    unsigned char            bReg;

            unsigned char    bData;

 

} CONFIG_WRITE, *PCONFIG_WRITE;

 

 

Step 2: Include the below code in an appropriate C/C++ file

 

{

                        BOOL Status;

                        DWORD dwIoControlCode;

                        PVOID pInBuffer, pOutBuffer;

                        DWORD nInBufferSize, nOutBufferSize, cbReturned;

                       

                        //

                        // all input/output variables for whole function scope are defined here

                        //

                        SW_FLOW_CONTROL_PARAMS SWFCParams;

                        BOOL bInvert;

                        UCHAR ucTemp1, ucTemp2;

                        CONFIG_WRITE CfgWrite;

                       

                        pInBuffer = pOutBuffer = NULL;

                        nInBufferSize = nOutBufferSize = 0;

 

                        switch(dwIoCtlCodeIndex)

                        {

                                    case 0: //ENABLE_HWFLOWCONTROL

                                    {

                                                dwIoControlCode = IOCTL_XR17C15X_ENABLE_HWFLOWCONTROL;

                                    }

                                    break;

 

                                    case 1: //DISABLE_HWFLOWCONTROL

                                    {

                                                dwIoControlCode = IOCTL_XR17C15X_DISABLE_HWFLOWCONTROL;

                                    }

                                    break;

 

                                    case 2: //ENABLE_SWFLOWCONTROL

                                    {                                             

                                                SWFCParams.custom = TRUE; // FALSE if you want default

SWFCParams.One_or_Two_Char = 2;

                                                SWFCParams.Xoff1 = 0x13;

                                                SWFCParams.Xoff2 = 0x14;

                                                SWFCParams.Xon1 = 0x11;

                                                SWFCParams.Xon2 = 0x12;

 

                                                pInBuffer = &SWFCParams;

                                                nInBufferSize = sizeof(SW_FLOW_CONTROL_PARAMS);

                                                dwIoControlCode = IOCTL_XR17C15X_ENABLE_SWFLOWCONTROL;

                                    }

                                    break;

 

                                    case 3: //DISABLE_SWFLOWCONTROL

                                    {

                                                dwIoControlCode = IOCTL_XR17C15X_DISABLE_SWFLOWCONTROL;

                                    }

                                    break;

 

                                    case 4: //ENABLE_IR

                                    {                                             

                                                bInvert = TRUE; // FALSE if you don't want invert

 

                                                pInBuffer = &bInvert;

                                                nInBufferSize = sizeof(BOOL);

                                                dwIoControlCode = IOCTL_XR17C15X_ENABLE_IR;

                                    }

                                    break;

 

                                    case 5: //DISABLE_IR

                                    {

                                                dwIoControlCode = IOCTL_XR17C15X_DISABLE_IR;

                                    }

                                    break;

 

                                    case 6: //ENABLE_SLEEPMODE

                                    {

// This will put all the channels into sleep

                                                // This operation can only be called from the

                                                // first Channel's COM port handle

                                                dwIoControlCode = IOCTL_XR17C15X_ENABLE_SLEEPMODE;

                                    }

                                    break;

 

                                    case 7: //DISABLE_SLEEPMODE

                                    {

// This will bring out all the channels from sleep

                                                // This operation can only be called from the

                                                // first Channel's COM port handle

                                                dwIoControlCode = IOCTL_XR17C15X_DISABLE_SLEEPMODE;

                                    }

                                    break;

 

                                    case 8: //ENABLE_INTERNAL_LOOPBACK

                                    {

                                                dwIoControlCode = IOCTL_XR17C15X_ENABLE_INTERNAL_LOOPBACK;

                                    }

                                    break;

 

                                    case 9: //DISABLE_INTERNAL_LOOPBACK

                                    {

                                                dwIoControlCode = IOCTL_XR17C15X_DISABLE_INTERNAL_LOOPBACK;

                                    }

                                    break;                         

 

                                    case 10: //PCIUART_CONFIG_REG_READ

                                    {                                             

                                                ucTemp1 =  0x80 to 0x93; // configuration registers offset range is 0x80 to 0x93; provide appropriate register offset

                                                                                               

                                                pInBuffer = &ucTemp1;

                                                pOutBuffer = &ucTemp2;

                                                nInBufferSize = nOutBufferSize = sizeof(UCHAR);

                                                dwIoControlCode = IOCTL_XR17C15X_CONFIG_REG_READ;

                                    }

                                    break;

 

                                    case 11: //PCIUART_CONFIG_REG_WRITE

                                    {                                             

                                                CfgWrite.bReg = 0x80 to 0x93; // configuration registers offset range is 0x80 to 0x93; provide appropriate register offset

                                                CfgWrite.bData = your data to write;

 

                                                pInBuffer = (PVOID)&CfgWrite;

                                                nInBufferSize = sizeof(CONFIG_WRITE);                                          

                                                dwIoControlCode = IOCTL_XR17C15X_CONFIG_REG_WRITE;                                                             

                                    }

                                    break;

 

                                    default:

                                    {

                                                CString str;

                                                str.Format(_T("Error: Invalid IOCTL !!!"));

                                                MessageBox (str, TEXT("Failure"), MB_OK);            

                                    }

                                    break or return;

                        }                     

 

                        Status = DeviceIoControl(        hPort,

                                                                        dwIoControlCode,

                                                                        pInBuffer,

                                                                        nInBufferSize,

                                                                        pOutBuffer,

                                                                        nOutBufferSize,

                                                                        &cbReturned,

                                                                        0);

                        if (!Status)

                        {                     

                                    CString str;

                                    str.Format(_T("Error: This operation failed!!!"));

                                    MessageBox (str, TEXT("Failure"), MB_OK);

                        }

                        else

                        {

                                    // for Config Read we need to do extra work like displaying the data here                                 

                                    if(dwIoControlCode == IOCTL_XR17C15X_CONFIG_REG_READ)

                                    {

                                                ucTemp2 contains the Cnfig Regsiter’s Read data;

                                    }

                        }

            }