TOC PREV NEXT INDEX

Put your logo here!


PART II · USER MANUAL

4 THE LCU DRIVER COMMON MODULES - lcudrv and lculog

4.1 lcudrv - Driver Common Functions

This chapter describes the LCU part of the module in its version 1.17.

It shall provide a general description of the functions contained in this module. For detailed parameters etc. see section 4.6, examples are given in section 3.3.

A Driver Channel Table (DCT) is used to keep track of the channels opened to the devices controlled by the driver. By means of this table the other routines can check if a specific channel has been opened and if the open-mode allows access to a device through that channel. The index into the DCT is used to distinguish between channels opened to a device at the same time. It is therefore similar to a file-descriptor inside the driver. See section 2.5 also.

A mode-specifier defining the access rights must be given when opening a channel to a device:

· lcudrvOPEN_READONLY
Read only mode.
· lcudrvOPEN_SHARED
Shareable read and write mode. Write access is granted to a defined number of processes to use this open mode. Exceeding this number or requesting this mode for a device already opened in Exclusive write mode returns an error.
· lcudrvOPEN_EXCLUSIVE
Exclusive read and write mode. Write access is granted to the process using this open mode. Requesting this mode for a device already opened in Exclusive or Shareable write mode returns an error.
· lcudrvOPEN_TEST
Test read and write mode. Write access is granted to the process using this open mode regardless of the status of the device. Requesting this mode for a device already opened in Test mode returns an error.

The common lcudrvInitDCT routine should be called from the driver specific xxxDrv function (see section 3.3.1). It performs the following actions:

· allocates memory from the pool to build a Driver Channel Table (DCT) for the given size
· initializes the DCT

The routine returns lcudrvOK if successful or a negative error code if there is no memory available.

Several inline-functions are provided in the include-file lcudrvCheckDev.h, which should be used in the device-install function xxxDevCreate as shown in section 3.3.2 (simply to avoid duplication of code). All function return lcudrvOK on success or the appropriate lcudrv error-code:

· lcudrvCheckDevDriver - checks if a driver is installed for that device.
· lcudrvCheckDevName - checks the device-name and returns the unit number.
· lcudrvCheckDevBaseAddrA16 - converts a VMEbus-address in the short address space into a local address as seen from the CPU.
· lcudrvCheckDevBaseAddrA24 - converts a VMEbus-address in the standard address space into a local address as seen from the CPU.
· lcudrvCheckDevProbe - checks if the given address is valid.
· lcudrvCheckDevReturnOK - logs that device installation is OK and always returns lcudrvOK.

The common lcudrvInitDevice routine should be called from the driver specific xxxDevCreate function (see section 3.3.2). It performs the following actions:

· adds the device to the VxWorks system tables by calling iosDevAdd
· initializes the lcudrv-specific parts of the Device Descriptor (see section 4.2)

The routine returns lcudrvOK if successful or a negative error code if the device already exists.

The common lcudrvOpen routine should be called from the driver specific xxxOpen function (see section 3.3.3). It performs the following actions:

· checks device name remainder (should be blank)
· looks for a free DCT slot
· checks the open mode
· inserts the new channel in the DCT
· updates the device access mode in the Device Descriptor
· returns the channel number, which is used in subsequent I/O calls to identify the channel

The routine returns in a provided ststus variable lcudrvOK if successful or a negative error code if any problem occured.

The common lcudrvClose routine should be called from the driver specific xxxClose function (see section 3.3.4). It performs the following actions:

· checks the passed channel number
· updates the device access mode in the Device Descriptor
· frees the corresponding DCT slot

The routine returns lcudrvOK if successful or a negative error code if any problem occured.

The common lcudrvCheckAccess routine should be called from the driver specific xxxIoctl function (see section 3.3.5). It performs the following actions:

· checks the passed channel number against the limits defined at driver installation
· checks the entry in the DCT to make sure that the channel has been opened
· checks the passed access rights against the mode with which this channel has been opened

lcudrvCheckChannel can be used instead, if an access rights check is not required. The routine returns lcudrvOK if successful or a negative error code if any problem occured.

The lcudrvProbeAddress routine is a tool-function which checks whether a device exists at the specified address or not. The routine returns lcudrvOK if the address exists or lcudrvERROR if not. It should be called from xxxDevCreate to make sure that a device is actually present.

The lcudrvPrintError routine is a tool-function which prints an error-message for the corresponding error-number to the standard output. The lcudrvErrorGet function returns a pointer to the same error-description string.

The macros defined in lcudrvDevice.h can be used to access hardware registers directly. They use assembler directives, what normally - but not necessarily - results in more efficient code. At present the macros are supported only for GNU-gcc and the 68000 CPU family!

· For bit manipulation in memory: lcudrvBCHG, lcudrvBCLR, lcudrvBSET, lcudrvBTST
· For memory read access: lcudrvGETB, lcudrvGETW, lcudrvGETL
· For memory write access: lcudrvPUTB, lcudrvPUTW, lcudrvPUTL

