3.7   Devices in VxWorks

The VxWorks I/O system is flexible, allowing specific device drivers to handle the seven I/O functions. All VxWorks device drivers follow the basic conventions outlined previously, but differ in specifics; this section describes those specifics.

Table 3-6:  Drivers Provided with VxWorks  


Module
Driver Description

ttyDrv  
Terminal driver  
ptyDrv  
Pseudo-terminal driver 
pipeDrv  
Pipe driver 
memDrv  
Pseudo memory device driver 
nfsDrv  
NFS client driver 
netDrv  
Network driver for remote file access 
ramDrv  
RAM driver for creating a RAM disk 
scsiLib  
SCSI interface library  
-  
Other hardware-specific drivers 

3.7.1   Serial I/O Devices (Terminal and Pseudo-Terminal Devices)

VxWorks provides terminal and pseudo-terminal device drivers (tty and pty drivers). The tty driver is for actual terminals; the pty driver is for processes that simulate terminals. These pseudo terminals are useful in applications such as remote login facilities.1

VxWorks serial I/O devices are buffered serial byte streams. Each device has a ring buffer (circular buffer) for both input and output. Reading from a tty device extracts bytes from the input ring. Writing to a tty device adds bytes to the output ring. The size of each ring buffer is specified when the device is created during system initialization.

Tty Options

The tty devices have a full range of options that affect the behavior of the device. These options are selected by setting bits in the device option word using the ioctl( ) routine with the FIOSETOPTIONS function (see I/O Control Functions). For example, to set all the tty options except OPT_MON_TRAP:

status = ioctl (fd, FIOSETOPTIONS, OPT_TERMINAL & ~OPT_MON_TRAP);

Table 3-7 is a summary of the available options. The listed names are defined in the header file ioLib.h. For more detailed information, see the reference entry for tyLib.

Table 3-7:  Tty Options


Library
Description

OPT_LINE  
Select line mode. (See Raw Mode and Line Mode.) 
OPT_ECHO  
Echo input characters to the output of the same channel. 
OPT_CRMOD  
Translate input RETURN characters into NEWLINE (\n); translate output NEWLINE into RETURN-LINEFEED
OPT_TANDEM  
Respond to X-on/X-off protocol (CTRL+Q and CTRL+S). 
OPT_7_BIT  
Strip the most significant bit from all input bytes. 
OPT_MON_TRAP  
Enable the special ROM monitor trap character, CTRL+X by default.  
OPT_ABORT  
Enable the special target shell abort character, CTRL+C by default. (Only useful if the target shell is configured into the system; see 9. Target Shell in this manual for details.) 
OPT_TERMINAL  
Set all of the above option bits. 
OPT_RAW  
Set none of the above option bits. 

Raw Mode and Line Mode

A tty device operates in one of two modes: raw mode (unbuffered) or line mode. Raw mode is the default. Line mode is selected by the OPT_LINE bit of the device option word (see Tty Options).

In raw mode, each input character is available to readers as soon as it is input from the device. Reading from a tty device in raw mode causes as many characters as possible to be extracted from the input ring, up to the limit of the user's read buffer. Input cannot be modified except as directed by other tty option bits.

In line mode, all input characters are saved until a NEWLINE character is input; then the entire line of characters, including the NEWLINE, is made available in the ring at one time. Reading from a tty device in line mode causes characters up to the end of the next line to be extracted from the input ring, up to the limit of the user's read buffer. Input can be modified by the special characters CTRL+H (backspace), CTRL+U (line-delete), and CTRL+D (end-of-file), which are discussed in Tty Special Characters.

Tty Special Characters

The following special characters are enabled if the tty device operates in line mode, that is, with the OPT_LINE bit set:

The following characters have special effects if the tty device is operating with the corresponding option bit set:

The characters for most of these functions can be changed using the tyLib routines shown in Table 3-8.

Table 3-8:  Tty Special Characters


Character
Description
Modifier

CTRL+H  
backspace (character delete) 
tyBackspaceSet( )  
CTRL+U  
line delete 
tyDeleteLineSet( )  
CTRL+D  
EOF (end of file) 
tyEOFSet( )  
CTRL+C  
target shell abort  
tyAbortSet( )  
CTRL+X  
trap to boot ROMs 
tyMonitorTrapSet( )  
CTRL+S  
output suspend  
N/A 
CTRL+Q  
output resume 
N/A 

I/O Control Functions

The tty devices respond to the ioctl( ) functions in Table 3-9, defined in ioLib.h. For more information, see the reference entries for tyLib, ttyDrv, and ioctl( ).

Table 3-9:  I/O Control Functions Supported by tyLib  


Function
Description

