54
Wind River Systems Tornado Device Driver Workshop © Copyright Wind River Systems 4-1 Chapter 4 Writing Character Drivers I/O system interface to a character driver. Driver initialization. Character device driver entry points. Supporting select( ) in a driver.

Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

  • Upload
    others

  • View
    10

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-1

Chapter

4

Writing CharacterDrivers

• I/O system interface to a character driver.

• Driver initialization.

• Character device driver entry points.

• Supporting select( ) in a driver.

Page 2: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-2

Writing Character Drivers

4.1 Introduction

Writing Character Drivers

Development Support Routines

Supporting Select

• Writing an I/O system vs. non-I/O system driver.

• Block vs. character device drivers.

• I/O system interface to driver.

Page 3: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-3

Standard I/O System Interface

• UNIX compatible

• Routines:

● open (filename, flags, mode)

● creat (filename, flags)

● read (fd, &buf, nBytes)

● write (fd, &buf, nBytes)

● ioctl (fd, command, arg)

● close (fd)

● remove (filename)

Page 4: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-4

A Note on delete( )

• The delete entry point is accessed by an application

program calling remove( ).

• The delete entry point is intended to remove files; it is

not used by most drivers.

• Two types of “drivers” use it:

● File systems, e.g. dosFsLib uses it to remove files ona DOS file system

● Network drivers, e.g. netDrv uses it to request that aremote file be removed

• The delete entry is not intended to be used to remove

drivers or devices.

Page 5: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-5

I/O System Overview

Application

ioLib

open() close() read() write() ioctl()creat()

Driver A Driver B Driver C

• The I/O system provides an application some degree of device

independence.

Page 6: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-6

When to Write A Driver With AStandard Interface

• Flexible input/output to multiple devices with the

same interface is needed.

• Stream devices require support.

• Use of I/O redirection. is desired

• An interface familiar to application programmers is

desired.

• Support for select( ) is desired.

• The VxWorks shell calls creat( ), read( ) or write( ), and close( ) when

performing redirection.

• I/O redirection allows tasks to specify input or output sources at run

time. In VxWorks, see ioGlobalStdSet( ) and ioTaskStdSet( ) for details.

Page 7: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-7

When NOT to Write A Driver With AStandard Interface

• Device does not lend itself to I/O system model (not

stream oriented).

• Speed is very critical.

• While there is little overhead in the VxWorks I/O system, there is some

additional code which must be executed.

Page 8: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-8

Drivers Using The Standard Interface

• Block Drivers

● File system-based

● Random access and sequential

● Transfer data in multi-byte blocks

● Examples: floppy or hard disks, ramdisk

• Non-block Drivers

● Any other device

● Examples: serial or graphical input device such asmouse or graphics tablet

Page 9: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-9

Block Devices

• Block devices are designed to support a file system.

• VxWorks-supported file systems:

● MS-DOS

● Raw

● Tape

Page 10: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-10

I/O System Overview

Ap

pli

cati

on

I/O System

opencreatreadwriteioctlclosedelete

Devices

A

B

C

D

Blo

ckD

riv

ers

No

n-B

lock

Dri

ver

s

File Systems

DOS

------

Raw

• For block devices, the I/O system calls file system routines which in

turn make driver calls.

• For non-block devices, the I/O system directly calls driver routines.

Page 11: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-11

Device Reference

• Application references device by file name and file

descriptor

• Device driver references device by device descriptor

and device ID

filename device descriptor

deviceIdfd

Application I/O System Device Driver

• Device drivers typically do not know (or care) about the file name

(device name) or file descriptor.

• The I/O system communicates with the driver via device descriptors

and device IDs (defined by the driver).

Page 12: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-12

Driver Table

Use iosDrvShow( ) to display the driver table.

creat delete open close read write ioctl

0

12 myOpen myOpenNULL myClose myRead myWrite myIoctl

3

Driver Number

• Used by I/O system to access driver entry points

• Fixed in size, but configurable by the NUM_DRIVERS definition in

configAll.h.

• Commonly contains the same routine for both the creat( ) and open( )entry points.

• Normally contains a null entry point for the delete( ) routine .