4.2 The Device Descriptor Table

The Device Descriptor usually consists of three parts:

· The general part required by VxWorks
· The part used by the functions of lcudrv
· The optional driver-specific part

The declaration of a Device Descriptor structure should therefore include the lcudrvDEVICE_HEADER as first item, appended by as much further data as required by a device, for instance:

/*
* Device Descriptor
*/
typedef struct xxxDEVICE_DESCRIPTOR
{
lcudrvDEVICE_HEADER header; /* standard header (must be on top!) */

/* installation parameters: */
void *baseAddrA24; /* standard VMEbus base-address */
void *baseAddrA16; /* short VMEbus base-address */
int intrNumber; /* interrupt-vector-number */
int intrLevel; /* interrupt-level */

/* derived/computed values: */
void *dpramAddr; /* board DPRAM base address */
SEM_ID semAccess; /* access protection mutex-semaphore */
WDOG_ID wd; /* timeout watchdog */
} xxxDEVICE_DESCRIPTOR;

This declaration should be included in the header file xxxPrivate.h. The memory allocation of the whole Device Descriptor Table of a driver should be done in xxxDrv. The device-specific initialization should be done in xxxDevCreate. In doing so, the function lcudrvInitDevice can be used for the initialization of the lcudrv-specific part.

4.3 The Command Descriptor Table

This table is optional. It could be used inside xxxIoctl (see section 3.3.5) to determine which handler-routine shall be invoked to execute a requested command-code etc.

To achieve this, the table should contain:

· The command code
· The access rights for this command, which have to be checked by xxxIoctl,
e.g. the value (lcudrvOPEN_SHARED | lcudrvOPEN_EXCLUSIVE) would reject accesses in the modes Read-Only and Test (see section 4.1 for information about open-modes).
· If semaphore protection is necessary for this command (only commands without any write-accesses are allowed to execute without semaphore-protection!)
· The assigned handler routine

The corresponding example is:

/*
* Command Descriptor Table
*/
typedef const struct xxxCMD_DESCRIPTOR
{
int code; /* Cmd passed to controller */
int access; /* Access rights of the command */
BOOL protected; /* For exclusive access to the board */
/* Device layer routine executing the command: */
int (*handler)(const xxxDEVICE_DESCRIPTOR *devPtr, void *argPtr);
} xxxCMD_DESCRIPTOR;

This declaration should be included in the header file xxxPrivate.h. The memory allocation and initialization of the whole Command Descriptor Table of a driver should be done in xxxDrv.c.

4.4 lculog - Driver Common Logging Functions

This chapter describes the module in its version 1.9.

It shall provide a general description of the functions contained in this module. For detailed parameters etc. see section 4.6.

Several logging calls are available which are very similar to the normal VxWorks logMsg function, i.e. they take the same parameters and they can be used from interrupt level. The additional features are severity-specific logging and - if necessary - message handling by a special lculog-Task.

Corresponding to the message-severity the following calls should be used:1

· LCU_LOG_error - for severe errors when a function cannot be continued
· LCU_LOG_warning - for critical conditions which may cause malfunctions
· LCU_LOG_log - for normal informational messages
· LCU_LOG_trace - for messages which traces the flow of a task (can be turned off)
· LCU_LOG_debug - for output of debugging information (can be turned off)
· LCU_LOG_intr - dto. inside periodic interrupt handlers (can be turned off)

These calls are normally implemented as macros. This requires that the first parameter (the format string) must be a constant string, not a variable!

If this is too restrictive then macro-expansion can be inhibited, which means that normal function-calls are used instead (with more function-call overhead). This can be requested by:

#define lculogOPTION_NO_MACROS
#include "lculog.h"

Passing of pointers to volatile entities must be avoided, only pointers to static data (constant strings etc.) are allowed. The following example shows an allowed construction with two constant strings and an integer as parameters for LCU_LOG_error:

#define FNAME "xxxDevCreate"
int error = 99;
LCU_LOG_error("%s: error condition (%d)", (int)FNAME, error, 0, 0, 0, 0);

Output => "ERROR: xxxDevCreate: error condition (99)\n"

There are also preprocessor options to exclude logging calls completely from the compilation, for example to omit debugging-logs in the final version of a driver.

All log messages are handled by the normal VxWorks logging task, except when the routine lculogTask has been spawned as a task, in which case all messages are processed by this function instead.

All LCU logging outputs can be turned off by setting the variable lculogDisable to TRUE (1). This applies to all message-severities!

4.5 Errors Reference

See section 7.1 in the Reference chapter.

4.6 Functions Reference

See section 7.2 in the Reference chapter.

1
The prefix LCU_LOG (rather than lculog) is used for historical reasons.



Quadralay Corporation
http://www.webworks.com
Voice: (512) 719-3399
Fax: (512) 719-3606
sales@webworks.com
TOC PREV NEXT INDEX