FIOBAUDRATE  
Set the baud rate to the specified argument. 
FIOCANCEL  
Cancel a read or write. 
FIOFLUSH  
Discard all bytes in the input and output buffers. 
FIOGETNAME  
Get the file name of the fd
FIOGETOPTIONS  
Return the current device option word. 
FIONREAD  
Get the number of unread bytes in the input buffer. 
FIONWRITE  
Get the number of bytes in the output buffer. 
FIOSETOPTIONS  
Set the device option word. 


*

CAUTION: To change the driver's hardware options (for example, the number of stop bits or parity bits), use the ioctl( ) function SIO_HW_OPTS_SET. Because this command is not implemented in most drivers, you may need to add it to your BSP serial driver, which resides in installDir/target/src/drv/sio. The details of how to implement this command depend on your board's serial chip. The constants defined in the header file installDir/target/h/sioLib.h provide the POSIX definitions for setting the hardware options.

3.7.2   Pipe Devices

Pipes are virtual devices by which tasks communicate with each other through the I/O system. Tasks write messages to pipes; these messages can then be read by other tasks. Pipe devices are managed by pipeDrv and use the kernel message queue facility to bear the actual message traffic.

Creating Pipes

Pipes are created by calling the pipe create routine:

status = pipeDevCreate ("/pipe/name", maxMsgs, maxLength);

The new pipe can have at most maxMsgs messages queued at a time. Tasks that write to a pipe that already has the maximum number of messages queued are delayed until a message is dequeued. Each message in the pipe can be at most maxLength bytes long; attempts to write longer messages result in an error.

Writing to Pipes from ISRs

VxWorks pipes are designed to allow ISRs to write to pipes in the same way as task-level code. Many VxWorks facilities cannot be used from ISRs, including I/O to devices other than pipes. However, ISRs can use pipes to communicate with tasks, which can then invoke such facilities.

ISRs write to a pipe using the write( ) call. Tasks and ISRs can write to the same pipes. However, if the pipe is full, the message is discarded because the ISRs cannot pend. ISRs must not invoke any I/O function on pipes other than write( ).

I/O Control Functions

Pipe devices respond to the ioctl( ) functions summarized in Table 3-10. The functions listed are defined in the header file ioLib.h. For more information, see the reference entries for pipeDrv and for ioctl( ) in ioLib.

Table 3-10:  I/O Control Functions Supported by pipeDrv


Function
Description

FIOFLUSH  
Discard all messages in the pipe. 
FIOGETNAME  
Get the pipe name of the fd
FIONMSGS  
Get the number of messages remaining in the pipe. 
FIONREAD  
Get the size in bytes of the first message in the pipe. 

3.7.3   Pseudo Memory Devices

The memDrv driver allows the I/O system to access memory directly as a pseudo-I/O device. Memory location and size are specified when the device is created. This feature is useful when data must be preserved between boots of VxWorks or when sharing data between CPUs. This driver does not implement a file system as does ramDrv. The ramDrv driver must be given memory over which it has absolute control; whereas memDrv provides a high-level method of reading and writing bytes in absolute memory locations through I/O calls.

Installing the Memory Driver

The driver is first initialized and then the device is created:

STATUS memDrv 
    (void) 
STATUS memDevCreate 
    (char * name, char * base, int length)

Memory for the device is an absolute memory location beginning at base. The length parameter indicates the size of the memory. For additional information on the memory driver, see the reference entries for memDrv, memDevCreate( ), and memDrv( ).

I/O Control Functions

The memory driver responds to the ioctl( ) functions summarized in Table 3-11. The functions listed are defined in the header file ioLib.h. For more information, see the reference entries for memDrv and for ioctl( ) in ioLib.

Table 3-11:  I/O Control Functions Supported by memDrv


Function
Description

FIOSEEK  
Set the current byte offset in the file. 
FIOWHERE  
Return the current byte position in the file. 

3.7.4   Network File System (NFS) Devices

Network File System (NFS) devices allow files on remote hosts to be accessed with the NFS protocol. The NFS protocol specifies both client software, to read files from remote machines, and server software, to export files to remote machines.

The driver nfsDrv acts as a VxWorks NFS client to access files on any NFS server on the network. VxWorks also allows you to run an NFS server to export files to other systems; see VxWorks Network Programmer's Guide: File Access Applicationsl.

Using NFS devices, you can create, open, and access remote files exactly as though they were on a file system on a local disk. This is called network transparency.

Mounting a Remote NFS File System from VxWorks

Access to a remote NFS file system is established by mounting that file system locally and creating an I/O device for it using nfsMount( ). Its arguments are (1) the host name of the NFS server, (2) the name of the host file system, and (3) the local name for the file system.

For example, the following call mounts /usr of the host mars as /vxusr locally:

nfsMount ("mars", "/usr", "/vxusr");

This creates a VxWorks I/O device with the specified local name (/vxusr, in this example). If the local name is specified as NULL, the local name is the same as the remote name.

After a remote file system is mounted, the files are accessed as though the file system were local. Thus, after the previous example, opening the file /vxusr/foo opens the file /usr/foo on the host mars.

The remote file system must be exported by the system on which it actually resides. However, NFS servers can export only local file systems. Use the appropriate command on the server to see which file systems are local. NFS requires authentication parameters to identify the user making the remote access. To set these parameters, use the routines nfsAuthUnixSet( ) and nfsAuthUnixPrompt( ).

Select INCLUDE_NFS for inclusion in the project facility VxWorks view to include NFS client support in your VxWorks configuration; see Tornado User's Guide: Projects for information on configuring VxWorks.

The subject of exporting and mounting NFS file systems and authenticating access permissions is discussed in more detail in VxWorks Network Programmer's Guide: File Access Applications. See also the reference entries nfsLib and nfsDrv, and the NFS documentation from Sun Microsystems.

I/O Control Functions for NFS Clients

NFS client devices respond to the ioctl( ) functions summarized in Table 3-12. The functions listed are defined in ioLib.h. For more information, see the reference entries for nfsDrv and for ioctl( ) in ioLib.

Table 3-12:  I/O Control Functions Supported by nfsDrv


Function
Description

FIOFSTATGET  
Get file status information (directory entry data). 
FIOGETNAME  
Get the file name of the fd
FIONREAD  
Get the number of unread bytes in the file. 
FIOREADDIR  
Read the next directory entry. 
FIOSEEK  
Set the current byte offset in the file. 
FIOSYNC  
Flush data to a remote NFS file. 
FIOWHERE  
Return the current byte position in the file. 

3.7.5   Non-NFS Network Devices

VxWorks also supports network access to files on the remote host through the Remote Shell protocol (RSH) or the File Transfer Protocol (FTP). These implementations of network devices use the driver netDrv. When a remote file is opened using RSH or FTP, the entire file is copied into local memory. As a result, the largest file that can be opened is restricted by the available memory. Read and write operations are performed on the in-memory copy of the file. When closed, the file is copied back to the original remote file if it was modified.

In general, NFS devices are preferable to RSH and FTP devices for performance and flexibility, because NFS does not copy the entire file into local memory. However, NFS is not supported by all host systems.

Creating Network Devices

To access files on a remote host using either RSH or FTP, a network device must first be created by calling the routine netDevCreate( ). The arguments to netDevCreate( ) are (1) the name of the device, (2) the name of the host the device accesses, and (3) which protocol to use: 0 (RSH) or 1 (FTP).

For example, the following call creates an RSH device called mars: that accesses the host mars. By convention, the name for a network device is the remote machine's name followed by a colon (:).

netDevCreate ("mars:", "mars", 0);

Files on a network device can be created, opened, and manipulated as if on a local disk. Thus, opening the file mars:/usr/foo actually opens /usr/foo on host mars.

Note that creating a network device allows access to any file or device on the remote system, while mounting an NFS file system allows access only to a specified file system.

For the files of a remote host to be accessible with RSH or FTP, permissions and user identification must be established on both the remote and local systems. Creating and configuring network devices is discussed in detail in VxWorks Network Programmer's Guide: File Access Applications and in the reference entry for netDrv.

I/O Control Functions

RSH and FTP devices respond to the same ioctl( ) functions as NFS devices except for FIOSYNC and FIOREADDIR. The functions are defined in the header file ioLib.h. For more information, see the reference entries for netDrv and ioctl( ).

3.7.6   Block Devices

A block device is a device that is organized as a sequence of individually accessible blocks of data. The most common type of block device is a disk. In VxWorks, the term block refers to the smallest addressable unit on the device. For most disk devices, a VxWorks block corresponds to a sector, although terminology varies.

Block devices in VxWorks have a slightly different interface than other I/O devices. Rather than interacting directly with the I/O system, block device support consists of low-level drivers that interact with a file system. The file system, in turn, interacts with the I/O system. This arrangement allows a single low-level driver to be used with various different file systems and reduces the number of I/O functions that must be supported in the driver. The internal implementation of low-level drivers for block devices is discussed in 3.9.4 Block Devices.

File Systems

For use with block devices, VxWorks is supplied with file system libraries compatible with the MS-DOS (dosFs) and RT-11 (rt11Fs) file systems. In addition, there is a library for a simple raw disk file system (rawFs), which treats an entire disk much like a single large file. Also supplied is a file system that supports SCSI tape devices, which are organized so that individual blocks of data are read and written sequentially, and a file system that supports CD-ROM devices. Use of these file systems is discussed in 4. Local File Systems in this manual. Also see the reference entries for dosFsLib, rt11FsLib, rawFsLib, tapeFsLib, and cdromFsLib.