Page 13: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-13

Device List

Use devs( ) to see list

“/pipe/abc”2

“/pipe/xyz”2

“/tyCo/0”1

“sacto:”4

pipedriverdata

pipedriverdata

netDrvdriverdata

serialdriverdata

• Used by I/O system to match a device name to a driver for open( ),creat( ) and delete( ) — the 3 routines that identify a file by filename (not

file descriptor)

• Doubly linked list of structures

• One structure per device

• Number of entries on list is dynamic

• Multiple device list structures may access the same driver (i.e. a driver

may support multiple devices).

The matching above is done by comparing file name; the access is bydrvNum. Only accessed by I/O system during an open(), creat() andremove().

Page 14: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-14

The Device Descriptor Structure

• Every device has a device descriptor linked to the

device list.

• The first member of the structure is a DEV_HDR.

• The driver-dependent portion contains device specific

information.

DL_NODE

device name

driver #

devicespecific

data

Index into Driver Table

Driver dependent

Driver independentDEV_HDR

• The first member of the device descriptor struct is a DEV_HDR:

typedef struct{DL_NODE node;short drvNum;char * name;} DEV_HDR;

• Typical driver declaration:

#include "iosLib.h"...typedef struct

{DEV_HDR devHdr;/* driver specific information follows */...} XX_DEV;

Page 15: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-15

File Descriptor Table

Use iosFdShow( ) to see table.

3

4

5

6

7

...

Driver # Device ID

Index intoDriver Table

Driverdependent

value

• Used by I/O system to identify driver after a device or file is opened.

• A file descriptor — obtained by a successful open( ) or creat( ) — is an

index into this table.

• Fixed in size, but configurable by the NUM_FILES defininition in

configAll.h.

• The above description is simplified.

Defined in iosLib.c (not the header file!) as a FD_ENTRY, it alsocontains the filename, an inuse flag, and a pointer to the DEV_HDR.

Page 16: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-16

Writing Character Drivers

Introduction

4.2 Writing Character Drivers

Development Support Routines

Supporting Select

• Installing a driver

• Driver entry points

• Removing a driver

Page 17: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-17

Opening A Device

fd = open (“/myDevice”, O_READ, 0)

creat delete open close read write ioctl

0

1

2

myOpen myOpenNULL myClose

myOpen (pDevHdr, NULL, O_READ, 0)

Device List

Driver Table

myRead myWrite myIoctl

• Searches through device list for longest string match of name “/

myDevice”. Let’s say finds a match for “/myDevice”...

• Using the driver number stored in the DEV_HDR of the matching device

descriptor, the I/O system indexes the driver table to call the

appropriate driver xxOpen routine.

• The pDevHdr is a pointer to the matching device descriptor structure.

• Driver xxOpen( ) routine, i.e. myOpen( ), returns a device identifier.

• The sequence above applies as well for creat( ).

Page 18: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-18

Returning from Driver’s xxOpen( )

File Descriptor Table

deviceId = myOpen (pDevHdr, ... )

fd = open (“/myDevice”, O_READ, 0)

deviceIddrivernumber5

file descriptor

• On successful return from driver’s xxOpen:

● I/O system adds driver number and device ID to the file descriptortable:

● Device ID returned from driver’s xxOpen (usually it is pDevHdr, theaddress of the device descriptor)

• Thereafter, fd identifies the device.

• The file descriptor is in index into the file descriptor table (hence,

alleviating the need for searches).

Page 19: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-19

Reading from A Device

creat delete open close read write ioctl

0

1

2

myOpen myOpenNULL myClose

File Descriptor

Driver Table

myRead (devId, &buf, nBytes)

read (fd, &buf, nBytes)

Table

myRead myWrite myIoctl

• he fd, returned from open( ), is used as an index into the File Descriptor

Table.

• The driver number from the File Descriptor Table is used as an index

into the Driver Table, allowing invocation of the driver’s xxRead( )routine.

• The devId is the device ID (stored in the File Descriptor Table) defined by

the return value of the driver’s xxOpen( ).

Page 20: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-20

Writing to A Device

creat delete open close read write ioctl