RAM Disk Drivers

RAM drivers, as implemented in ramDrv, emulate disk devices but actually keep all data in memory. Memory location and "disk" size are specified when a RAM device is created by calling ramDevCreate( ). This routine can be called repeatedly to create multiple RAM disks.

Memory for the RAM disk can be preallocated and the address passed to ramDevCreate( ), or memory can be automatically allocated from the system memory pool using malloc( ).

After the device is created, a name and file system (dosFs, rt11Fs, or rawFs) must be associated with it using the file system's device initialization routine or file system's make routine, for example, dosFsDevInit( ) or dosFsMkfs( ). Information describing the device is passed to the file system in a BLK_DEV structure. A pointer to this structure is returned by the RAM disk creation routine.

In the following example, a 200KB RAM disk is created with automatically allocated memory, 512-byte sections, a single track, and no sector offset. The device is assigned the name DEV1: and initialized for use with dosFs.

    BLK_DEV               *pBlkDev; 
    DOS_VOL_DESC          *pVolDesc; 
    pBlkDev = ramDevCreate (0, 512, 400, 400, 0); 
    pVolDesc = dosFsMkfs ("DEV1:", pBlkDev);

The dosFsMkfs( ) routine calls dosFsDevInit( ) with default parameters and initializes the file system on the disk by calling ioctl( ) with the FIODISKINIT.

If the RAM disk memory already contains a disk image, the first argument to ramDevCreate( ) is the address in memory, and the formatting arguments must be identical to those used when the image was created. For example:

pBlkDev = ramDevCreate (0xc0000, 512, 400, 400, 0); 
pVolDesc = dosFsDevInit ("DEV1:", pBlkDev, NULL);

In this case, dosFsDevInit( ) must be used instead, because the file system already exists on the disk and does not require re-initialization. This procedure is useful if a RAM disk is to be created at the same address used in a previous boot of VxWorks. The contents of the RAM disk are then preserved. Creating a RAM disk with rt11Fs using rt11FsMkfs( ) and rt11FsDevInit( ) follows these same procedures. For more information on RAM disk drivers, see the reference entry for ramDrv. For more information on file systems, see 4. Local File Systems.

SCSI Drivers

SCSI is a standard peripheral interface that allows connection with a wide variety of hard disks, optical disks, floppy disks, tape drives, and CD-ROM devices. SCSI block drivers are compatible with the dosFs and rt11Fs libraries, and offer several advantages for target configurations. They provide:

The SCSI-2 support in VxWorks supersedes previous SCSI support, although it offers the option of configuring the original SCSI functionality, now known as SCSI-1. With SCSI-2 enabled, the VxWorks environment can still handle SCSI-1 applications, such as file systems created under SCSI-1. However, applications that directly used SCSI-1 data structures defined in scsiLib.h may require modifications and recompilation for SCSI-2 compatibility.

The VxWorks SCSI implementation consists of two modules, one for the device-independent SCSI interface and one to support a specific SCSI controller. The scsiLib library provides routines that support the device-independent interface; device-specific libraries provide configuration routines that support specific controllers (for example, wd33c93Lib for the Western Digital WD33C93 device or mb87030Lib for the Fujitsu MB87030 device). There are also additional support routines for individual targets in sysLib.c.

Configuring SCSI Drivers

Constants associated with SCSI drivers are listed in Table 3-13. Define these in the indicated portion of the VxWorks view or in the configuration files. To enable SCSI functionality, select INCLUDE_SCSI for inclusion in the project facility VxWorks view. This enables SCSI-1. To enable SCSI-2, you must select, in addition to SCSI-1, INCLUDE_SCSI2.

Table 3-13:  SCSI Constants


Constant
Description
Where to Configure

INCLUDE_SCSI  
Include SCSI interface. 
hardware/buses  
INCLUDE_SCSI2 
SCSI-2 extensions. 
hardware/buses  
INCLUDE_SCSI_DMA  
Enable DMA for SCSI. 
sysLib.c or sysScsi.c  
INCLUDE_SCSI_BOOT  
Allow booting from a SCSI device. 
sysLib.c or sysScsi.c  
SCSI_AUTO_CONFIG  
Auto-configure and locate all targets on a SCSI bus. 
sysLib.c or sysScsi.c  
INCLUDE_DOSFS 
Include the DOS file system. 
operating system components/IO system components  
INCLUDE_TAPEFS 
Include the tape file system. 
config.h  
INCLUDE_CDROMFS 
Include CD-ROM file system support. 
config.h  

Autoconfiguration, DMA, and booting from a SCSI device are defined appropriately for each BSP. If you need to change these settings, see the online reference for sysScsiConfig( ) under VxWorks Reference>Manual: Libraries and the source file installDir/target/src/config/usrScsi.c. Except for dosFs, which can be configured from the project facility, the file systems that can be used with SCSI must be defined in config.h. (For more information see 8. Configuration and Build.)


*

CAUTION: Including SCSI-2 in your VxWorks image can significantly increase the image size. If you receive a warning from vxsize when building VxWorks, or if the size of your image becomes greater than that supported by the current setting of RAM_HIGH_ADRS, be sure to see 8.6.1 Scaling Down VxWorks and 8.9 Creating Bootable Applications for information on how to resolve the problem.

Configuring the SCSI Bus ID

Each board in a SCSI-2 environment must define a unique SCSI bus ID for the SCSI initiator. SCSI-1 drivers, which support only a single initiator at a time, assume an initiator SCSI bus ID of 7. However, SCSI-2 supports multiple initiators, up to eight initiators and targets at one time. Therefore, to ensure a unique ID, choose a value in the range 0-7 to be passed as a parameter to the driver's initialization routine (for example, ncr710CtrlInitScsi2( )) by the sysScsiInit( ) routine in sysScsi.c. For more information, see the reference entry for the relevant driver initialization routine. If there are multiple boards on one SCSI bus, and all of these boards use the same BSP, then different versions of the BSP must be compiled for each board by assigning unique SCSI bus IDs.

ROM Size Adjustment for SCSI Boot

If INCLUDE_SCSI_BOOT is defined, larger ROMs may be required for some boards. If this is the case, the definition of ROM_SIZE in Makefile and in config.h should be changed to a size that suits the capabilities of the target hardware.

Structure of the SCSI Subsystem

The SCSI subsystem supports libraries and drivers for both SCSI-1 and SCSI-2. It consists of the following six libraries which are independent of any SCSI controller:

scsiLib
routines that provide the mechanism for switching SCSI requests to either the SCSI-1 library (scsi1Lib) or the SCSI-2 library (scsi2Lib), as configured by the board support package (BSP).

scsi1Lib
SCSI-1 library routines and interface, used when only INCLUDE_SCSI is selected for inclusion in the project facility VxWorks view (see Configuring SCSI Drivers.)

scsi2Lib
SCSI-2 library routines and all physical device creation and deletion routines.

scsiCommonLib
commands common to all types of SCSI devices.

scsiDirectLib
routines and commands for direct access devices (disks).

scsiSeqLib
routines and commands for sequential access block devices (tapes).

Controller-independent support for the SCSI-2 functionality is divided into scsi2Lib, scsiCommonLib, scsiDirectLib, and scsiSeqLib. The interface to any of these SCSI-2 libraries can be accessed directly. However, scsiSeqLib is designed to be used in conjunction with tapeFs, while scsiDirectLib works with dosFs, rt11Fs, and rawFs. Applications written for SCSI-1 can be used with SCSI-2; however, SCSI-1 device drivers cannot.

VxWorks targets using SCSI interface controllers require a controller-specific device driver. These device drivers work in conjunction with the controller-independent SCSI libraries, and they provide controller configuration and initialization routines contained in controller-specific libraries. For example, the Western Digital WD33C93 SCSI controller is supported by the device driver libraries wd33c93Lib, wd33c93Lib1, and wd33c93Lib2. Routines tied to SCSI-1 (such as wd33c93CtrlCreate( )) and SCSI-2 (such as wd33c93CtrlCreateScsi2( )) are segregated into separate libraries to simplify configuration. There are also additional support routines for individual targets in sysLib.c.

Booting and Initialization

To boot from a SCSI device, see 4.2.21 Booting from a Local dosFs File System Using SCSI.

After VxWorks is built with SCSI support, the system startup code initializes the SCSI interface by executing sysScsiInit( ) and usrScsiConfig( ) when INCLUDE_SCSI is selected for inclusion in the project facility VxWorks view. The call to sysScsiInit( ) initializes the SCSI controller and sets up interrupt handling. The physical device configuration is specified in usrScsiConfig( ), which is in installDir/target/src/config/usrScsi.c. The routine contains an example of the calling sequence to declare a hypothetical configuration, including:

  • definition of physical devices with scsiPhysDevCreate( )
  • creation of logical partitions with scsiBlkDevCreate( )
  • specification of a file system with either dosFsDevInit( ) or rt11FsDevInit( )

If you are not using SCSI_AUTO_CONFIG, modify usrScsiConfig( ) to reflect your actual configuration. For more information on the calls used in this routine, see the reference entries for scsiPhysDevCreate( ), scsiBlkDevCreate( ), dosFsDevInit( ), rt11FsDevInit( ), dosFsMkfs( ), and rt11FsMkfs( ).