0

1

2

myOpen myOpenNULL myClose

File Descriptor

Driver Table

myWrite (devId, &buf, nBytes)

write (fd, &buf, nBytes)

Table

myRead myWrite myIoctl

• The mechanism for write (as well as ioctl and close) is identical to read.

Page 21: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-21

I/O System Overview

Application

ioLibopen() close() read() write() ioctl()creat()

iosLibiosDrvInstall()

iosDevAdd()

xxDrvxxDrv() xxDevCreate() xxOpen() xxClose() xxRead() xxWrite() xxIoctl()

Startup Code

• The xxDrv( ) and xxDevCreate( ) driver entry points are not accessed

through ioLib. These routines install the driver and devices into the I/O

system.

• The xxDrv( ) and xxDevCreate( ) routines are normally called during

system startup (often from the usrRoot task).

• The xx in xxDrv denotes the driver handler name, typically the same as

the name prefixing any global variable (including function names), e.g.,

xxDrv( ), xxOpen( ), xxDrvNum.

Page 22: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-22

Device Driver Functions

• xxDrv( )

● Installs driver in driver table -- iosDrvInstall( )● Performs any driver initialization

● Called once and once only

• xxDevCreate( )

● Adds device to the system device list -- iosDevAdd( )● Performs any device initialization

● Called once for each device

• Any of the 6 driver entry points

● These are optional

Driver initialization may include allocating memory andinitialization data structures to default values. Device initializationmay include actually writing to the device.

Page 23: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-23

Initializing A Driver

STATUS xxDrv (args...)

• xx is the driver handler, e.g. pipeDrv or tyCoDrv.

• The arguments are driver dependent.

• Calls iosDrvInstall( ) to add driver to I/O system

driver table.

• Should be called once only.

• Often called from user initialization code.

Page 24: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-24

Adding Driver into Driver Table

iosDrvInstall (xxCreat, xxDelete, xxOpen,xxClose, xxRead, xxWrite, xxIoctl)

• All routines are optional — use NULL if routine not

provided.

• Returns ERROR or driver number on success.

• Example:

fooDrvNum = iosDrvInstall (fooOpen, NULL, fooOpen, fooClose, fooRead, fooWrite, fooIoctl)

• Remember this should only be called once for driver.

• Driver number should be stored in global variable for future reference.

Page 25: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-25

Example xxDrv( ) Routine

1 LOCAL int fooDrvNum;23 STATUS fooDrv (void)4 {5 /* If driver already installed, just return */6 if (fooDrvNum > 0)7 return (OK);89 /* driver initialization, if any, here */1011 /* add driver to driver table */12 if ((fooDrvNum = iosDrvInstall (fooOpen, NULL,13 fooOpen, fooClose, fooRead,

fooWrite,14 fooIoctl)) == ERROR)15 return (ERROR);16 return (OK);17 }

• As shown above, installing a driver open( ) routine in the creat( ) entry

point is a common practice.

Page 26: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-26

Creating an Instance of Device

STATUS xxDevCreate (devName, args...)

• Args are driver dependent.

• Adds the specified device name to the system device list

by calling iosDevAdd( ).

• Performs any device specific initialization.

• Typically, allocates memory for device descriptor

structure.

• If the driver is not installed (xxDrvNum < 1), sets errnoto S_ioLib_NO_DRIVER and returns ERROR.

• The args are used for device-specific information such as board address,

channel number or other identifier.

Page 27: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-27

Adding to the Device List

STATUS iosDevAdd (pDevHdr, devName,drvNum)

pDevHdr Pointer to DEV_HDR

devName Name of device

drvNum Driver number returnedfrom iosDrvInstall( )

• Adds the device descriptor to the device list.

• Initializes the DEV_HDR with the device name and

driver number.

• Fails if devName already exists in the device list.

This routine malloc’s memory to hold devName. It initializes theDEV_HDR with the drvNum and devName and adds it to the linkedlist.

Page 28: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-28

Example Device Creation

1 LOCAL int fooDrvNum; /* initialized in fooDrv()*/...