Device-Specific Configuration Options

The SCSI libraries have the following default behaviors enabled:

  • SCSI messages
  • disconnects
  • minimum period and maximum REQ/ACK offset
  • tagged command queuing
  • wide data transfer

Device-specific options do not need to be set if the device shares this default behavior. However, if you need to configure a device that diverges from these default characteristics, use scsiTargetOptionsSet( ) to modify option values. These options are fields in the SCSI_OPTIONS structure, shown below. SCSI_OPTIONS is declared in scsi2Lib.h. You can choose to set some or all of these option values to suit your particular SCSI device and application.

typedef struct                    /* SCSI_OPTIONS - programmable options */ 
    { 
    UINT     selTimeOut;          /* device selection time-out (us)      */ 
    BOOL     messages;            /* FALSE => do not use SCSI messages   */ 
    BOOL     disconnect;          /* FALSE => do not use disconnect      */ 
    UINT8     maxOffset;          /* max sync xfer offset (0 => async.)  */ 
    UINT8     minPeriod;          /* min sync xfer period (x 4 ns)       */ 
    SCSI_TAG_TYPE tagType;        /* default tag type                    */ 
    UINT     maxTags;            /* max cmd tags available (0 => untag   */ 
    UINT8     xferWidth;         /* wide data trnsfr width in SCSI units */ 
    } SCSI_OPTIONS;

There are numerous types of SCSI devices, each supporting its own mix of SCSI-2 features. To set device-specific options, define a SCSI_OPTIONS structure and assign the desired values to the structure's fields. After setting the appropriate fields, call scsiTargetOptionsSet( ) to effect your selections. Example 3-5 illustrates one possible device configuration using SCSI_OPTIONS.

Call scsiTargetOptionsSet( ) after initializing the SCSI subsystem, but before initializing the SCSI physical device. For more information about setting and implementing options, see the reference entry for scsiTargetOptionsSet( ).


*

WARNING: Calling scsiTargetOptionsSet( ) after the physical device has been initialized may lead to undefined behavior.

The SCSI subsystem performs each SCSI command request as a SCSI transaction. This requires the SCSI subsystem to select a device. Different SCSI devices require different amounts of time to respond to a selection; in some cases, the selTimeOut field may need to be altered from the default.

If a device does not support SCSI messages, the boolean field messages can be set to FALSE. Similarly, if a device does not support disconnect/reconnect, the boolean field disconnect can be set to FALSE.

The SCSI subsystem automatically tries to negotiate synchronous data transfer parameters. However, if a SCSI device does not support synchronous data transfer, set the maxOffset field to 0. By default, the SCSI subsystem tries to negotiate the maximum possible REQ/ACK offset and the minimum possible data transfer period supported by the SCSI controller on the VxWorks target. This is done to maximize the speed of transfers between two devices. However, speed depends upon electrical characteristics, like cable length, cable quality, and device termination; therefore, it may be necessary to reduce the values of maxOffset or minPeriod for fast transfers.

The tagType field defines the type of tagged command queuing desired, using one of the following macros:

  • SCSI_TAG_UNTAGGED
  • SCSI_TAG_SIMPLE
  • SCSI_TAG_ORDERED
  • SCSI_TAG_HEAD_OF_QUEUE

For more information about the types of tagged command queuing available, see the ANSI X3T9-I/O Interface Specification Small Computer System Interface (SCSI-2).

The maxTags field sets the maximum number of command tags available for a particular SCSI device.

Wide data transfers with a SCSI target device are automatically negotiated upon initialization by the SCSI subsystem. Wide data transfer parameters are always negotiated before synchronous data transfer parameters, as specified by the SCSI ANSI specification, because a wide negotiation resets any prior negotiation of synchronous parameters. However, if a SCSI device does not support wide parameters and there are problems initializing that device, you must set the xferWidth field to 0. By default, the SCSI subsystem tries to negotiate the maximum possible transfer width supported by the SCSI controller on the VxWorks target in order to maximize the default transfer speed between the two devices. For more information on the actual routine call, see the reference entry for scsiTargetOptionsSet( ).

SCSI Configuration Examples

The following examples show some possible configurations for different SCSI devices. Example 3-4 is a simple block device configuration setup. Example 3-5 involves selecting special options and demonstrates the use of scsiTargetOptionsSet( ). Example 3-6 configures a tape device and a tape file system. Example 3-7 configures a SCSI device for synchronous data transfer. Example 3-8 shows how to configure the SCSI bus ID. These examples can be embedded either in the usrScsiConfig( ) routine or in a user-defined SCSI configuration function.

Example 3-4:  Configuring SCSI Drivers

In the following example, usrScsiConfig( ) was modified to reflect a new system configuration. The new configuration has a SCSI disk with a bus ID of 4 and a Logical Unit Number (LUN) of 0 (zero). The disk is configured with a dosFs file system (with a total size of 0x20000 blocks) and a rawFs file system (spanning the remainder of the disk). The following usrScsiConfig( ) code reflects this modification.

/* configure Winchester at busId = 4, LUN = 0 */ 
 
if ((pSpd40 = scsiPhysDevCreate (pSysScsiCtrl, 4, 0, 0, NONE, 0, 0, 0)) 
        == (SCSI_PHYS_DEV *) NULL) 
    { 
    SCSI_DEBUG_MSG ("usrScsiConfig: scsiPhysDevCreate failed.\n"); 
    } 
else 
    { 
    /* create block devices - one for dosFs and one for rawFs */ 
 
    if (((pSbd0 = scsiBlkDevCreate (pSpd40, 0x20000, 0)) == NULL) || 
        ((pSbd1 = scsiBlkDevCreate (pSpd40, 0, 0x20000)) == NULL)) 
        { 
        return (ERROR); 
        }
/* initialize both dosFs and rawFs file systems */ if ((dosFsDevInit ("/sd0/", pSbd0, NULL) == NULL) || (rawFsDevInit ("/sd1/", pSbd1) == NULL)) { return (ERROR); } }

If problems with your configuration occur, insert the following lines at the beginning of usrScsiConfig( ) to obtain further information on SCSI bus activity.

#if FALSE 
scsiDebug = TRUE; 
scsiIntsDebug = TRUE; 
#endif

Do not declare the global variables scsiDebug and scsiIntsDebug locally. They can be set or reset from the shell; see the Tornado User's Guide: Shell for details.  

Example 3-5:  Configuring a SCSI Disk Drive with Asynchronous Data Transfer and No Tagged Command Queuing

In this example, a SCSI disk device is configured without support for synchronous data transfer and tagged command queuing. The scsiTargetOptionsSet( ) routine is used to turn off these features. The SCSI ID of this disk device is 2, and the LUN is 0:

int              which; 
SCSI_OPTIONS     option; 
int              devBusId; 
 
devBusId = 2; 
which = SCSI_SET_OPT_XFER_PARAMS | SCSI_SET_OPT_TAG_PARAMS; 
option.maxOffset = SCSI_SYNC_XFER_ASYNC_OFFSET;  
                                            /* => 0 defined in scsi2Lib.h */ 
option.minPeriod = SCSI_SYNC_XFER_MIN_PERIOD;  /* defined in scsi2Lib.h */ 
option.tagType = SCSI_TAG_UNTAGGED;      /* defined in scsi2Lib.h */ 
option.maxTag = SCSI_MAX_TAGS; 
 
if (scsiTargetOptionsSet (pSysScsiCtrl, devBusId, &option, which) == ERROR) 
    { 
    SCSI_DEBUG_MSG ("usrScsiConfig: could not set options\n", 0, 0, 0, 0,  
        0, 0); 
    return (ERROR); 
    } 
 
/* configure SCSI disk drive at busId = devBusId, LUN = 0 */ 
 
if ((pSpd20 = scsiPhysDevCreate (pSysScsiCtrl, devBusId, 0, 0, NONE, 0, 0,  
        0)) == (SCSI_PHYS_DEV *) NULL) 
    { 
    SCSI_DEBUG_MSG ("usrScsiConfig: scsiPhysDevCreate failed.\n"); 
    return (ERROR); 
    }

Example 3-6:  Working with Tape Devices

SCSI tape devices can be controlled using common commands from scsiCommonLib and sequential commands from scsiSeqLib. These commands use a pointer to a SCSI sequential device structure, SEQ_DEV, defined in seqIo.h. For more information on controlling SCSI tape devices, see the reference entries for these libraries.

This example configures a SCSI tape device whose bus ID is 5 and whose LUN is 0. It includes commands to create a physical device pointer, set up a sequential device, and initialize a tapeFs device.