2 STATUS fooDevCreate (char * devName)3 {4 FOO_DEV * pFooDev;

5 /* Check if driver is installed */6 if (fooDrvNum < 1)7 {8 errno = S_ioLib_NO_DRIVER;9 return (ERROR);10 }

11 /* Allocate and zero device structure */12 if ((pFooDev = (FOO_DEV *) malloc (sizeof (FOO_DEV))) =

= NULL)13 return (ERROR);14 bzero (pFooDev, sizeof (FOO_DEV));

• xxDevCreate( ) may take optional device-specific arguments.

• If you dynamically allocate the device descriptor structure (FOO_DEV),

remember to zero out its contents.

Page 29: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-29

Example (cont‘d)

15 /* Init device specific portion of FOO_DEV here*/

16 /* Perform any device-specific initialization here*/

17 /* Add device to the device list */18 if (iosDevAdd (&pFooDev->devHdr, devName,

fooDrvNum) ==ERROR)

19 {20 free ((char *) pFooDev);21 return (ERROR);22 }23 return (OK);24 }

Page 30: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-30

Driver Open Routine

int xxOpen (pDevHdr, name, flags, mode)

pDevHdr Pointer to device descriptor

name Pointer to device name remainder

flags Flags from open( ): O_RDONLY, etc.

mode Permissions from open( ) — notnormally used in character driver

• Returns ERROR or device identifier, usually pDevHdr.

• Initializes the specific channel, if appropriate.

• Optionally, fails multiple attempts to open the same

device.

• Name is a pointer to the characters remaining after the device name —

specified in the xxDevCreate( ). For example, if the device was create

with

xx DevCreate ("/myDev",...)

and opened withfd = open ("/myDev/4", 0)

then name would be a pointer to “/4”. For most drivers, this will be anull pointer.

• If return value from xxOpen( ) is ERROR, then the open has failed and

nothing is added to the file descriptor table.

The file descriptor table holds a pointer to the DEV_HDR, pointer to filename,an “inuse” flag, and a “value”. The value holds the driver’s return fromxxOpen(). This value is the first argument passed to read, write, ioctl, andclose. The inuse flag is a BOOL to indicate whether this is a valid entry, likezeroing the inode number in a UNIX directory.

Page 31: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-31

Return Value from xxOpen()

• ERROR to cause application open to fail.

• Pointer to the device descriptor, when information is

maintained only by device.

• A driver-specific identifier, typically a pointer to a

private driver structure.

• To confirm that the return value from xxOpen( ) is being saved in file

descriptor table, use iosFdValue( ).

If a driver specific structure is chosen, there are two choices: 1. mallocmemory as needed, this is good in that it does not limit the number ofopen’s, bad in that if many open/closes are made, memory willbecome fragmented. 2. Declare a fixed sized array of structures, this isgood because it avoids the memory fragmentation problem, bad inthat if the number of open’s are limited and if structure is large orarray large then memory is wasted. This approach is also slightlyfaster.

Page 32: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-32

Example

1 typedef struct2 {3 MY_DEV * pMyDev;4 int offset;5 } MY_DEV_PER_FD:

...6 int myOpen (DEV_HDR * pDevHdr, char * name, int

flags)7 ...8 if ((pMyDevPerFd = (MY_DEV_PER_FD *) malloc

(sizeof9 (MY_DEV_PER_FD)) == NULL)10 return (ERROR);11 pMyDevPerFd->pMyDev = (MY_DEV *) pDevHdr;12 pMyDevPerFd->offset = 0;13 return ((int) pMyDevPerFd);14 }

• Consequences of using the code above:

● Must supply a myClose( ) to free memory allocated in myOpen( ).● To maintain current device offset, driver would have to modify offset

on each myRead( ), myWrite( ), and myIoctl( ), if an FIOSEEKcommand is implemented.

● Remember that the first parameter to each I/O call will now be apointer to your MY_DEV_PER_FD structure and not to MY_DEV:

int myRead (int deviceId, char * buf, int nBytes){MY_DEV_PER_FD *pMyDevPerFd = (MY_DEV_PER_FD *)

deviceId;MY_DEV * pMyDev = pMyDevPerFd->pMyDev;...

Page 33: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-33

Read/Write Routine

int xxWrite (deviceId, pBuf, nBytes)

int xxRead (deviceId, pBuf, nBytes)

deviceId Value returned from driver xxOpen()

pBuf Pointer to buffer to read or write

nBytes The number of bytes to read or write

• These routines should return:

● the number of bytes successfully read or written, or● ERROR on failure, or● zero to indicate end-of-file or end-of-device (if meaningful)

Page 34: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-34

Ioctl Routine

int xxIoctl (deviceId, cmd, arg)

deviceId Value returned from driver xxOpen()

cmd Action to perform

arg Optional cmd-specific int, often usedas a pointer

• Return value is cmd specific, except that ERROR is

reserved to indicate failure.

• Unknown commands should be failed and errno set to

S_ioLib_UNKNOWN_REQUEST.

• The cmd‘s are usually defined in a header file used by the driver and the

application program.

• The I/O system itself handles the FIOGETNAME command which copies

the filename associated with file descriptor to arg.

• Include ioLib.h.

Page 35: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-35

Ioctl Arguments

• Arg may be defined as:

● an integer value

● an address to input data

● an address to output data

● not used

• When arg is used as an address, it is often an address of

a structure.

Page 36: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-36

Ioctl Example

1 LOCAL FOO_STATE fooState;2 LOCAL int fooSpeed;3 LOCAL SEM_ID fooSem;4 ...5 int fooIoctl (int fooDevId, int cmd, int arg)6 {7 int status;89 switch (cmd)10 {11 case FOO_SPEED_SET:12 fooSpeed = arg;13 status = OK;14 break;15 case FOO_SPEED_GET:16 if (arg)17 *(int *)arg = fooSpeed;18 status = fooSpeed;19 break;

• Example demonstrates

● Passing an int (FOO_SPEED_SET) to a driver

● Returning an int (FOO_SPEED_GET) from a driver

● Passing the contents of a structure (FOO_STATE_SET) to a driver

● Returning the contents of a structure (FOO_STATE_GET) from a driver

• Line 16-17: For demonstration purposes, these lines show how fooSpeedmay be either returned or stored at the address of arg. Normally, a driver

passes fooSpeed back one way or the other (not both ways as shown).

This assumes that fooSpeed can not have a value of -1 (ERROR). The test

(line 16) for non-zero arg is precautionary.

Page 37: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-37

Ioctl Example (cont’d)

20 case FOO_STATE_SET:21 semTake (fooSem, WAIT_FOREVER);22 fooState = * (FOO_STATE *) arg;23 semGive (fooSem);24 status = OK;25 break;26 case FOO_STATE_GET:27 semTake (fooSem, WAIT_FOREVER);28 * (FOO_STATE *) arg = fooState;29 semGive (fooSem);30 status = OK;31 break;32 default:33 errno = S_ioLib_UNKNOWN_REQUEST;34 status = ERROR;35 }36 return (status);37 }

• In this example, the use of arg is cmd dependent:

FOO_SPEED_SET int

FOO_SPEED_GET Pointer to an int

FOO_STATE_SET Pointer to a structure

FOO_STATE_GET Pointer to a structure

• Since assignment of structures is non-atomic, the FOO_STATE_SET and

FOO_STATE_GET commands are protected by a mutex semaphore.

Page 38: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-38

The xxClose Routine

STATUS xxClose (devId)

• If driver is managing a private structure referenced by

devId, perform any reset action if necessary.

• Free memory allocated in your xxOpen( ), if any.

• Most drivers do not have a close routine.

Page 39: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-39

Writing Character Drivers

Introduction

Writing Character Drivers

4.3 Development Support Routines

Supporting Select

• Routines that may be useful for developing and debugging character

drivers.

Page 40: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-40

Deleting a Device

void iosDevDelete (pDevHdr)

• Removes the device descriptor addressed by pDevHdrfrom the device list.

• Inverse of iosDevAdd( ).

• Prevents any new opens on the device.

• Any file descriptors already opened remain unaffected

(as long as the device descriptor itself is not freed or

modified).

Page 41: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-41

Removing a Driver

iosDrvRemove (drvNum, forceClose)

• Removes driver from driver table and deletes any

associated devices from the device list.

• If forceClose is TRUE, closes all open files associated with

driver.

• If forceClose is FALSE, returns ERROR if any files are open.

• If forceClose is TRUE and driver has an xxClose( ) routine, routine will be

called for each open file.

• This routine does not free memory allocated for a device list structure.

Page 42: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-42

Getting A Device Descriptor

DEV_HDR * iosDevFind (name, pNameTail)

name Device namepNameTail Pointer to string of name

remainder

• Returns a pointer to the DEV_HDR associated with nameor, if not found, to the default device, or NULL if no

default device defined.

• Routine initializes pNameTail with a pointer to the part

of name which was not matched with the device name.

• Sometimes useful in debugging or removing a device.

• If pNameTail points to a null character, the match was exact.

• If pNameTail points to name, there was no match.

Page 43: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-43

Example Remove Device Routine

1 #include "vxWorks.h"2 #include "iosLib.h"34 STATUS rmDev (char * devName)5 {6 DEV_HDR *pDevHdr;7 char * pNameTail;89 pDevHdr = iosDevFind (devName, &pNameTail);1011 if (pDevHdr == NULL || *pNameTail != ’\0’)12 return (ERROR);1314 iosDevDelete (pDevHdr);15 return (OK);16 }

• Important limitations in above routine:

● Does not free the device descriptor● If the device descriptors are dynamically allocated in the

xxDevCreate( ) routine, using this routine alone would create amemory leak

● Does not close files — there may still be open file descriptorsreferencing this device

● It would be safe to free the device descriptor only after all referencingfile descriptors were closed

● The device descriptor itself may reference resources which would notbe freed, e.g. semaphores, message queues, or private buffers

Page 44: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-44

File Descriptor to Device IDConversion

int iosFdValue (fd)

• Returns the Device ID (return value from driver’s

xxOpen) for the device associated with the file

descriptor fd.

• Returns ERROR if fd is invalid.

Page 45: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-45

Writing Character Drivers

Introduction

Writing Character Drivers

Development Support Routines

4.4 Supporting Select

• Select initialization

• Supporting select’s ioctl commands

• Notifying select when device has data to read or is ready to write

Page 46: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-46

Supporting select( )

• The select( ) call permits tasks to pend on multiple file

descriptors.

• Task can block until data is available, or device can be

written to.

• Allows for pending with a timeout.

• Supporting select( ) is optional.

• Appropriate only for I/O system character drivers.

Page 47: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-47

Select() Tools

• Select uses a struct fd_set which may be viewed as an

array of bits:

• Each bit represents a file descriptor of interest.

• Macros to help manipulate a struct fd_set:

FD_SET (fd, &fdset) Sets the fd bit in fdset

FD_CLR (fd, &fdset) Clears the fd bit in fdset

FD_ZERO (&fdset) Clears all bits in fdset

FD_ISSET (fd, &fdset) Tests if the fd bit is set in fdset

891011121314... 01234567

Page 48: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-48

Using select( )

int select (width, pReadFds, pWriteFds,pExceptFds, pTimeOut)

width Number of bits to examine in the structfd_set’s below

pReadFds Pointer to a struct fd_set which holdsthe read file descriptors of interest

pWriteFds Pointer to a struct fd_set which holdsthe write file descriptors of interest

pExceptFds Pointer to a struct fd_set which holdsthe exception file descriptors of interest— not implemented

pTimeOut Pointer to a struct timeval, NULL implieswait forever

• The fd_set holds a bit per file descriptor, i.e. file descriptor 0 is bit 0, file

descriptor 1 is bit 1 and so forth.

• Returns number of fds that are ready, zero on time out, or ERROR (e.g. ifdriver does not support select).

• On return, select has modified the struct fd_set so that only those bitscorresponding to the file descriptors which meet the requestedcondition are set.

• The selectLib is UNIX BSD 4.3 compatible. VxWorks namingconventions are violated to maintain compatibility.

Page 49: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-49

Select Example

1 struct fd_set readFds;2 int fds[NUM_FDS], width = 0;

...3 FD_ZERO (&readFds);4 for (i=0; i<NUM_FDS; i++)5 {6 FD_SET (fds[i], &readFds);7 width = (fds[i] > width) ? fds[i] : width;8 }9 width++;10 if (select(width, &readFds,NULL,NULL,NULL) == ERROR)11 return (ERROR);12 for (i=0; i<NUM_FDS; i++)13 {14 if (FD_ISSET (fds[i], &readFds))15 {16 /* do something now that fds[i] is ready */17 }18 }

• When select( ) returns, the struct fd_set has been modified so that only

the bits corresponding to the file descriptors that are ready are set.

• If a read, write, or exception argument is NULL, that argument is

ignored.

• Must include selectLib.h.

Page 50: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-50

Select Overview

xxDevCreate( )

selWakeupListInit( )

select( )

xxIoctl (...,FIOSELECT,...)

selNodeAdd( )

selWakeup( )

xxIoctl (...,FIOUNSELECT,...)

selNodeDelete( )

selWakeupAll (...,SELWRITE)

selWakeupAll (...,SELREAD)

Ap

plic

atio

n

ready to write

data to read

selectLib Driver

Page 51: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-51

Select Initialization

• Driver must declare a SEL_WAKEUP_LIST structure,

typically in the device descriptor structure.

• xxDevCreate( ) must call:

selWakeupListInit (pWakeupList)SEL_WAKEUP_LIST * pWakeupList;

• When device becomes available for writes, call:

selWakeupAll (pWakeupList, SELWRITE);

• When device obtains data for reads, call:

selWakeupAll (pWakeupList, SELREAD);

• The SEL_WAKEUP_LIST structure is usually declared as part of the device

descriptor structure:

typedef struct{DEV_HDR devHdr;...SEL_WAKEUP_LIST selWakeupList;...} FOO_DEV;...STATUS fooDevCreate (...)

{...pFooDev = (FOO_DEV *) malloc (sizeof (FOO_DEV));selWakeupListInit (&pFooDev->selWakeupList);...}

• The selWakeupAll( ) routine may be called at interrupt time.

Page 52: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-52

Select Commands in ioctl

• Command FIOSELECT

selNodeAdd (pSelWakeupList, (SEL_WAKEUP_NODE *)arg);if ((selWakeupType ((SEL_WAKEUP_NODE *) arg) ==

SELREAD) && thereIsDataToRead )selWakeup ((SEL_WAKEUP_NODE *) arg);

if ((selWakeupType ((SEL_WAKEUP_NODE *) arg) == SELWRITE) && deviceCanBeWrittenTo )selWakeup ((SEL_WAKEUP_NODE *) arg);

• Command FIOUNSELECT

selNodeDelete (pSelWakeupList, (SEL_WAKEUP_NODE *)arg);

• In FIOSELECT code, thereIsDataToRead and deviceCanBeWrittenTo must be

replaced with appropriate device-dependent code.

• Example:

int fooIoctl (int deviceId, int cmd, int arg){FOO_DEV * pFooDev = (FOO_DEV *) deviceId;

switch (cmd){

case FIOSELECT:selNodeAdd (&pFooDev->selWakeupList,

(SEL_WAKEUP_NODE *) arg);...

}}

Page 53: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-53

Summary

• xxDrv( ) — called once per driver

● call iosDrvInstall( )● return STATUS

• xxDevCreate( ) — called once per device

● allocate and initialize a device descriptor structure● call iosDevAdd( )● return STATUS

Page 54: Writing Character Drivers - pudn.comread.pudn.com/downloads124/ebook/526229/ddCharDrv_4.f.pdf · Writing Character Drivers 4.1 Introduction Writing Character Drivers Development Support

Wind River SystemsTornado Device Driver Workshop © Copyright Wind River Systems 4-54

Summary

• xxOpen( )

● initialize any per-open structure● return device ID or ERROR on failure

• xxClose( )

● reset any per open structure● free any memory allocated during xxOpen( )

• xxRead( ) / xxWrite( )

• xxIoctl( )

● process known commands● fail unknown commands