/* configure Exabyte 8mm tape drive at busId = 5, LUN = 0 */
if ((pSpd50 = scsiPhysDevCreate (pSysScsiCtrl, 5, 0, 0, NONE, 0, 0, 0)) == (SCSI_PHYS_DEV *) NULL) { SCSI_DEBUG_MSG ("usrScsiConfig: scsiPhysDevCreate failed.\n"); return (ERROR); }
/* configure the sequential device for this physical device */
if ((pSd0 = scsiSeqDevCreate (pSpd50)) == (SEQ_DEV *) NULL) { SCSI_DEBUG_MSG ("usrScsiConfig: scsiSeqDevCreate failed.\n"); return (ERROR); }
/* setup the tape device configuration */
pTapeConfig = (TAPE_CONFIG *) calloc (sizeof (TAPE_CONFIG), 1); pTapeConfig->rewind = TRUE; /* this is a rewind device */ pTapeConfig->blkSize = 512; /* uses 512 byte fixed blocks */
/* initialize a tapeFs device */
if (tapeFsDevInit ("/tape1", pSd0, pTapeConfig) == NULL) { return (ERROR); }
/* rewind the physical device using scsiSeqLib interface directly*/
if (scsiRewind (pSd0) == ERROR) { return (ERROR); }

Example 3-7:  Configuring a SCSI Disk for Synchronous Data Transfer with Non-Default Offset and Period Values

In this example, a SCSI disk drive is configured with support for synchronous data transfer. The offset and period values are user-defined and differ from the driver default values.The chosen period is 25, defined in SCSI units of 4 ns. Thus the period is actually 4 * 25 = 100 ns. The synchronous offset is chosen to be 2. Note that you may need to adjust the values depending on your hardware environment.

int                   which; 
SCSI_OPTIONS          option; 
int                   devBusId;
devBusId = 2;
which = SCSI_SET_IPT_XFER_PARAMS; option.maxOffset = 2; option.minPeriod = 25;
if (scsiTargetOptionsSet (pSysScsiCtrl, devBusId &option, which) == ERROR) { SCSI_DEBUG_MSG ("usrScsiConfig: could not set options\n",  0, 0, 0, 0, 0, 0) return (ERROR); }
/* configure SCSI disk drive at busId = devBusId, LUN = 0 */
if ((pSpd20 = scsiPhysDevCreate (pSysScsiCtrl, devBusId, 0, 0, NONE,   0, 0, 0)) == (SCSI_PHYS_DEV *) NULL) { SCSI_DEBUG_MSG ("usrScsiConfig: scsiPhysDevCreate failed.\n") return (ERROR); }

Example 3-8:  Changing the Bus ID of the SCSI Controller

To change the bus ID of the SCSI controller, modify sysScsiInit( ) in sysScsi.c. Set the SCSI bus ID to a value between 0 and 7 in the call to xxxCtrlInitScsi2( ) (where xxx is the controller name); the default bus ID for the SCSI controller is 7.

Troubleshooting
  • Incompatibilities Between SCSI-1 and SCSI-2
  • Applications written for SCSI-1 may not execute for SCSI-2 because data structures in scsi2Lib.h, such as SCSI_TRANSACTION and SCSI_PHYS_DEV, have changed. This applies only if the application used these structures directly.

    If this is the case, you can choose to configure only the SCSI-1 level of support, or you can modify your application according to the data structures in scsi2Lib.h. In order to set new fields in the modified structure, some applications may simply need to be recompiled, and some applications will have to be modified and then recompiled.

  • SCSI Bus Failure
  • If your SCSI bus hangs, it could be for a variety of reasons. Some of the more common are:

    • Your cable has a defect. This is the most common cause of failure.

    • The cable exceeds the cumulative maximum length of 6 meters specified in the SCSI-2 standard, thus changing the electrical characteristics of the SCSI signals.

    • The bus is not terminated correctly. Consider providing termination power at both ends of the cable, as defined in the SCSI-2 ANSI specification.

    • The minimum transfer period is insufficient or the REQ/ACK offset is too great. Use scsiTargetOptionsSet( ) to set appropriate values for these options.

    • The driver is trying to negotiate wide data transfers on a device that does not support them. In rejecting wide transfers, the device-specific driver cannot handle this phase mismatch. Use scsiTargetOptionsSet( ) to set the appropriate value for the xferWidth field for that particular SCSI device.

    3.7.7   Sockets

    In VxWorks, the underlying basis of network communications is sockets. A socket is an endpoint for communication between tasks; data is sent from one socket to another. Sockets are not created or opened using the standard I/O functions. Instead they are created by calling socket( ), and connected and accessed using other routines in sockLib. However, after a stream socket (using TCP) is created and connected, it can be accessed as a standard I/O device, using read( ), write( ), ioctl( ), and close( ). The value returned by socket( ) as the socket handle is in fact an I/O system fd.

    VxWorks socket routines are source-compatible with the BSD 4.4 UNIX socket functions and the Windows Sockets (Winsock 1.1) networking standard. Use of these routines is discussed in VxWorks Network Programmer's Guide: Networking APIs.


    1:  For the remainder of this section, the term tty is used to indicate both tty and pty devices.

    2:  It will not be possible to restart VxWorks if unhandled external interrupts occur during the boot countdown.