02.03.2014 Views

BSP Developer's Guide

BSP Developer's Guide

BSP Developer's Guide

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

VxWorks®<br />

5.5<br />

<strong>BSP</strong> DEVELOPER’S GUIDE


Copyright © 2002 Wind River Systems, Inc.<br />

ALL RIGHTS RESERVED. No part of this publication may be copied in any form, by photocopy,<br />

microfilm, retrieval system, or by any other means now known or hereafter invented without the prior<br />

written permission of Wind River Systems, Inc.<br />

AutoCode, Embedded Internet, Epilogue, ESp, FastJ, IxWorks, MATRIX X , pRISM, pRISM+, pSOS,<br />

RouterWare, Tornado, VxWorks, wind, WindNavigator, Wind River Systems, WinRouter, and Xmath are<br />

registered trademarks or service marks of Wind River Systems, Inc. or its subsidiaries.<br />

Attaché Plus, BetterState, Doctor Design, Embedded Desktop, Emissary, Envoy, How Smart Things Think,<br />

HTMLWorks, MotorWorks, OSEKWorks, Personal JWorks, pSOS+, pSOSim, pSOSystem, SingleStep,<br />

SNiFF+, VSPWorks, VxDCOM, VxFusion, VxMP, VxSim, VxVMI, Wind Foundation Classes, WindC++,<br />

WindManage, WindNet, Wind River, WindSurf, and WindView are trademarks or service marks of Wind<br />

River Systems, Inc. or its subsidiaries. This is a partial list. For a complete list of Wind River trademarks<br />

and service marks, see the following URL:<br />

http://www.windriver.com/corporate/html/trademark.html<br />

Use of the above marks without the express written permission of Wind River Systems, Inc. is prohibited.<br />

All other trademarks, registered trademarks, or service marks mentioned herein are the property of their<br />

respective owners.<br />

Corporate Headquarters<br />

Wind River Systems, Inc.<br />

500 Wind River Way<br />

Alameda, CA 94501-1153<br />

U.S.A.<br />

toll free (U.S.): 800/545-WIND<br />

telephone: 510/748-4100<br />

facsimile: 510/749-2010<br />

For additional contact information, please visit the Wind River URL:<br />

http://www.windriver.com<br />

For information on how to contact Customer Support, please visit the following URL:<br />

http://www.windriver.com/support<br />

VxWorks <strong>BSP</strong> Developer’s <strong>Guide</strong>, 5.5<br />

9 Aug 02<br />

Part #: DOC-14695-ND-00


1 Overview .................................................................................................................. 1<br />

2 <strong>BSP</strong> Organization ................................................................................................. 11<br />

3 Creating a New <strong>BSP</strong> ............................................................................................. 41<br />

4 Hardware <strong>Guide</strong>lines ............................................................................................ 63<br />

5 Driver <strong>Guide</strong>lines .................................................................................................. 89<br />

6 Components ........................................................................................................ 111<br />

7 Validation Testing ............................................................................................... 139<br />

8 Writing Portable C Code .................................................................................... 159<br />

9 Documentation <strong>Guide</strong>lines ................................................................................ 173<br />

10 Product Packaging ............................................................................................. 195<br />

A Upgrading a <strong>BSP</strong> for Tornado 2.0 ..................................................................... 203<br />

B Upgrading a <strong>BSP</strong> for Tornado 2.2 ..................................................................... 211<br />

C Upgrading a <strong>BSP</strong> for the VxWorks Network Stack .......................................... 221<br />

D VxWorks Boot Sequence ................................................................................... 223<br />

E Component Language ........................................................................................ 231<br />

F Generic Drivers ................................................................................................... 247<br />

G Upgrading 4.3 BSD Network Drivers ................................................................. 257<br />

H Implementing a MUX-Based Network Interface Driver .................................... 267<br />

I Writing a SCSI-2 Device Driver .......................................................................... 317<br />

iii


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

J <strong>BSP</strong> Validation Test Suite Reference Entries ......................................................... 365<br />

K <strong>BSP</strong> Validation Checklists ....................................................................................... 401<br />

L Refgen ....................................................................................................................... 415<br />

M <strong>BSP</strong> Product Contents ............................................................................................. 423<br />

Index .......................................................................................................................... 427<br />

iv


Contents<br />

1 Overview ................................................................................................................... 1<br />

1.1 Introduction ...................................................................................................... 1<br />

New Features for Tornado 2.x .......................................................... 2<br />

Prerequisites ........................................................................................ 4<br />

<strong>BSP</strong> Kit Components ......................................................................... 4<br />

Documentation ................................................................................... 5<br />

Documentation Conventions ........................................................... 7<br />

2 <strong>BSP</strong> Organization ..................................................................................................... 11<br />

2.1 Introduction ...................................................................................................... 11<br />

2.2 <strong>BSP</strong> Components .............................................................................................. 11<br />

2.2.1 <strong>BSP</strong> Source and Include Files ........................................................... 12<br />

Files in the target/config/all Directory .......................................... 13<br />

Files in the target/config/comps/vxWorks Directory ................. 14<br />

Files in the target/config/comps/src Directory ........................... 14<br />

Files in the target/config/bspname Directory .............................. 15<br />

2.2.2 Derived Files ....................................................................................... 28<br />

2.2.3 Required Routines ............................................................................. 30<br />

2.2.4 Optional Routines .............................................................................. 31<br />

v


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

2.3 VxWorks Boot Sequence ................................................................................. 32<br />

2.3.1 Processor Variances ........................................................................... 32<br />

2.3.2 Sequence Overview ........................................................................... 33<br />

2.3.3 Files and Routines ............................................................................. 33<br />

2.4 Mistakes To Be Avoided .................................................................................. 38<br />

3 Creating a New <strong>BSP</strong> ................................................................................................. 41<br />

3.1 Introduction ...................................................................................................... 41<br />

3.2 Setting Up Your Development Environment ............................................... 43<br />

3.3 Writing the <strong>BSP</strong> Pre-Kernel Initialization Code .......................................... 44<br />

3.3.1 Writing the <strong>BSP</strong> Files ......................................................................... 44<br />

3.3.2 Building and Downloading VxWorks ............................................ 49<br />

3.3.3 Debugging the Initialization Code .................................................. 50<br />

ROM Initialization ............................................................................. 50<br />

RAM Initialization ............................................................................. 51<br />

Generic Initialization ......................................................................... 52<br />

3.3.4 Starting the WDB Agent Before the Kernel ................................... 53<br />

3.4 Using a Minimal Kernel .................................................................................. 55<br />

3.4.1 ISR <strong>Guide</strong>lines .................................................................................... 55<br />

3.4.2 Required Drivers ............................................................................... 56<br />

3.4.3 Serial Drivers ...................................................................................... 56<br />

3.5 The Target Agent and Tornado ...................................................................... 57<br />

3.6 Finishing the Port ............................................................................................. 57<br />

3.6.1 Cleanup ............................................................................................... 58<br />

3.6.2 NVRAM .............................................................................................. 58<br />

3.6.3 Adding Other Timers ........................................................................ 58<br />

3.6.4 Network .............................................................................................. 58<br />

vi


Contents<br />

3.6.5 Cache, MMU, and DMA Devices .................................................... 60<br />

3.6.6 Boot ROMs .......................................................................................... 60<br />

3.6.7 SCSI ...................................................................................................... 61<br />

3.6.8 Projects ................................................................................................. 61<br />

4 Hardware <strong>Guide</strong>lines ................................................................................................ 63<br />

4.1 Introduction ...................................................................................................... 63<br />

4.2 Architectural Considerations .......................................................................... 64<br />

4.2.1 Interrupt Handling ............................................................................ 64<br />

4.2.2 Cache Issues ........................................................................................ 65<br />

4.2.3 MMU Support .................................................................................... 66<br />

4.2.4 Floating-Point Support ...................................................................... 66<br />

4.2.5 Other Issues ........................................................................................ 67<br />

4.3 Memory .............................................................................................................. 67<br />

4.3.1 RAM ..................................................................................................... 68<br />

4.3.2 ROM ..................................................................................................... 68<br />

4.3.3 Ethernet RAM ..................................................................................... 68<br />

4.3.4 NVRAM ............................................................................................... 69<br />

4.3.5 Parity Checking .................................................................................. 69<br />

4.3.6 Addressing .......................................................................................... 69<br />

4.3.7 Bus ........................................................................................................ 70<br />

VMEbus ............................................................................................... 70<br />

Multibus II ........................................................................................... 74<br />

PCI, cPCI, and PMC ........................................................................... 76<br />

Busless ................................................................................................. 76<br />

4.4 Devices ............................................................................................................... 76<br />

4.4.1 Interrupts ............................................................................................. 77<br />

4.4.2 System Clock ...................................................................................... 79<br />

vii


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

4.4.3 Auxiliary Clock .................................................................................. 79<br />

4.4.4 Timestamp Clocks ............................................................................. 79<br />

4.4.5 Serial Ports .......................................................................................... 79<br />

4.4.6 Ethernet Controllers .......................................................................... 80<br />

4.4.7 SCSI Controllers ................................................................................. 81<br />

4.4.8 DMA Controllers ............................................................................... 82<br />

4.4.9 Reset Button ........................................................................................ 82<br />

4.4.10 Abort Button ....................................................................................... 82<br />

4.4.11 DIP Switches ....................................................................................... 82<br />

4.4.12 User LEDs ........................................................................................... 82<br />

4.4.13 Parallel Ports ...................................................................................... 83<br />

4.5 Enabling the Virtual Memory Library .......................................................... 83<br />

4.5.1 Changes to sysLib.c ........................................................................... 83<br />

4.5.2 Changes to config.h ........................................................................... 85<br />

4.5.3 Additional Requirements for SPARC Targets ................................ 85<br />

Sun-4 MMU ........................................................................................ 85<br />

SPARC Reference MMU ................................................................... 86<br />

5 Driver <strong>Guide</strong>lines ...................................................................................................... 89<br />

5.1 Introduction ...................................................................................................... 89<br />

5.2 Design Goals ..................................................................................................... 90<br />

Designing for Performance .............................................................. 90<br />

Code Flexibility/Portability ............................................................. 90<br />

Maintenance and Readability .......................................................... 91<br />

Ease of Configuration ....................................................................... 91<br />

Performance Testing .......................................................................... 91<br />

Code Size ............................................................................................ 91<br />

Reentrancy .......................................................................................... 91<br />

5.3 Design Problems .............................................................................................. 92<br />

Hardware Designs of All Types ....................................................... 92<br />

viii


Contents<br />

Memory-Mapped Chips ................................................................... 92<br />

I/O-Mapped Chips ............................................................................ 93<br />

Multi-Function Chips ........................................................................ 93<br />

Multiple Buses .................................................................................... 94<br />

Interrupt Controllers ......................................................................... 94<br />

5.4 Design <strong>Guide</strong>lines ............................................................................................ 95<br />

Names and Locations ........................................................................ 95<br />

Documentation and Standards ........................................................ 96<br />

Per-Device Data Structure ................................................................ 97<br />

Per-Driver Data Structure ................................................................. 97<br />

Driver Interrupt Service Routines ................................................... 97<br />

Access Macros .................................................................................... 98<br />

5.5 Step by Step ....................................................................................................... 100<br />

5.6 Cache Considerations ...................................................................................... 101<br />

5.7 Helpful Hints .................................................................................................... 102<br />

5.8 Driver Use of the Cache Library .................................................................... 103<br />

5.8.1 Review of cacheLib Facilities ........................................................... 103<br />

5.8.2 Conducting Driver Analysis ............................................................ 103<br />

Shared Memory Types ....................................................................... 104<br />

Driver Attributes ................................................................................ 105<br />

5.8.3 Developing the cacheLib Strategy ................................................... 106<br />

Flush and Invalidate Macros ............................................................ 107<br />

WRITE_PIPING Attribute ................................................................ 107<br />

SNOOPED Attribute ......................................................................... 108<br />

MMU_TAGGING Attribute ............................................................. 108<br />

USER_DATA_UNKNOWN Attribute ............................................ 108<br />

DEVICE_WRITES_ASYNCHRONOUSLY Attribute ................... 109<br />

SHARED_CACHE_LINES Attribute .............................................. 109<br />

DEVICE_WRITES_ASYNCHRONOUSLY and<br />

SHARED_CACHE_LINES Attributes .............................. 109<br />

SHARED_POINTERS Attribute ...................................................... 110<br />

5.8.4 Additional Cache Library Hints ...................................................... 110<br />

ix


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

6 Components .............................................................................................................. 111<br />

6.1 Introduction ...................................................................................................... 111<br />

6.2 Component Description Language ............................................................... 113<br />

6.2.1 Components ....................................................................................... 113<br />

6.2.2 CDL Object Types .............................................................................. 115<br />

Folders ................................................................................................. 116<br />

Selections ............................................................................................ 118<br />

Components ....................................................................................... 120<br />

Parameters .......................................................................................... 123<br />

Initialization Groups ......................................................................... 124<br />

6.3 Creating Components ..................................................................................... 125<br />

6.3.1 CDF Conventions .............................................................................. 126<br />

6.3.2 CDF Precedence and Paths .............................................................. 126<br />

6.3.3 Defining a Component ...................................................................... 127<br />

6.3.4 Modifying a Component .................................................................. 134<br />

6.4 Releasing Components .................................................................................... 135<br />

6.4.1 Testing New Components ................................................................ 136<br />

6.4.2 Packaging a Component ................................................................... 137<br />

7 Validation Testing ..................................................................................................... 139<br />

7.1 Introduction ...................................................................................................... 139<br />

7.2 Background ....................................................................................................... 140<br />

7.2.1 Design Goals ....................................................................................... 140<br />

7.2.2 Validation Test Suite Software Architecture .................................. 141<br />

7.3 Configuring the <strong>BSP</strong> VTS ................................................................................ 143<br />

7.3.1 Hardware Setup ................................................................................. 143<br />

7.3.2 Installing the <strong>BSP</strong> VTS ...................................................................... 145<br />

x


Contents<br />

7.3.3 System Configuration ........................................................................ 147<br />

Configuring the Host System ........................................................... 147<br />

Configuring the Target Hardware ................................................... 147<br />

Configuring VxWorks ....................................................................... 148<br />

Configuring the <strong>BSP</strong> VTS .................................................................. 149<br />

7.4 Running the <strong>BSP</strong> VTS ...................................................................................... 153<br />

7.4.1 Starting the <strong>BSP</strong> VTS ......................................................................... 153<br />

7.4.2 Monitoring a <strong>BSP</strong> Test ....................................................................... 155<br />

8 Writing Portable C Code .......................................................................................... 159<br />

Background ......................................................................................... 159<br />

8.1 Portable C Code ................................................................................................ 160<br />

8.1.1 Data Structures ................................................................................... 160<br />

Specify Field Widths .......................................................................... 161<br />

Avoid Bit Fields .................................................................................. 161<br />

8.1.2 In-Line Assembly ............................................................................... 162<br />

8.1.3 Static Data Alignment ....................................................................... 163<br />

8.1.4 Runtime Alignment Checking ......................................................... 163<br />

Checking the Alignment of a Data Item ......................................... 163<br />

Verifying Pointer Alignment ............................................................ 163<br />

Unaligned Accesses and Copying ................................................... 164<br />

8.1.5 Other Issues ........................................................................................ 165<br />

Follow Strict ANSI Compilation ...................................................... 165<br />

Remove Compiler Warnings ............................................................ 165<br />

Avoid Use of Casts ............................................................................. 165<br />

Avoid inline Keyword ....................................................................... 165<br />

Avoid alloca( ) Function .................................................................... 166<br />

Take Care with void Pointer Arithmetic ......................................... 166<br />

Use volatile and const Attributes .................................................... 167<br />

Misuse of the register Attribute ....................................................... 167<br />

Avoid vector Name ............................................................................ 167<br />

Statement Labels ................................................................................ 168<br />

Summary of Compiler Macros ......................................................... 168<br />

xi


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

8.2 Tool Implementation ....................................................................................... 171<br />

8.2.1 New Tool Macros File ....................................................................... 171<br />

8.2.2 New Tool Directories ......................................................................... 171<br />

8.2.3 <strong>BSP</strong> Makefile Changes ...................................................................... 171<br />

8.2.4 Macro Definitions for GNU and Diab ............................................ 172<br />

9 Documentation <strong>Guide</strong>lines ...................................................................................... 173<br />

9.1 Introduction ...................................................................................................... 173<br />

9.2 Written Style ..................................................................................................... 173<br />

Sentences ............................................................................................. 174<br />

Punctuation ........................................................................................ 174<br />

Word Usage ........................................................................................ 174<br />

Spelling ................................................................................................ 175<br />

Acronyms ............................................................................................ 178<br />

Board Names ...................................................................................... 179<br />

9.3 Format ................................................................................................................ 180<br />

Layout ................................................................................................. 180<br />

Special Elements ................................................................................ 180<br />

Displays ............................................................................................... 182<br />

9.4 Subsections ........................................................................................................ 183<br />

Library and Subroutine Reference Pages ....................................... 183<br />

Target Information Reference Page: target.nr ................................ 186<br />

9.5 Generating Reference Pages ........................................................................... 189<br />

9.5.1 Files ...................................................................................................... 189<br />

Source Directory ................................................................................ 189<br />

Documentation Directories .............................................................. 190<br />

9.5.2 Tools ..................................................................................................... 190<br />

9.5.3 Text Formatting .................................................................................. 190<br />

Markup Commands .......................................................................... 190<br />

Tables ................................................................................................. 192<br />

xii


Contents<br />

9.5.4 Processing ........................................................................................... 193<br />

10 Product Packaging ................................................................................................... 195<br />

10.1 SETUP Developer’s Kit ................................................................................... 195<br />

10.2 <strong>BSP</strong> Packaging .................................................................................................. 195<br />

<strong>BSP</strong> Contents ....................................................................................... 196<br />

Default Configuration ....................................................................... 196<br />

Included Files ..................................................................................... 197<br />

Excluded Files ..................................................................................... 197<br />

Source of the Files .............................................................................. 198<br />

Vendor-Supplied Shared Files .......................................................... 199<br />

10.2.1 <strong>BSP</strong> Media ........................................................................................... 200<br />

10.3 Component Packaging .................................................................................... 200<br />

10.4 Project Packaging ............................................................................................. 201<br />

A Upgrading a <strong>BSP</strong> for Tornado 2.0 ........................................................................... 203<br />

A.1 Porting Issues .................................................................................................... 203<br />

A.2 Code Interface Changes ................................................................................... 204<br />

A.3 Project Issues ..................................................................................................... 205<br />

A.4 Product Contents .............................................................................................. 205<br />

A.4.1 Product Restrictions ........................................................................... 206<br />

A.4.2 Product Requirements ....................................................................... 207<br />

A.5 Summary ........................................................................................................... 208<br />

B Upgrading a <strong>BSP</strong> for Tornado 2.2 ........................................................................... 211<br />

B.1 Architecture-Independent Changes to <strong>BSP</strong>s ................................................ 211<br />

B.2 Architecture-Dependent <strong>BSP</strong> Issues .............................................................. 214<br />

B.2.1 Migration Changes Common to All Architectures ....................... 214<br />

xiii


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

B.2.2 68K/CPU32 ........................................................................................ 215<br />

B.2.3 ARM .................................................................................................... 215<br />

B.2.4 ColdFire ............................................................................................... 216<br />

B.2.5 MIPS .................................................................................................... 216<br />

B.2.6 Pentium ............................................................................................... 217<br />

B.2.7 PowerPC ............................................................................................. 218<br />

B.2.8 XScale/StrongARM ........................................................................... 219<br />

B.2.9 SuperH ................................................................................................ 220<br />

C Upgrading a <strong>BSP</strong> for the VxWorks Network Stack ................................................ 221<br />

D VxWorks Boot Sequence ......................................................................................... 223<br />

E Component Language .............................................................................................. 231<br />

E.1 Component Description Language (CDL) ................................................... 231<br />

E.1.1 Component Properties ...................................................................... 232<br />

E.1.2 Parameter Properties ......................................................................... 234<br />

E.1.3 Folder Properties ............................................................................... 235<br />

E.1.4 Selection Properties ........................................................................... 235<br />

E.1.5 InitGroup Properties ......................................................................... 236<br />

E.2 Folder Hierarchy .............................................................................................. 236<br />

E.3 Project Initialization Order ............................................................................. 238<br />

E.3.1 romInit.s .............................................................................................. 239<br />

E.3.2 romStart.c ............................................................................................ 239<br />

E.3.3 usrEntry.c ............................................................................................ 239<br />

E.3.4 sysALib.s ............................................................................................. 240<br />

E.3.5 prjConfig.c .......................................................................................... 240<br />

xiv


Contents<br />

F Generic Drivers ......................................................................................................... 247<br />

F.1 Introduction ...................................................................................................... 247<br />

F.2 Serial Drivers ..................................................................................................... 248<br />

F.3 Multi-Mode Serial (SIO) Drivers .................................................................... 249<br />

F.4 Timer .................................................................................................................. 251<br />

F.5 Non-Volatile Memory ...................................................................................... 252<br />

F.6 VMEbus ............................................................................................................. 253<br />

F.7 DMA ................................................................................................................... 254<br />

F.8 Interrupt Controllers ........................................................................................ 254<br />

F.9 Multi-Function .................................................................................................. 254<br />

F.10 PCI Bus ............................................................................................................... 255<br />

G Upgrading 4.3 BSD Network Drivers ...................................................................... 257<br />

G.1 Introduction ...................................................................................................... 257<br />

G.1.1 Structure of a 4.3 BSD Network Driver .......................................... 258<br />

G.1.2 Etherhook Routines Provide Access to Raw Packets .................... 259<br />

G.2 Upgrading to 4.4 BSD ...................................................................................... 260<br />

G.2.1 Removing the xxOutput( ) Routine ................................................. 261<br />

G.2.2 Changing the Transmit Startup Routine ......................................... 262<br />

G.2.3 Changes in Receiving Packets .......................................................... 262<br />

G.2.4 Creating a Transmit Startup Routine .............................................. 263<br />

G.3 Porting a Network Interface Driver to the END Model ............................. 264<br />

Rewrite xxattach( ) to Use an endLoad( ) Interface ....................... 265<br />

xxReceive( ) Still Handles Task-Level Packet Reception .............. 265<br />

Rewrite xxOutput( ) to Use an endSend( ) Interface ..................... 265<br />

xv


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

xxIoctl( ) is the Basis of endIoctl( ) .................................................. 266<br />

H Implementing a MUX-Based Network Interface Driver .......................................... 267<br />

H.1 Introduction ...................................................................................................... 267<br />

H.2 How VxWorks Launches and Uses Your Driver ......................................... 270<br />

H.2.1 Launching Your Driver ..................................................................... 271<br />

H.2.2 Your ISR Puts Work on the Network Job Queue ........................... 272<br />

H.2.3 Executing Calls Waiting in the Network Job Queue .................... 273<br />

H.2.4 Adding Your Network Interface Driver to VxWorks ................... 273<br />

H.3 <strong>Guide</strong>lines for Handling Packet Reception in Your Driver ....................... 275<br />

H.3.1 Setting Up and Using a Memory Pool for Receive and<br />

Transmit Buffers 276<br />

H.3.2 Swapping Buffers Between Protocol and Driver .......................... 280<br />

H.3.3 Using Private Memory Management Routines ............................. 280<br />

H.3.4 Supporting Scatter-Gather in Your Driver ..................................... 280<br />

H.4 Indicating Error Conditions ........................................................................... 280<br />

H.5 Required Driver Entry Points and Structures .............................................. 282<br />

H.5.1 Required Structures for a Driver ..................................................... 283<br />

Tracking Your Device’s Control Structure: DEV_OBJ .................. 285<br />

Identifying the Entry Points into Your Network<br />

Driver: NET_FUNCS .......................................................... 286<br />

Tracking Link-Level Information: LL_HDR_INFO ...................... 287<br />

Tracking Data That Passes Between the Driver and the<br />

Protocol: mBlk ...................................................................... 288<br />

H.5.2 Required Driver Entry Points .......................................................... 289<br />

Loading the Device: endLoad( ) ...................................................... 290<br />

Unloading the Device: endUnload( ) .............................................. 291<br />

Providing an Opaque Control Interface to Your<br />

Driver: endIoctl( ) ................................................................ 292<br />

Sending Data Out on the Device: endSend( ) ................................ 293<br />

Starting a Stopped but Loaded Driver: endStart( ) ....................... 294<br />

xvi


Contents<br />

Stopping the Driver Without Unloading It: endStop( ) ................ 294<br />

Handling a Polling Send: endPollSend( ) ....................................... 295<br />

Handling a Polling Receive: endPollReceive( ) ............................. 296<br />

Adding a Multicast Address: endMCastAddrAdd( ) ................... 296<br />

Deleting a Multicast Address: endMCastAddrDel( ) ................... 297<br />

Getting the Multicast Address Table: endMCastAddrGet( ) ....... 298<br />

Forming an Address into a Packet for Transmission:<br />

endAddressForm( ) ............................................................. 299<br />

Getting a Data-Only mBlk: endPacketDataGet( ) ......................... 299<br />

Return Addressing Information: endPacketAddrGet( ) ............... 300<br />

H.6 Writing Protocols That Use the MUX API .................................................... 301<br />

Protocol Startup .................................................................................. 302<br />

Sending Data ...................................................................................... 303<br />

Receiving Data .................................................................................... 303<br />

Supporting Scatter/Gather Devices ................................................ 304<br />

Protocol Transmission Restart .......................................................... 304<br />

Protocol Shutdown ............................................................................ 305<br />

H.6.1 Protocol to MUX API ......................................................................... 305<br />

The Protocol Data Structure NET_PROTOCOL ............................ 306<br />

Passing a Packet Up to the Protocol: stackRcvRtn( ) .................... 307<br />

Passing Error Messages Up to the Protocol: stackError( ) ........... 308<br />

Shutting Down a Protocol: stackShutdownRtn( ) ......................... 309<br />

Restarting Protocols: stackTxRestartRtn( ) ..................................... 310<br />

H.6.2 Network Layer to Data Link Layer Address Resolution ............. 310<br />

H.7 Converting an END Driver from RFC 1213 to RFC 2233 ........................... 311<br />

I Writing a SCSI-2 Device Driver ............................................................................... 317<br />

I.1 Introduction ...................................................................................................... 317<br />

I.2 Overview of SCSI ............................................................................................. 318<br />

I.3 The SCSI Libraries ............................................................................................ 321<br />

I.3.1 SCSI Manager (scsiMgrLib) .............................................................. 322<br />

I.3.2 SCSI Controller Library (scsiCtrlLib) .............................................. 324<br />

I.3.3 SCSI Direct Access Library (scsiDirectLib) .................................... 324<br />

xvii


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

I.3.4 SCSI Sequential Access Library (scsiSeqLib) ................................. 324<br />

I.3.5 SCSI Common Access Library (scsiCommonLib) ........................ 324<br />

I.3.6 An Execution Example ..................................................................... 325<br />

I.4 The SCSI Driver Programming Interface ...................................................... 325<br />

I.4.1 Basic SCSI Controller Driver ............................................................ 325<br />

I.4.2 Advanced SCSI Controller Driver ................................................... 334<br />

I.5 The <strong>BSP</strong> Interface ............................................................................................. 357<br />

I.6 <strong>Guide</strong>lines for Developing a SCSI Driver .................................................... 359<br />

I.7 Test Suites .......................................................................................................... 360<br />

scsciDiskThruputTest( ) .................................................................... 360<br />

scsiDiskTest( ) ..................................................................................... 361<br />

scsiSpeedTest( ) .................................................................................. 362<br />

tapeFsTest( ) ........................................................................................ 363<br />

I.8 Troubleshooting and Debugging ................................................................... 364<br />

J <strong>BSP</strong> Validation Test Suite Reference Entries ......................................................... 365<br />

K <strong>BSP</strong> Validation Checklists ....................................................................................... 401<br />

L Refgen ....................................................................................................................... 415<br />

M <strong>BSP</strong> Product Contents ............................................................................................. 423<br />

Index .......................................................................................................................... 427<br />

xviii


1<br />

Overview<br />

1.1 Introduction<br />

One strength of VxWorks is that it provides a high degree of architectural and<br />

hardware independence for application code. This portability is due to VxWorks’s<br />

modular design, which isolates all hardware-specific functionality into a set of<br />

libraries called the Board Support Package (<strong>BSP</strong>). The <strong>BSP</strong> libraries provide an<br />

identical software interface to the hardware functions of all boards. They include<br />

facilities for hardware initialization, interrupt handling and generation, hardware<br />

clock and timer management, mapping of local and bus memory spaces, memory<br />

sizing, and so on.<br />

Broadly speaking, there are several types of VxWorks porting activity:<br />

■<br />

Host Porting: Porting Tornado and VxWorks development capability to a<br />

previously unsupported host.<br />

■<br />

■<br />

■<br />

■<br />

Architecture Porting: Porting VxWorks and the Tornado debugger to a<br />

previously unsupported target processor type or architecture.<br />

Board Porting: Porting VxWorks to a new target board, for which there is<br />

already an architecture port and a host port available.<br />

Upgrading pre-Tornado <strong>BSP</strong>s to work with Tornado.<br />

Porting an optional Component to a Tornado release.<br />

Host ports and architecture ports require access to the entire VxWorks source code<br />

and are outside the scope of this manual. Board porting, the focus of this manual,<br />

requires access to just the hardware-dependent source within VxWorks and the<br />

debugger. This source code is the <strong>BSP</strong>.<br />

1


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Over the years, Wind River has been able to offer a wide range of <strong>BSP</strong>s to<br />

customers. However, with the proliferation of many new CPU boards (many of<br />

which are custom designs) Wind River alone has not been able to keep up with the<br />

demand for new <strong>BSP</strong>s.<br />

The Tornado <strong>BSP</strong> Developer’s Kit for VxWorks (<strong>BSP</strong> Kit) is intended to help you<br />

create, document, and test new <strong>BSP</strong>s, components, and projects. The process of<br />

porting VxWorks to a new board can be challenging, primarily because the<br />

VxWorks development tools are unavailable until after the porting is finished.<br />

Wind River has developed strategies that make porting easier. This <strong>BSP</strong> Kit<br />

provides these strategies and a detailed look at how the system elements interact.<br />

It also includes the technical information that a third party needs in order to create<br />

and distribute components and projects based upon Tornado 2.x.<br />

This release of the <strong>BSP</strong> Kit is compatible with Tornado 2.0 or later. Upgrading<br />

earlier <strong>BSP</strong>s to work with the Tornado 2.x product is a relatively simple task. For<br />

more information, see A. Upgrading a <strong>BSP</strong> for Tornado 2.0 or B. Upgrading a <strong>BSP</strong> for<br />

Tornado 2.2.<br />

New Features for Tornado 2.x<br />

■<br />

SCSI 1 Dropped Support for SCSI-1 drivers and libraries has been dropped. These<br />

libraries are still included in Tornado 2.0, but they are classified as obsolete and<br />

will not be included in future releases.<br />

■<br />

Macro TYCO5_2 Deleted The TYCO5_2 macro is no longer supported. Customers<br />

should be using SIO drivers for Tornado 2.x.<br />

■<br />

<strong>BSP</strong> Packaging Changes Refer to 10.2 <strong>BSP</strong> Packaging, p.195 for details on<br />

packaging requirements. See M. <strong>BSP</strong> Product Contents for a quick summary of a<br />

typical product contents.<br />

■<br />

Documentation All on-line documentation is now provided as HTML pages. A<br />

utility called refgen that generates HTML from existing nroff input is included in<br />

the system.<br />

■<br />

VxWorks Network Stack The network stack, which was an option for Tornado 1.0.1<br />

users, is now the only stack supported. It is referred to as the VxWorks network<br />

stack. All <strong>BSP</strong>s have been converted to use drivers modified for the VxWorks<br />

network stack (BSD 44 stack). In <strong>BSP</strong>s where both BSD44 and END drivers are<br />

available, the END driver has been selected as the default driver for the <strong>BSP</strong>.<br />

2


1<br />

Overview<br />

■<br />

New Drivers Many new END network drivers have been added to the driver<br />

product in order to provide as many <strong>BSP</strong>s as possible with at least one available<br />

END driver.<br />

1<br />

■<br />

Integrated Simulators Tornado 2.x includes an integrated simulator with the base<br />

product. This allows developers to begin application development before the<br />

hardware environment is ready.<br />

■<br />

Integrated WindView The Tornado 2.x product contains an integrated WindView<br />

tool for examining run-time behavior. Refer to the WindView User’s <strong>Guide</strong> for<br />

information on how to use all the features of WindView.<br />

■<br />

VTS Test Updates The Validation Test Suite has received only minor updates that<br />

allow it to work correctly with the new virtual I/O features of the target shell.<br />

■<br />

SCSI Test Suites The SCSI performance test suites, which were omitted from the<br />

previous release of the porting kit, are now included on the CD-ROM.<br />

■<br />

ROM_WARM_ADRS This new macro has been introduced into the template <strong>BSP</strong>s<br />

and some existing <strong>BSP</strong>s. It represents the warm entry point into the boot ROM<br />

code, and is needed to remove the artificial computation of the entry point based<br />

on CPU family. Normally, ROM_WARM_ADRS is based on an offset from<br />

ROM_TEXT_ADRS, for example:<br />

#define ROM_WARM_ADRS (ROM_TEXT_ADRS + 8)<br />

■<br />

New SIO IOCTLs New SIO IOCTL codes have been created to support modem<br />

control lines. The IOCTLs SIO_OPEN and SIO_HUP notify the driver when the<br />

device is opened and closed. The new IOCTLs SIO_HW_OPTS_SET and<br />

SIO_HW_OPTS_GET allow the user to manage character length, parity, stop bits,<br />

and modem control lines. The options bit CLOCAL disables modem control lines<br />

from being used in the driver. For backward compatibility, the CLOCAL option is<br />

selected by default in Wind River-supplied <strong>BSP</strong>s.<br />

■<br />

Target.txt File Removed. The text version of the target.nr file (generated for<br />

Windows host users) has been eliminated. Both UNIX and Windows hosts now use<br />

a browser for reading documentation in HTML format. The host utility refgen<br />

takes nroff input and generates HTML output.<br />

3


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Prerequisites<br />

Users of the <strong>BSP</strong> Kit should have a working knowledge of low-level C<br />

programming and assembly languages, familiarity with device drivers, familiarity<br />

with interrupts, and general experience interfacing software with hardware. In<br />

addition, you should be familiar with the Tornado development tools (at least to<br />

the point of having read through the Tornado User’s <strong>Guide</strong>). Finally, you should<br />

have a reference <strong>BSP</strong> that is a released Tornado <strong>BSP</strong> based on the same CPU used<br />

by your target.<br />

You should also have the template <strong>BSP</strong> for your architecture and the template<br />

drivers. Most customers also purchase one or more of the driver source code<br />

products as well.<br />

<strong>BSP</strong> Kit Components<br />

The <strong>BSP</strong> Kit consists of a documentation set and a CD-ROM with software. The<br />

documentation set consists of an installation guide and this manual, which is<br />

summarized in Documentation, p.5. The software consists of the following:<br />

■<br />

■<br />

■<br />

■<br />

<strong>BSP</strong> Validation Test Suite (VTS). The purpose of these programs is to exercise<br />

the basic functionality of a <strong>BSP</strong>, and, in the process, note and report any<br />

defects. These programs run on both the target machine and the supported<br />

hosts. Feel free to enhance existing tests or create new ones. However, the basic<br />

set of tests provided by the VTS is the standard by which <strong>BSP</strong>s are judged.<br />

The test suite is highly automated. Once started, a <strong>BSP</strong> test requires no user<br />

intervention, ensuring repeatability of the tests and also reducing the tedium<br />

of running the tests by hand.<br />

The VTS is distributed in source form to facilitate maintenance and extension.<br />

When performing official validation testing, the tests should not be modified<br />

from their original code.<br />

Template <strong>BSP</strong>s. These templates are provided for all architecture types. These<br />

templates provide a starting point for <strong>BSP</strong> development. Each template<br />

compiles, but nearly every optional feature has been disabled. This allows<br />

quick-starting from a copy of the template directory, without having to make<br />

major changes.<br />

Template Drivers. Template drivers are provided for all device types.<br />

SCSI Test suite. A suite of SCSI test programs is included. Please refer to the<br />

test programs in the target/src/test/scsi directory.<br />

4


1<br />

Overview<br />

Included with Tornado (not the <strong>BSP</strong> Kit) is a reference <strong>BSP</strong> appropriate to the<br />

architecture you specified when you ordered Tornado. This is a full working <strong>BSP</strong>.<br />

Use this reference <strong>BSP</strong> as the source for many of the header files and object<br />

modules in the <strong>BSP</strong> you create.<br />

For instructions on how to install the <strong>BSP</strong> Kit, the reference <strong>BSP</strong>, or any other Wind<br />

River software product, see the Tornado Getting Started <strong>Guide</strong>.<br />

1<br />

Documentation<br />

This Manual<br />

The <strong>BSP</strong> Kit documentation includes the Tornado Getting Started <strong>Guide</strong> and this<br />

manual.<br />

This user’s guide contains information on all aspects of writing, documenting, and<br />

testing a <strong>BSP</strong>. This manual also details the standards that should be used for both<br />

C source code and documentation, and provides information on how to write<br />

network interface drivers, SCSI device drivers, and other drivers. The chapters of<br />

this manual are summarized below:<br />

■<br />

■<br />

■<br />

■<br />

■<br />

■<br />

1. Overview (this chapter)<br />

2. <strong>BSP</strong> Organization is an overview of <strong>BSP</strong> construction and requirements. It<br />

discusses required and optional files and routines. This is the basic overview<br />

of what constitutes a <strong>BSP</strong> and how it interacts with VxWorks.<br />

3. Creating a New <strong>BSP</strong> presents strategies for beginning a <strong>BSP</strong> port. Several<br />

methods for getting started using different hardware configurations are<br />

discussed. Getting started without having a working VxWorks boot ROM is<br />

the most difficult part of porting to a new board.<br />

4. Hardware <strong>Guide</strong>lines discusses CPU architectural considerations and how<br />

different hardware elements can influence the <strong>BSP</strong> porting effort.<br />

5. Driver <strong>Guide</strong>lines provides guidelines for device drivers in general. Specific<br />

details of drivers are found elsewhere in various appendices describing<br />

particular device types.<br />

6. Components describes how a <strong>BSP</strong> interacts with components. This chapter<br />

provides the basis for component creation and usage.<br />

5


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

■<br />

■<br />

■<br />

■<br />

■<br />

■<br />

■<br />

■<br />

■<br />

■<br />

7. Validation Testing describes the operation and use of the <strong>BSP</strong> Validation Test<br />

Suite (VTS), a collection of programs that run on the host and target machines<br />

to exercise the basic functionality of <strong>BSP</strong>s and to detect and report defects<br />

found in them. Documentation for the test suite programs and the individual<br />

tests can be found in J. <strong>BSP</strong> Validation Test Suite Reference Entries. A checklist to<br />

be followed for <strong>BSP</strong> testing is found in K. <strong>BSP</strong> Validation Checklists.<br />

8. Writing Portable C Code describes how to write compiler-independent<br />

portable C code. The goal is to write code that does not require changes in<br />

order to work correctly with different compilers.<br />

9. Documentation <strong>Guide</strong>lines covers Wind River conventions for style and<br />

format, and the procedures for generating <strong>BSP</strong> documentation from source<br />

modules. The template <strong>BSP</strong>s supplied with the <strong>BSP</strong> Kit provide examples of<br />

the writing style, text format, module layout, and text commands discussed<br />

throughout this section.<br />

10. Product Packaging discusses the content and format of the <strong>BSP</strong> product that<br />

is delivered to the end user.<br />

A. Upgrading a <strong>BSP</strong> for Tornado 2.0 describes how to convert an existing<br />

Tornado 1.0.1./SENS <strong>BSP</strong> to a Tornado 2.0 <strong>BSP</strong>.<br />

B. Upgrading a <strong>BSP</strong> for Tornado 2.2 discusses the migration of a <strong>BSP</strong> from<br />

Tornado 2.0 to 2.2. It includes information on both architecture-independent<br />

and architecture-dependent issues.<br />

C. Upgrading a <strong>BSP</strong> for the VxWorks Network Stack describes the <strong>BSP</strong> update<br />

procedure for the network stack. This is only for <strong>BSP</strong>s that were not previously<br />

updated for the Tornado 1.0.1 SENS stack product.<br />

D. VxWorks Boot Sequence provides a detailed look at the full VxWorks boot<br />

sequence. It identifies each step by its function, its name, and its source<br />

location.<br />

E. Component Language provides a technical summary of the Component<br />

Description Language (CDL) used in component description files (CDFs). It<br />

also presents a hierarchical view of the default component folders and their<br />

initialization groups and sequencing.<br />

F. Generic Drivers provides details on how to write other drivers used in the<br />

VxWorks system.<br />

■<br />

G. Upgrading 4.3 BSD Network Drivers is an application note on converting a 4.3<br />

BSD style driver to the 4.4 BSD interface required by the new network stack.<br />

6


1<br />

Overview<br />

■<br />

■<br />

■<br />

■<br />

■<br />

■<br />

H. Implementing a MUX-Based Network Interface Driver describes the<br />

requirements for a new Enhanced Network Driver (an END) that uses the<br />

MUX to access all the features of the new network stack. Enhanced drivers<br />

include polling and multicast support not available in the basic NETIF drivers.<br />

I. Writing a SCSI-2 Device Driver describes how a VxWorks SCSI-2 device<br />

driver fits into the VxWorks I/O system hierarchy, and how to write a SCSI-2<br />

driver that interfaces with the VxWorks SCSI-2 library (scsi2Lib), which<br />

provides the high-level SCSI-2 interface routines that are device independent.<br />

J. <strong>BSP</strong> Validation Test Suite Reference Entries provides the detailed<br />

documentation for using the <strong>BSP</strong> Validation Test Suite (<strong>BSP</strong>-VTS).<br />

K. <strong>BSP</strong> Validation Checklists provides copies of the <strong>BSP</strong> validation checklists<br />

used at Wind River. PostScript copies of the forms are included on the<br />

CD-ROM.<br />

L. Refgen documents use of the refgen tool for generating HTML reference<br />

pages from traditional <strong>BSP</strong> source code.<br />

M. <strong>BSP</strong> Product Contents lists the typical contents of a <strong>BSP</strong> product.<br />

1<br />

Other Documentation<br />

The following documents provide important background information on<br />

VxWorks and Tornado.<br />

■<br />

Tornado Getting Started <strong>Guide</strong>, 2.2<br />

■<br />

Tornado Release Notes, 2.2<br />

■<br />

Tornado User’s <strong>Guide</strong>, 2.2<br />

■<br />

VxWorks Programmer’s <strong>Guide</strong>, 5.5<br />

■<br />

VxWorks API Reference: Drivers, 5.5<br />

■<br />

VxWorks API Reference: OS Libraries, 5.5<br />

■<br />

Wind River Technical Notes (available from the WindSurf Web site)<br />

Documentation Conventions<br />

The remainder of this chapter describes this document’s conventions for cross<br />

references, path names, and type.<br />

Cross-References<br />

Cross-references in this guide to a reference entry for a tool or module refer to an<br />

entry in the VxWorks API Reference (for target libraries or subroutines) or to the<br />

reference appendix in the Tornado User’s <strong>Guide</strong> (for host tools) or the <strong>BSP</strong>-specific<br />

7


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Path Names<br />

entries in the Tornado man directories. These references are also provided in the<br />

Tornado Online Manuals. For more information about how to access online<br />

documentation, see the Tornado User’s <strong>Guide</strong>: Documentation <strong>Guide</strong>.<br />

Other references from one book to another are always at the chapter level, and take<br />

the form Book Title: Chapter Name.<br />

The top-level Tornado directory structure includes three major directories (see the<br />

Tornado User’s <strong>Guide</strong>: Directories and Files). Because all VxWorks files reside in the<br />

target directory, this manual uses relative path names starting below that directory.<br />

For example, if you install Tornado in /usr/wind, the full path name for the file<br />

shown as config/all/configAll.h is /usr/wind/target/config/all/configAll.h.<br />

NOTE: In this manual, forward slashes are used as path name delimiters for both<br />

UNIX and Windows filenames.<br />

Typographical Conventions<br />

This manual uses the conventions shown in Table 1-1 to differentiate various<br />

elements. Parentheses are always included to indicate a subroutine name, as in<br />

printf( ).<br />

Table 1-1<br />

Font Usage for Special Terms<br />

Term<br />

files, path names<br />

libraries, drivers<br />

host tools<br />

Example<br />

/etc/hosts<br />

memLib, nfsDrv<br />

more, chkdsk<br />

subroutines semTake( )<br />

boot commands<br />

p<br />

code display main ();<br />

keyboard input make CPU=MC68040 ...<br />

display output value = 0<br />

user-supplied parameters<br />

constants<br />

name<br />

INCLUDE_NFS<br />

8


1<br />

Overview<br />

Table 1-1<br />

Font Usage for Special Terms (Continued)<br />

Term<br />

Example<br />

1<br />

C keywords, cpp directives<br />

named key on keyboard<br />

control characters<br />

lower-case acronyms<br />

#define<br />

RETURN<br />

CTRL+C<br />

fd<br />

9


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

10


2<br />

<strong>BSP</strong> Organization<br />

2.1 Introduction<br />

This chapter describes the components of a <strong>BSP</strong>. It lists and describes the contents<br />

of all the <strong>BSP</strong>-associated source and include files. For the .h files, this chapter<br />

describes the consequences of defining or undefining the standard symbolic<br />

constants. For the .c files, it describes all the required and optional functions<br />

associated with the file. This chapter describes the derived files, such as sysLib.o<br />

(the interface between board-dependent and board-independent code) and<br />

bootrom.<br />

There is a section enumerating the principal <strong>BSP</strong>-associated routines and their<br />

order of invocation (for a tabular summary of the boot sequence, see D. VxWorks<br />

Boot Sequence). This information is provided to give you the system awareness<br />

needed to debug the VxWorks boot phase.<br />

At the end of this chapter is a discussion of mistakes commonly made by the<br />

novice <strong>BSP</strong> developer.<br />

2.2 <strong>BSP</strong> Components<br />

A <strong>BSP</strong> consists of the routines that provide VxWorks with its main interface to the<br />

hardware environment. Figure 2-1 illustrates the various components of VxWorks,<br />

indicating the hardware-dependent and -independent elements.<br />

11


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Figure 2-1<br />

VxWorks Components<br />

Hardware-Independent Software<br />

Tools - Applications<br />

I/O System<br />

VxWorks Libraries<br />

TCP/IP<br />

File<br />

System<br />

Hardware-Dependent Software<br />

wind Kernel<br />

SCSI<br />

Driver<br />

<strong>BSP</strong><br />

Network<br />

Driver<br />

Hardware<br />

SCSI<br />

Controller<br />

Serial<br />

Controller<br />

Clock<br />

Timer<br />

Ethernet<br />

Controller<br />

The <strong>BSP</strong> routines are contained in a number of C and assembly files that you must<br />

create (or modify, if starting with a template <strong>BSP</strong>). The rest of this section<br />

summarizes <strong>BSP</strong> files and directories.<br />

2.2.1 <strong>BSP</strong> Source and Include Files<br />

This section describes the directories target/config/all and target/config/bspname.<br />

Strictly speaking, the files in target/config/all are not part of the <strong>BSP</strong>, but the<br />

modules defined there are shared by all <strong>BSP</strong>s. Familiarity with these modules is<br />

essential if you want to understand your particular <strong>BSP</strong>. When building project<br />

images, the component configlettes in target/config/comps/src replace the files in<br />

target/config/all.Aconfiglette is any C source code compiled by the project facility<br />

as a part of the project build step. Such files provide only some limited part of the<br />

final project configuration.<br />

12


2<br />

<strong>BSP</strong> Organization<br />

Files in the target/config/all Directory<br />

The files in target/config/all are delivered as part of the VxWorks architecture<br />

product. Do not alter these files unless absolutely necessary. Of special concern is<br />

configAll.h. This file sets the default configuration for all VxWorks images. The<br />

values you define here should be generic and therefore true for most if not all<br />

VxWorks developers at your site. If you need a VxWorks image that differs from<br />

the default configuration, use your <strong>BSP</strong>’s config.h to override (#define or #undef)<br />

the default values in configAll.h.<br />

Files in config/all are not directly used when building a project. They are scanned<br />

only once when a new project is made from a <strong>BSP</strong>. Any changes to the files in<br />

target/config/all after a project has been created do not affect the project. If a<br />

change is desired, the user must make the change directly in the project area.<br />

2<br />

! CAUTION: Changing configAll.h from the command line can have unpleasant<br />

side effects for other VxWorks users at your site. This note only applies to building<br />

from the command line. One benefit of the Tornado project facility is that changes<br />

do not affect existing projects. Only new projects created from a <strong>BSP</strong> after the<br />

change to configAll.h inherit that change.<br />

bootConfig.c – Main Initialization for Boot ROM Images<br />

The bootConfig.c file is the main initialization and control file for all boot ROM<br />

images. It includes the complete boot ROM shell task. It contains a table (NETIF)<br />

for network device initialization. This module is a subset of usrConfig.c. Boot<br />

ROM images do not provide all of the optional features available in the full<br />

VxWorks images. Of particular note is that boot images do not use MMU libraries<br />

(except for SPARC).<br />

The Tornado project facility does not have the ability to create and manipulate a<br />

boot ROM project. For projects created from a <strong>BSP</strong>, there is a button that performs<br />

the traditional command-line creation of a boot ROM image from the Build menu.<br />

Please take note that project-specific configuration information has no effect at all<br />

when the boot ROM image gets built. Only the traditional config.h, configAll.h,<br />

bootConfig.c, and bootInit.c files affect the building of a boot ROM image.<br />

bootInit.c – Second-Stage ROM Initialization<br />

The bootInit.c file is the second stage of boot ROM initialization, after romInit.o.<br />

The romInit( ) routine in romInit.s terminates by jumping to romStart( ), defined<br />

in this file. The routine romStart( ) performs the necessary code uncompression<br />

and relocation for ROM images. First it copies the text and data segments from<br />

13


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

ROM to RAM. Then it clears those parts of main RAM not otherwise used. Finally<br />

it uncompresses the compressed portion of the image. Different configuration<br />

options can modify how these operations are performed.<br />

In a project being built for Tornado 2.x, the configlette romStart.c replaces the<br />

functionality of bootInit.c. (For a ROMed VxWorks image only. Not for a boot<br />

ROM image).<br />

dataSegPad.s – VxVMI Text Segment Protection<br />

The dataSegPad.s file is used only for VxVMI text segment protection. It insures<br />

that text and data segments do not share an MMU page.<br />

usrConfig.c – Initialization Code for VxWorks Image<br />

The userConfig.c file contains the main initialization code for traditional VxWorks<br />

images. Unlike bootConfig.c, which is fully self-contained, usrConfig.c includes<br />

target/src/config/usrExtra.c, which includes other files that provide subsystem<br />

initialization and configuration.<br />

This file is used only when building from the command line, as was done in<br />

Tornado 1.0. When building projects using the project facility, project initialization<br />

groups determine the order of component initialization. Each component has a set<br />

of properties that specify which initialization group it belongs to and where in that<br />

group it belongs.<br />

Files in the target/config/comps/vxWorks Directory<br />

Files under this directory are the basic component descriptor files (CDF files) for<br />

the VxWorks real-time kernel. Refer to 6. Components for more information on how<br />

components are created, used, and delivered. Refer to E.1 Component Description<br />

Language (CDL), p.231 for details on the syntax for CDF files.<br />

Files in the target/config/comps/src Directory<br />

The files in this directory represent the configlettes associated with the kernel<br />

components. They represent code fragments formerly found in<br />

target/config/all/usrConfig.c and in target/src/config.<br />

14


2<br />

<strong>BSP</strong> Organization<br />

Files in the target/config/bspname Directory<br />

The target/config/bspname subdirectory contains the system or<br />

hardware-dependent files for the <strong>BSP</strong>.<br />

2<br />

README<br />

The README file contains the <strong>BSP</strong> release record. It records each release version<br />

and revision and documents work done on the <strong>BSP</strong> as a whole. This file was first<br />

introduced with Tornado 1.0.<br />

Makefile and depend.bspname<br />

The makefile controls the building of images from the command line. Beginning<br />

with VxWorks 5.2, the standard make utility was GNU make, and the current<br />

make technology continues to use many of the advanced features available in<br />

GNU make. The <strong>BSP</strong> make system includes make subfiles located in the<br />

target/h/make directory. If a dependencies file does not already exist, make<br />

automatically generates a depend.bspname file that it uses to track all module<br />

dependencies. The depend.bspname dependency file is not shipped with the <strong>BSP</strong>, it<br />

is a generated file. For more information on customizing the makefile, see the<br />

Tornado User’s <strong>Guide</strong>, 2.2.<br />

Within the makefile, you must define the following macros:<br />

CPU<br />

The target CPU architecture (for example, MC68040).<br />

TOOL<br />

The host tool chain (for example, gnu).<br />

TARGET_DIR<br />

The target directory (<strong>BSP</strong>) name.<br />

VENDOR<br />

The target manufacturer’s name.<br />

BOARD<br />

The target name.<br />

ROM_TEXT_ADRS<br />

Specifies the boot ROM entry address in hexadecimal. For most boards, this is<br />

set to the beginning of the ROM address area. However, if your hardware<br />

configuration uses an area at the start of ROM for the reset vector, you should<br />

offset accordingly.<br />

15


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

config.h<br />

ROM_WARM_ADRS<br />

The warm entry point to the boot ROM code.<br />

ROM_SIZE<br />

The ROM area’s size in hexadecimal.<br />

RAM_LOW_ADRS<br />

The address at which to load VxWorks.<br />

RAM_HIGH_ADRS<br />

The destination address used when copying the boot ROM image to RAM.<br />

The config.h file contains all includes and definitions specific to the CPU board.<br />

The standard organization of config.h contents is roughly as follows:<br />

(1) <strong>BSP</strong> version and revision ID numbers<br />

(2) configAll.h (#included)<br />

(3) memory caching and MMU configuration<br />

(4) shared memory network definitions<br />

(5) on-board memory addresses and size<br />

(6) ROM addresses and size<br />

(7) non-volatile memory (NVRAM) parameters<br />

(8) the default bootline parameters<br />

(9) timestamp driver support<br />

(10) external bus address mapping<br />

(11) network device and interrupt vectors<br />

(12) bspname.h file (#included)<br />

NOTE: A config.h file should include both configAll.h and bspname.h.<br />

<strong>BSP</strong> Release Numbers. The release number for a <strong>BSP</strong> consists of its version<br />

number and revision number. A <strong>BSP</strong>’s version number identifies a <strong>BSP</strong>’s<br />

generation. A <strong>BSP</strong>’s revision number is an incrementing number that identifies a<br />

particular release of a <strong>BSP</strong> within its generation.<br />

16


2<br />

<strong>BSP</strong> Organization<br />

Version 1.0 <strong>BSP</strong>s are written for all standard VxWorks releases up to and including<br />

VxWorks 5.2. Version 1.1 <strong>BSP</strong>s are written for Tornado 1.0 and Tornado 1.0.1.<br />

Version 1.2 identifies a <strong>BSP</strong> designed for use with Tornado 2.x. The main interface<br />

differences between 1.1 and 1.2 <strong>BSP</strong>s is support for the networking stack and<br />

different packaging. With each new version sequence, the revision number begins<br />

with 0 and is incremented each time the <strong>BSP</strong> is released for production.<br />

To specify a <strong>BSP</strong> version number, you can define <strong>BSP</strong>_VERSION to be the string<br />

“1.2” or “1.1”. Otherwise, you can define either of the macros <strong>BSP</strong>_VER_1_1 or<br />

<strong>BSP</strong>_VER_1_2, whichever is appropriate. To set the revision number, use <strong>BSP</strong>_REV,<br />

which you should set to a string value such as “/0”. The revision number includes<br />

the slash character. The full <strong>BSP</strong> release number is the concatenation of the two<br />

string macros <strong>BSP</strong>_VER and <strong>BSP</strong>_REV: for example, “1.2/0”.<br />

Thus, to set a <strong>BSP</strong>’s release number to “1.2/0”, define the following:<br />

2<br />

#define <strong>BSP</strong>_VER_1_1<br />

#define <strong>BSP</strong>_VER_1_2<br />

#define <strong>BSP</strong>_VERSION "1.2"<br />

#define <strong>BSP</strong>_REV "/0" /* Increment for each new release */<br />

configAll.h. Include configAll.h (located in the target/config/all directory) in your<br />

config.h so the reasonable configuration defaults for a <strong>BSP</strong> are adopted. Use<br />

config.h as the main user-editable configuration file for your <strong>BSP</strong>.<br />

Use config.h as the main user-editable configuration file for your <strong>BSP</strong>. To pick up<br />

the reasonable configuration defaults for a <strong>BSP</strong> at your site, your config.h should<br />

include configAll.h (located in the target/config/all directory). 1<br />

Within your config.h you can override these site defaults, with values more<br />

appropriate to this particular <strong>BSP</strong>. You should also present your config.h to<br />

subsequent users of your <strong>BSP</strong> as the configuration file that they should edit either<br />

to override configAll.h or to configure whatever optional features you have built<br />

into your <strong>BSP</strong>.<br />

When building project images, components and parameters selected using the<br />

project override any values assigned in either configAll.h, config.h, or even<br />

bspname.h. Any macro known to the project facility is assigned the project value,<br />

overriding any other assignment.<br />

1. Here, the term “user” refers to developers who use your <strong>BSP</strong> to build their VxWorks applications.<br />

In addition, if a value is not optional but always required and must not be edited,<br />

set it in bspname.h, not config.h.<br />

17


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

! CAUTION: A config.h file should not include configAll.h until after<br />

<strong>BSP</strong>_VERSION and <strong>BSP</strong>_REV have been defined. If they are not defined,<br />

configAll.h, assigns default values.<br />

If you include <strong>BSP</strong>-specific configuration options in config.h, try to make those<br />

options as user-friendly as possible. Ideally, users should immediately understand<br />

the use of an option from its name alone. In addition, do not expect users to<br />

perform calculations to set a configuration option. For example, you should make<br />

the code (or the compiler) figure out register values based on whether a<br />

meaningfully named constant is defined.<br />

Cache and MMU Configuration. The default cache and MMU configuration are<br />

architecture dependent. They are usually configured to maximize board<br />

performance. Depending on the architecture, cache and the MMU can be<br />

completely independent or highly integrated. Usually, when the MMU is enabled,<br />

it assumes control of caching on a page-by-page basis. This means that the macros<br />

USER_I_CACHE_MODE and USER_D_CACHE_MODE do not usually affect caching<br />

when the MMU is enabled. For detailed information on cache and MMU<br />

interactions, refer to the relevant VxWorks Architecture Supplement document.<br />

Most <strong>BSP</strong>s undefine the configAll.h default settings for cache and MMU, and<br />

redefine them in config.h just to allow users to make their own selections more<br />

easily. Doing so brings the settings to the direct attention of users when they make<br />

configuration changes. Of course, if cache mode is not a user-changeable option,<br />

these macros should be defined in bspname.h instead of config.h.<br />

Shared Memory Network Definitions. This section describes the parameters needed<br />

to configure the shared memory network driver (for additional information, refer<br />

to the VxWorks Network Programmer’s <strong>Guide</strong>: Data Link Layer Network Components).<br />

The shared memory network allows a number of CPU boards in a system to<br />

communicate via shared memory. The following constants are important when the<br />

shared memory network is initialized:<br />

SM_ANCHOR_ADRS<br />

The backplane anchor address. The anchor contains a pointer to the actual<br />

shared memory pool. If the on-board memory is being dual-ported, then the<br />

allocated memory’s low address + 0x600 is the default used by Wind River. If<br />

a memory board is used, then the base address of this memory is used.<br />

SM_MEM_ADRS<br />

The location of the shared memory. Specifying NONE means that the memory<br />

is to be dynamically located from the master’s on-board dual-ported memory<br />

using malloc( ).<br />

18


2<br />

<strong>BSP</strong> Organization<br />

SM_MEM_SIZE<br />

The size of the shared memory pool.<br />

SM_INT_TYPE<br />

The method of communication with other CPU boards on the backplane.<br />

Define SM_INT_TYPE to equal one of the macros listed in Table 2-1.<br />

2<br />

Table 2-1<br />

Shared Memory Interrupt Types<br />

SM_INT_TYPE SM_INT_ARG1 SM_INT_ARG2 SM_INT_ARG3 Meaning<br />

SM_INT_NONE - - - Polling<br />

SM_INT_BUS level vector - Bus interrupt<br />

SM_INT_MAILBOX_1 address space address value 1-byte write<br />

mailbox<br />

SM_INT_MAILBOX_2 address space address value 2-byte write<br />

mailbox<br />

SM_INT_MAILBOX_4 address space address value 4-byte write<br />

mailbox<br />

SM_INT_MAILBOX_R1 address space address - 1-byte read<br />

mailbox<br />

SM_INT_MAILBOX_R2 address space address - 2-byte read<br />

mailbox<br />

SM_INT_MAILBOX_R4 address space address - 4-byte read<br />

mailbox<br />

For information on changes made to the shared memory subsystem for Tornado<br />

2.2, see the Tornado Migration <strong>Guide</strong>.<br />

RAM Addresses and Size.<br />

LOCAL_MEM_LOCAL_ADRS<br />

The start of the on-board memory area.<br />

LOCAL_MEM_SIZE<br />

The fixed (static) memory size.<br />

19


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

LOCAL_MEM_AUTOSIZE<br />

Run-time (dynamic) memory sizing. For more information, see Wind River<br />

Technical Note #42.<br />

USER_RESERVED_MEM<br />

Reserved memory size (bytes). For more information, see Wind River Technical<br />

Note #41.<br />

RAM_HIGH_ADRS<br />

The destination address used for copying the boot ROM image. It is usually<br />

the on-board memory start address plus 0x00100000. This must be the same<br />

value as defined in the makefile (see Makefile and depend.bspname, p.15).<br />

ROM Addresses and Size.<br />

ROM_BASE_ADRS<br />

The ROM start address in hexadecimal.<br />

ROM_TEXT_ADRS<br />

The boot ROM entry address in hexadecimal. For most boards, this is set to the<br />

beginning of the ROM address area. However, there are boards that use some<br />

area at the start of the ROM address area for the reset vector. This must be the<br />

same value as defined in the makefile (see Makefile and depend.bspname, p.15).<br />

ROM_LINK_ADRS<br />

If used, this macro specifies the boot ROM link address in hexidecimal form.<br />

For most boards, this is set to the beginning of the ROM address area. If this<br />

address is present, the linker uses it to link the boot ROM image. Otherwise,<br />

ROM_TEXT_ADRS is used as the link address.<br />

ROM_WARM_ADRS<br />

The warm boot entry address. This is usually defined as an offset from<br />

ROM_TEXT_ADRS.<br />

ROM_SIZE<br />

The size of the ROM area in hexadecimal. This must be the same value as<br />

defined in the makefile (see Makefile and depend.bspname, p.15).<br />

Non-Volatile Memory. The routines sysNvRamSet( ) and sysNvRamGet( ) have an<br />

offset parameter. If NV_BOOT_OFFSET is greater than zero, you can access the bytes<br />

before the boot line by specifying a negative offset. To override the default value of<br />

NV_BOOT_OFFSET, first undefine the macro in config.h, then define it.<br />

20


2<br />

<strong>BSP</strong> Organization<br />

For boards without NVRAM, include the file mem/nullNvRam.c so that calls to<br />

NVRAM routines return ERROR. This file is provided on the <strong>BSP</strong> Kit CD-ROM in<br />

the target/src/drv/mem directory.<br />

There is a generic NVRAM driver called templateNvRam.c. See comments in this<br />

file for a description of the requirements and macros needed to use this driver. The<br />

templateNvRam.c file is appropriate for all boards where NVRAM is byte<br />

accessible, as opposed to block accessible.<br />

NV_RAM_SIZE<br />

The total bytes of NVRAM available. Define NV_RAM_SIZE in config.h. For<br />

boards without NVRAM, define NV_RAM_SIZE as NONE.<br />

BOOT_LINE_SIZE<br />

The number of bytes of NVRAM that are reserved for the VxWorks boot line.<br />

The default value is 255 and is defined in configAll.h. BOOT_LINE_SIZE must<br />

be less than or equal to NV_RAM_SIZE. To override the default value of<br />

BOOT_LINE_SIZE, first undefine the macro in config.h, then define it.<br />

2<br />

NV_BOOT_OFFSET<br />

The byte offset to the beginning of the VxWorks boot line in NVRAM. The<br />

default value is 0 and is defined in configAll.h.<br />

Default Bootline Parameters. The DEFAULT_BOOT_LINE macro provides an<br />

example bootline, which end users can alter to reflect their target environment.<br />

This is particularly useful for targets without NVRAM, because it means the end<br />

user does not have to re-enter the boot parameters on each power cycle.<br />

Timestamp Support. Each <strong>BSP</strong> should have timestamp support for the WindView<br />

product. The user configures timestamp support by defining or undefining the<br />

macro INCLUDE_TIMESTAMP. See the comments in the timer driver source file for<br />

a description of the additional support required by that specific driver.<br />

External Bus Address Mapping. VMEbus mapping is controlled by a series of nine<br />

macros for master window mapping and another set of nine standard macros for<br />

slave window mapping. The user configures VME by defining INCLUDE_VME in<br />

config.h. The VME mappings for A16, A24, and A32 space master access are<br />

controlled by a sequence of three macros each.<br />

It is assumed that the <strong>BSP</strong> honors all of these macros. If the hardware is fixed and<br />

one or more sets of these macros must have fixed values, then those macros should<br />

be moved from config.h to bspname.h. Only macros that the user can reasonably<br />

change should be in config.h.<br />

21


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Use the following macros to define the windows onto the VMEbus from the local<br />

CPU (bus master accesses):<br />

VME_A16_MSTR_SIZE<br />

VME_A16_MSTR_BUS<br />

VME_A16_MSTR_LOCAL<br />

VME_A24_MSTR_SIZE<br />

VME_A24_MSTR_BUS<br />

VME_A24_MSTR_LOCAL<br />

VME_A32_MSTR_SIZE<br />

VME_A32_MSTR_BUS<br />

VME_A32_MSTR_LOCAL<br />

Size of the window into A16 space.<br />

First bus address of A16 window.<br />

Local address of A16 window.<br />

Size of the window into A24 space.<br />

First bus address in A24 window.<br />

Local address of A24 window.<br />

Size of the window into A32space.<br />

First bus address in A32 window.<br />

Local address of A32 window.<br />

Use the following macros to define the windows from the VMEbus into local<br />

memory. By default, only CPU 0 exports its memory to an external bus. These<br />

macros control bus slave windows that make local memory visible to the VMEbus.<br />

Because of its small size, main memory is rarely mapped into an A16 slave<br />

window. Setting the size of any window to 0 should disable that window.<br />

VME_A16_SLV_SIZE<br />

VME_A16_SLV_BUS<br />

VME_A16_SLV_LOCAL<br />

VME_A24_SLV_SIZE<br />

VME_A24_SLV_BUS<br />

VME_A24_SLV_LOCAL<br />

VME_A32_SLV_SIZE<br />

VME_A32_SLV_BUS<br />

VME_A32_SLV_LOCAL<br />

Size of the window onto A16 space.<br />

Bus address of A16 window.<br />

Local address mapped into A16 window.<br />

Size of the window onto A24 space.<br />

Bus address of A24 window.<br />

Local address mapped into A24 window.<br />

Size of the window onto A32space.<br />

Bus address of A32 window.<br />

Local address mapped into A32 window.<br />

A standard set of macros to describe PCI address mapping has not yet been<br />

formalized. Contact Wind River for the latest PCI interface standards. For<br />

additional information, see Wind River Technical Note #44 and<br />

target/src/drv/vme/templateVme.c.<br />

PCI Address Macros. For PCI, you should describe at least 1 and sometimes 4<br />

windows reaching from local bus space to PCI spaces. These are called the master<br />

windows because the local CPU is the bus master for these transactions.<br />

PCI_MSTR_MEM_SIZE<br />

PCI_MSTR_MEM_BUS<br />

PCI_MSTR_MEM_LOCAL<br />

PCI_MSTR_IO_SIZE<br />

PCI_MSTR_IO_BUS<br />

Size of the window onto PCI memory space.<br />

Bus address of PCI memory window.<br />

Local address mapped into PCI memory<br />

window.<br />

Size of the window onto PCI I/O space.<br />

Bus address of PCI I/O window.<br />

22


2<br />

<strong>BSP</strong> Organization<br />

PCI_MSTR_IO_LOCAL Local address mapped into PCI I/O window.<br />

PCI_MSTR_MEMIO__SIZE Size of the window onto PCI memory<br />

(non-prefetched).<br />

PCI_MSTR_MEMIO_BUS Bus address of PCI non-prefetched memory<br />

window.<br />

PCI_MSTR_MEMIO_LOCAL Local address mapped into non-prefetched<br />

window.<br />

Not all PCI spaces are implemented in every situation. Note that there are different<br />

windows mapping main memory. The default window is for prefetchable memory<br />

operations. The second window, PCI_MSTR_MEMIO, is for performing<br />

non-prefetchable operations. One or both of these windows to main memory is<br />

always mapped. Our standard signal to disable a window is to set the size value<br />

to zero, which should disable access from local memory to that space.<br />

For more information on PCI macros, please refer to Wind River Technical Note #49.<br />

2<br />

romInit.s<br />

Network Device and Interrupt Vector. If this <strong>BSP</strong> uses external boards for network<br />

devices, then the bus addresses and interrupt vector assignments are user options<br />

presented in config.h.<br />

bspname.h. This file is normally included after all option selections. This allows<br />

tests to be inserted into bspname.h to check for proper selection combinations. An<br />

example would be a board that has two different Ethernet options, only one of<br />

which can be selected at a time. In this case, the bspname.h file would check to see<br />

if both were defined and generate an error message, if necessary.<br />

Another example would be to add additional features required to support a<br />

user-selected feature. For example, the user might select NFS support, and the<br />

bspname.h file would add RPC and network support as being required to support<br />

NFS. This is precisely what usrExtra.c does for usrConfig.c. Of course, this is just<br />

a hypothetical illustration of the concept, not an actual example.<br />

This file contains the assembly language source for initialization code that is the<br />

entry point for the VxWorks boot ROMs and ROM-based versions of VxWorks.<br />

The entry point, romInit( ), is the first code executed on power-up. It sets the<br />

BOOT_COLD parameter to be passed to the generic romStart( ) routine. If the<br />

hardware requires immediate memory mapping or setting special registers,<br />

handle it here. Most hardware initialization occurs using the sysHwInit( ) routine<br />

in sysLib.c.<br />

23


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

sysALib.s<br />

There are three main functions that must be performed by romInit( ):<br />

■<br />

Disable interrupts and set up the CPU.<br />

■<br />

Set up the memory system. This usually involves turning off caches and<br />

setting up memory controllers as needed. For the SPARC architecture, the<br />

MMU must be enabled.<br />

■<br />

Set up the stack pointer and other registers to begin executing C code. The<br />

address of the romStart( ) routine is calculated and the routine is called. There<br />

is no return from romStart( ).<br />

It is important to note that romInit( ) must be coded as position-independent code<br />

(PIC). This is needed to support the complex boot strategies of VxWorks. If an<br />

address cannot be made PC-relative, then it must be recomputed by subtracting<br />

the symbol romInit and adding the value ROM_TEXT_ADRS. This is usually done<br />

by a macro ROM_ADRS.<br />

#define ROM_ADRS(x) ((x) - _romInit + ROM_TEXT_ADRS)<br />

It is a common mistake for <strong>BSP</strong> writers to attempt too much initialization in<br />

romInit.s. Most other initialization functions are quite easily deferred to the<br />

sysHwInit( ) function. Additionally, code in romInit.s should not call out to other<br />

modules or routines. This causes linking problems for the compressed boot ROM<br />

image and negates any benefits of compression.<br />

Calling out from romInit.s to C level routines is possible but discouraged. Certain<br />

C code uses absolute addressing rather than PC relative code and is therefore not<br />

PIC. If a C routine is needed, then it should not be part of sysLib.c. Such a routine<br />

should be placed in a separate module and included into the system by adding the<br />

module to the makefile variable BOOT_EXTRA.<br />

Another common mistake made by <strong>BSP</strong> writers is to assume that devices<br />

initialized by romInit.s do not need to be reinitialized by sysALib.s or sysLib.c.A<br />

VxWorks image does not assume that it was booted by the VxWorks bootrom<br />

program. It must reset and reinitialize all devices and features for itself. Failure to<br />

do this makes proper operation of a VxWorks image dependent on code executed<br />

by a bootrom image. Linking of bootrom and VxWorks images in this way is not<br />

desirable.<br />

This file contains the assembler source of target-specific, system-dependent<br />

routines. All <strong>BSP</strong> routines should be coded in C. However, if there are compelling<br />

technical reasons for resorting to assembler, you can place the routines in<br />

sysALib.s.<br />

24


2<br />

<strong>BSP</strong> Organization<br />

The entry point of the VxWorks image, _sysInit, is located in sysALib.s. It is the<br />

first code executed after booting (see sysALib.s: sysInit( ), p.34). It is usual here to<br />

perform all the functions performed by romInit.s, except for system memory<br />

setup. The memory system should be initialized at this stage of the startup<br />

procedure.<br />

Unlike romInit.s, code in sysALib.s does not need to be written as PIC or to use<br />

the ROM_ADRS macro to remap absolute addresses. It can call out to other<br />

modules and routines.<br />

2<br />

sysLib.c<br />

sysSerial.c<br />

sysScsi.c<br />

This file contains the C source of target-specific, system-dependent sysLib<br />

routines. These routines provide the board-level interface on which VxWorks and<br />

application code can be built in a system-independent way. Note that sysLib.c can<br />

include drivers from the src/drv directory and that these drivers can include some<br />

of the routines listed below. For more information, see 5. Driver <strong>Guide</strong>lines and<br />

F. Generic Drivers.<br />

Driver setup and initialization is usually done in a subfile, which is included in<br />

sysLib.c. Common subfiles are named: sysSerial.c, sysScsi.c, sysNet.c, and so on.<br />

The purpose of using subfiles is keeping the setup and initialization of a particular<br />

device constant across all architectures. The setup file for one board using a<br />

particular device should be the same for any other board using that same device.<br />

Not every feature of a particular board is necessarily supported by this <strong>BSP</strong><br />

abstraction. Some boards provide functions with jumpers or PALs instead of<br />

software controllable/readable registers. Other hardware configurations might<br />

not support some normally expected basic features.<br />

When features are missing, it is usually safe to code an empty stub that returns<br />

ERROR or NULL (whichever is appropriate), if any return value is required.<br />

This optional file contains all the serial I/O setup and initialization for the SIO<br />

device drivers. It is not separately compiled, but is included from sysLib.c. The<br />

purpose of separating serial initialization from sysLib.o is to modularize the code<br />

and allow reuse of code between <strong>BSP</strong>s.<br />

This optional file contains the SCSI-2 setup and initialization for the <strong>BSP</strong>. Like<br />

sysSerial.c, it is included in sysLib.c.<br />

25


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

sysNet.c<br />

bspname.h<br />

Optional setup and initialization for network interface devices.<br />

Use bspname.h to set all non-optional, board-specific information as defined in this<br />

file, including definitions for the serial interface, timer, and I/O devices. The<br />

directory target/h/drv is where much of the information is located. The header files<br />

of the drivers needed to port VxWorks to your board should be included at the<br />

beginning of bspname.h.<br />

This file is intended for constant information that is not subject to user<br />

configuration. If any macros or values defined in bspname.h can be changed to<br />

customize the system, then define those macros or values in config.h instead.<br />

It is helpful to use a sample header file, because most constant names, basic device<br />

addresses, and so on are already defined and just require refinement. The<br />

following should be defined in bspname.h:<br />

■<br />

interrupt vectors/levels<br />

■<br />

I/O device addresses<br />

■<br />

the meaning of the device register bits<br />

■<br />

system and auxiliary clock parameters (maximum and minimum rates)<br />

Also, use a board description macro prefix (for example, Heurikon is defined as<br />

HK_) to indicate values that are board-specific.<br />

Interrupt Vectors and Levels. Define all interrupt vectors and levels dictated by<br />

hardware and not user changeable in bspname.h.<br />

I/O Device Addresses. Define all I/O addresses fixed by hardware or otherwise<br />

not user-changeable in bspname.h.<br />

Meaning of Device Register Bits. For on-board control registers, define a macro<br />

value for each bit or group of bits in each registers. Typically, such macro<br />

definitions are placed in bspname.h if there is no better location for them.<br />

System and Auxiliary Clocks. When given a new clock rate, the timer drivers use<br />

these macros to determine if the new rate is valid:<br />

SYS_CLK_RATE_MIN<br />

SYS_CLK_RATE_MAX<br />

AUX_CLK_RATE_MIN<br />

AUX_CLK_RATE_MAX<br />

Sets the minimum system clock rate.<br />

Sets the maximum system clock rate.<br />

Sets the minimum auxiliary clock rate.<br />

Sets the maximum auxiliary clock rate.<br />

26


2<br />

<strong>BSP</strong> Organization<br />

target.nr<br />

The file target.nr, located in the target/config/bspname directory, contains<br />

board-specific information necessary to run VxWorks. To provide a convenient<br />

starting point for a new <strong>BSP</strong>, the <strong>BSP</strong> Porting Kit CD-ROM includes several<br />

architecture-specific templates, such as target/config/template68k/target.nr.<br />

For Tornado 2.x, the target.nr file is not processed as a UNIX-style reference page<br />

or Windows-compatible text page. It is delivered to the customer as an HTML file.<br />

Refer to L. Refgen for details on the refgen documentation utility.<br />

This reference entry is divided into the following sections:<br />

NAME<br />

The name of the board.<br />

INTRODUCTION<br />

Summary of scope and assumptions. Instructions concerning boot ROMs and<br />

necessary jumper settings.<br />

FEATURES<br />

Summary of all supported and unsupported features of the board.<br />

HARDWARE DETAILS<br />

Summary of available devices, for example, serial, Ethernet, and SCSI.<br />

SPECIAL CONSIDERATIONS<br />

Special features or restrictions.<br />

BOARD LAYOUT<br />

An ASCII representation of the board, useful for illustrating boot ROMs and<br />

jumpers. Jumpers and jumper states are represented by the characters shown<br />

in Table 2-2.<br />

SEE ALSO<br />

References to other relevant VxWorks manuals.<br />

BIBLIOGRAPHY<br />

Summary of data sheets and other sources of technical information pertinent<br />

to the board and devices.<br />

2<br />

27


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Table 2-2<br />

ASCII Representation of Board Layout<br />

Jumper Type State Character<br />

Vertical jumper Installed x<br />

Vertical jumper Open : (colon)<br />

Vertical jumper (three-pin) Up U<br />

Vertical jumper (three-pin) Down D<br />

Horizontal jumper Installed - (dash)<br />

Horizontal jumper Open " (quote)<br />

Horizontal jumper (three-pin) Left L<br />

Horizontal jumper (three-pin) Right R<br />

2.2.2 Derived Files<br />

The following files are derived from the source files, the system header files, driver<br />

source files, and modules in the VxWorks archive libraries. These files are only<br />

delivered for demonstration purposes. The user recreates some or all of these files<br />

when configuring a system.<br />

When you are working with a Tornado 2.x project, these derived files are found in<br />

the project directory. Their counterparts in the <strong>BSP</strong> directory are used only when<br />

building from the traditional command-line method.<br />

NOTE: As of this release, boot ROMs cannot be built from the Tornado project<br />

facility. Enhancement of the project facility to configure and build boot ROM<br />

images is planned.<br />

bootInit.o, bootInit_res.o, and bootInit_uncmp.o<br />

There are three boot strategies available: compressed ROMs, uncompressed<br />

ROMs, and ROM-resident ROMs. All three strategies can be used for boot ROMs<br />

or VxWorks ROMs. The name of the module indicates the strategy it is used with.<br />

28


2<br />

<strong>BSP</strong> Organization<br />

bootrom<br />

This file is an object module containing the binary VxWorks boot ROM.<br />

2<br />

bootrom.hex<br />

This is an ASCII file containing the VxWorks boot ROM code, suitable for<br />

downloading over a serial connection to a PROM programmer. The default<br />

encoding uses Motorola S-Records.<br />

bootrom.Z.s and bootrom.Z.o<br />

ctdt.o<br />

dataSegPad.o<br />

This is the source and object output that is the compressed image of the bootrom.o<br />

module.<br />

This module handles C++ constructor/destructor functionality.<br />

The module insuring that the text and data segments do not share a common<br />

memory page. For the VxVMI option, this module forces alignment of the data<br />

segment in a different MMU page from the text segment.<br />

symTbl.c and sysALib.o<br />

These are the source and object files for the built-in symbol table.<br />

sysLib.o and sysALib.o<br />

romInit.o<br />

These modules always go together as a pair. They are the output of the sysALib.s<br />

and sysLib.c modules.<br />

This module is the startup code for any ROM image, boot or VxWorks. For<br />

Tornado, it works in conjunction with the romStart.o module instead of bootInit.o.<br />

vxWorks and vxWorks.sym<br />

The vxWorks file is the complete, linked VxWorks binary to be run on the target.<br />

The vxWorks.sym file is the symbol table for the VxWorks binary. Both files are<br />

created with the supplied configuration files.<br />

29


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

vxWorks.st<br />

This file is the complete, linked, standalone VxWorks binary with the symbol table<br />

linked in.<br />

target/proj/bspname_gnu/* and target/proj/bspname_diab/*<br />

These directories contain the <strong>BSP</strong> project files and default build outputs. There are<br />

two ways to create a new project: the preferred method uses the project facility; the<br />

alternative uses the command make prj_gnu or make prj_diab from the command<br />

line.<br />

doc/vxworks/bsp/bspname/*.*<br />

This directory contains the HTML documentation files that are incorporated into<br />

the user’s help system when the product is installed. This documentation is<br />

generated from the command line with the command make man.<br />

2.2.3 Required Routines<br />

The following routines are expected to be found in the sysLib.o module. If any<br />

routine is missing, then an unresolved global error is encountered during linking.<br />

sysBspRev( ) - return the <strong>BSP</strong> version and revision number<br />

sysClkConnect( ) - connect a routine to the system clock interrupt<br />

sysClkDisable( ) - turn off system clock interrupts<br />

sysClkEnable( ) - turn on system clock interrupts<br />

sysClkInt( ) - handle system clock interrupts (internal)<br />

sysClkRateGet( ) - get the system clock rate<br />

sysClkRateSet( ) - set the system clock rate<br />

sysHwInit( ) - initialize the system hardware<br />

sysHwInit2( ) - initialize additional system hardware<br />

sysMemTop( ) - get the address of the top of logical memory<br />

sysModel( ) - return the model name of the CPU board<br />

sysNvRamGet( ) - get the contents of non-volatile RAM<br />

sysNvRamSet( ) - write to non-volatile RAM<br />

30


2<br />

<strong>BSP</strong> Organization<br />

sysSerialHwInit( ) - initialize the <strong>BSP</strong> serial devices to a quiescent state<br />

sysSerialHwInit2( ) - connect <strong>BSP</strong> serial device interrupts<br />

sysSerialChanGet( ) - get the SIO_CHAN device associated with a serial<br />

channel<br />

sysToMonitor( ) - transfer control to the ROM monitor<br />

2<br />

2.2.4 Optional Routines<br />

The following routines are usually present on all targets. Those marked as<br />

“internal” are internal to the <strong>BSP</strong> and are not called by the application.<br />

sysAbortInt( ) - handle the ABORT button interrupt<br />

sysAuxClkConnect( ) - connect a routine to the auxiliary clock interrupt<br />

sysAuxClkDisable( ) - turn off auxiliary clock interrupts<br />

sysAuxClkEnable( ) - turn on auxiliary clock interrupts<br />

sysAuxClkInt( ) - handle auxiliary clock interrupts<br />

sysAuxClkRateGet( ) - get the auxiliary clock rate<br />

sysAuxClkRateSet( ) - set the auxiliary clock rate<br />

sysPhysMemTop( ) - get the address of the top of physical memory<br />

The following routines are normally present only on targets that have a bus<br />

interface:<br />

sysProcNumGet( ) - get the processor number<br />

sysProcNumSet( ) - set the processor number<br />

sysBusIntAck( ) - acknowledge a bus interrupt<br />

sysBusIntGen( ) - generate a bus interrupt<br />

sysBusTas( ) - test and set a location across the bus<br />

sysBusTasClear( ) - clear a location set by sysBusTas( )<br />

sysBusToLocalAdrs( ) - convert a bus address to a local address<br />

sysIntDisable( ) - disable a bus interrupt level<br />

sysIntEnable( ) - enable a bus interrupt level<br />

sysLocalToBusAdrs( ) - convert a local address to a bus address<br />

31


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

sysMailboxConnect( ) - connect a routine to the mailbox interrupt<br />

sysMailboxEnable( ) - enable the mailbox interrupt<br />

sysMailboxInt( ) - handle the mailbox interrupt (internal)<br />

sysNanoDelay( ) - set a calibrated delay (spin loop)<br />

2.3 VxWorks Boot Sequence<br />

This section describes a typical VxWorks boot scenario. Fundamentally, all<br />

processors execute the same logical steps when initializing and loading VxWorks,<br />

although some may require an extra step or two, and others may skip certain steps.<br />

Minimally, initializing a processor consists of providing a portion of code and<br />

possibly some tables located at a specific location in memory that the processor<br />

always jumps to on reset or power-up. This code sets the processor in a specific<br />

state, initializes memory and memory addressing, disables interrupts, and then<br />

passes control to additional bootstrapping code.<br />

This section covers the boot sequence step-by-step for various configurations and<br />

architectures. In some cases, this description can only provide an approximate<br />

guide to the processor boot sequence because there may be unique variations for<br />

specialized chips, such as the M68302 embedded controller.<br />

To see the boot sequence for an image built from the traditional command line,<br />

refer to D. VxWorks Boot Sequence. To see the boot sequence for an image built using<br />

the project tool, refer to E.3 Project Initialization Order, p.238.<br />

2.3.1 Processor Variances<br />

The VxWorks Motorola 680x0 heritage is evident in the VxWorks boot sequence;<br />

fortunately, most processors accommodate this scenario.<br />

The Intel i960 is unique in requiring an Initial Boot Record (IBR) that contains an<br />

exhaustive processor configuration table defining memory regions, interrupt table<br />

information, exception handling, and so on. In a way, this is the first code executed<br />

on the processor and must be in a fixed location, such as the Stack Pointer and<br />

Program Counter on many other processors.<br />

32


2<br />

<strong>BSP</strong> Organization<br />

The Motorola M68040 must be put in a transparent memory-mapping mode.<br />

The Motorola M683xx family is a special case. These processors run on busless<br />

boards that communicate with the outside world via serial lines; for this reason,<br />

the boot ROMs contain an embedded standalone VxWorks shell<br />

(vxWorks.st_rom.hex). This type of configuration may become more prevalent in<br />

future busless systems.<br />

2<br />

2.3.2 Sequence Overview<br />

The processor is first “jumped” to the entry point in ROM, which sets the status<br />

word and creates a dummy stack; then it jumps toaCroutine. A parameter on the<br />

dummy stack determines whether to clear memory (cold start), and then copies the<br />

rest of ROM into RAM (if the remainder of the ROM is compressed, then it is<br />

uncompressed during the copy). Next, the processor jumps to the entry point in<br />

RAM. 2<br />

The RAM entry point in bootConfig.c disables the cache, clears the bss segment to<br />

zero, initializes the vector table, performs board specific initialization, and then<br />

starts the multitasking kernel with a user booting task as its only activity.<br />

The VxWorks boot ROM image is a standalone application in its own right. The<br />

developer uses it to boot a new VxWorks image over the network and link in<br />

application code. The boot ROM’s kernel is discarded; there is no trap mechanism<br />

or reuse of this code. The application is linked with a new image built on the host.<br />

2.3.3 Files and Routines<br />

This section contains a more detailed explanation of how booting takes place,<br />

organized by file and routine name. For clarity, the sequence has been broken<br />

down into a number of main steps or function calls. The key functions are listed as<br />

headings and shown in invocation order.<br />

romInit.s: romInit( )<br />

At power-up (cold start) the processor begins execution at romInit( ), always the<br />

first routine in romInit.s. For warm starts, the processor begins execution at<br />

2. The reason for executing the text segment from RAM is partly for speed (although it is not<br />

faster in all situations), and to allow a uniform model for uncompression, which may be<br />

insufficient reason for an application to retain this model, especially at the cost of wasted<br />

RAM. Either way, the data segment and bss (uninitialized data) must be in RAM.<br />

33


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

romInit( ) plus a small offset (see sysToMonitor( ) in sysLib.c). The romInit( )<br />

routine disables interrupts, puts the boot type (cold/warm) on the stack, clears<br />

caches, and branches to romStart( ) in bootInit.c. The stack is placed to begin<br />

before the text section and grows in the opposite direction. The routine romInit( )<br />

must do as little device setup as possible to start executing C code. Hardware<br />

initialization is the function of the sysHwInit( ) routine in sysLib.c.<br />

bootInit.c: romStart( )<br />

The text and data segments are copied from ROM to RAM in these ways:<br />

■<br />

■<br />

■<br />

If the text segment is not ROM-resident, the text and data segments are copied.<br />

If the text segment is ROM-resident, only the data segment is copied.<br />

Unused memory is cleared to initialize it.<br />

■<br />

If necessary, decompression is done.<br />

Atypically, the i960 invokes sysInit(bootType), which eventually invokes<br />

usrInit(bootType), as on all other architectures.<br />

sysALib.s: sysInit( )<br />

VxWorks calls sysInit( ) in normal rebooting to avoid code redundancy, the i960<br />

calls the routine during ROM initialization as well. The sysInit( ) routine, which<br />

must always be the first routine defined in sysALib.s, invalidates caches if<br />

applicable, initializes the system interrupt tables with default stubs, initializes the<br />

system fault tables with default stubs, and initializes all the processor registers to<br />

known default values. It enables tracing, clears all pending interrupts and finally<br />

invokes usrInit(bootType).<br />

This routine must duplicate the hardware initialization done by romInit( ). If not,<br />

then features set up in the boot ROM code could transfer to the VxWorks image.<br />

This is very undesirable as the configuration and initialization actions of the boot<br />

ROM would have influence over the run-time VxWorks images. It would likely<br />

result in the user rebuilding boot ROMs for configuration changes. It might also<br />

result in the user having to use paired sets of boot ROMs and VxWorks images.<br />

usrConfig.c and bootConfig.c: usrInit( )<br />

The usrInit( ) routine (in usrConfig.c) saves information about the boot type,<br />

handles all the initialization that must be performed before the kernel is actually<br />

started, and then starts the kernel execution. It is the first C code to run in VxWorks.<br />

It is invoked in supervisor mode with all hardware interrupts locked out.<br />

34


2<br />

<strong>BSP</strong> Organization<br />

Many VxWorks facilities cannot be invoked from this routine. Because there is no<br />

task context as yet (no TCB and no task stack), facilities that require a task context<br />

cannot be invoked. This includes any facility that can cause the caller to be<br />

preempted, such as semaphores, or any facility that uses such facilities, such as<br />

printf( ). Instead, the usrInit( ) routine does only what is necessary to create an<br />

initial task, usrRoot( ). This task then completes the startup.<br />

The initialization in usrInit( ) includes the following:<br />

■<br />

■<br />

■<br />

Cache Initialization. The code at the beginning of usrInit( ) initializes the<br />

caches, sets the mode of the caches and puts the caches in a safe state. At the<br />

end of usrInit( ), the instruction and data caches are enabled by default.<br />

Zeroing Out the System bss Segment. The C and C++ languages specify that<br />

all uninitialized variables must have initial values of 0. These uninitialized<br />

variables are put together in a segment called the bss. This segment is not<br />

actually loaded during the bootstrap, because it is known to be zeroed out.<br />

Because usrInit( ) is the first C code to execute, it clears the section of memory<br />

containing bss as its very first action. While the VxWorks boot ROMs clear all<br />

memory, VxWorks does not assume that the boot ROMs are used.<br />

Initializing Interrupt Vectors. The exception vectors must be set up before<br />

enabling interrupts and starting the kernel. First, intVecBaseSet( ) is called to<br />

establish the vector table base address.<br />

2<br />

! CAUTION: For some architectures, there are exceptions to the rule that<br />

intVecBaseSet( ) must be called before enabling interrupts and starting the kernel.<br />

See the appropriate VxWorks Architecture Supplement document.<br />

After intVecBaseSet( ) is called, the routine excVecInit( ) initializes all exception<br />

vectors to default handlers that safely trap and report exceptions caused by<br />

program errors or unexpected hardware interrupts.<br />

Initializing System Hardware to a Quiescent State. System hardware is initialized<br />

by calling the system-dependent routine sysHwInit( ). This mainly consists of<br />

resetting and disabling hardware devices that can cause interrupts after interrupts<br />

are enabled (when the kernel is started). This is important because VxWorks ISRs<br />

(for I/O devices, system clocks, and so on) are not connected to their interrupt<br />

vectors until the system initialization is completed in the usrRoot( ) task. However,<br />

because the memory pool is not yet initialized, you must not try to connect an<br />

interrupt handler to an interrupt during the sysHwInit( ) call.<br />

35


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

lib/*.a: kernelInit( )<br />

The kernelInit( ) routine initiates the multitasking environment and never returns.<br />

It takes the following parameters:<br />

– The application to be spawned as the “root” task, typically usrRoot( ).<br />

– The stack size.<br />

– The start of usable memory; that is, the memory after the main text, data, and<br />

bss of the VxWorks image. All memory after this area is added to the system<br />

memory pool, which is managed by memPartLib. Allocation for dynamic<br />

module loading, task control blocks, stacks, etc., all come out of this region.<br />

– The top of memory as indicated by sysMemTop( ). If a contiguous block of<br />

memory is to be preserved from normal memory allocation, set the macro<br />

USER_RESERVED_MEM in config.h to the amount of reserved memory<br />

desired.<br />

– The interrupt stack size. The interrupt stack corresponds to the largest amount<br />

of stack space that could be used by any interrupt-level routine that might be<br />

called (plus a safe margin for the nesting of interrupts).<br />

– The interrupt lock-out level. For architectures that have a level concept, it is the<br />

maximum level. For architectures that do not have a level concept, it is the<br />

mask to disable interrupts. See the appropriate VxWorks Architecture<br />

Supplement.<br />

The kernelInit( ) routine calls intLockLevelSet( ), disables round-robin mode, and<br />

creates an interrupt stack if supported by the architecture. It then creates a root<br />

stack and TCB from the top of the memory pool, spawns the root task, usrRoot( ),<br />

and terminates the usrInit( ) thread of execution. At this time, interrupts are<br />

enabled; it is critical that all interrupt sources are disabled and pending interrupts<br />

cleared.<br />

usrConfig.c and bootConfig.c: usrRoot( )<br />

For the generic VxWorks development environment, usrRoot( ) initializes the I/O<br />

system, installs drivers, creates devices, and then sets up the network as<br />

configured in configAll.h and config.h.<br />

The usrRoot( ) routine calls memInit( ). Optionally, it calls memShowInit( ) and<br />

usrMmuInit( ).<br />

The routine sysClkConnect( ) is the first routine called in the <strong>BSP</strong> after the system<br />

is multitasking. It immediately calls sysHwInit2( ). This is an opportune time for<br />

36


2<br />

<strong>BSP</strong> Organization<br />

further board initialization that could not be completed in sysHwInit( ); for<br />

example, an intConnect( ) of additional devices may be done in sysHwInit2( ).<br />

The 60 Hz system clock is set up by calling sysClkRateSet( ) and sysClkEnable( ).<br />

VxWorks can be booted without the system clock running. However, network<br />

drivers, when they attach, usually execute a taskDelay( ) to allow hardware reset<br />

to complete. If the system clock is not running, the delay does not expire, causing<br />

the system to hang.<br />

The system clock can be dynamically changed from the shell or application<br />

programs. However, facilities that take a “snapshot” of the clock rate (for example,<br />

spyLib) can be broken by such an unexpected rate change.<br />

If INCLUDE_IO_SYSTEM is defined in configAll.h, the VxWorks I/O system is<br />

initialized by calling the routine iosInit( ). The arguments specify the maximum<br />

number of drivers that can be subsequently installed, the maximum number of<br />

files that can be open in the system simultaneously, and the desired name of the<br />

“null” device that is included in the VxWorks I/O system. This null device is a<br />

“bit-bucket” on output and always returns end-of-file for input.<br />

The inclusion or exclusion of INCLUDE_IO_SYSTEM also affects whether the<br />

console devices are created, and whether standard in, standard out, and standard<br />

error are set; see the next two sections for more information.<br />

If the driver for the on-board serial ports is included (INCLUDE_TTY_DEV), it is<br />

installed in the I/O system by calling the driver’s initialization routine, typically<br />

ttyDrv( ). The actual devices are then created and named by calling the driver’s<br />

device-creation routine, typically ttyDevCreate( ). The arguments to this routine<br />

include the device name, a serial I/O channel descriptor (from the <strong>BSP</strong>), and input<br />

and output buffer sizes.<br />

The macro NUM_TTY specifies the number of tty ports (default is 2);<br />

CONSOLE_TTY specifies which port is the console (default is 0); and<br />

CONSOLE_BAUD_RATE specifies the bps rate (default is 9600). These macros are<br />

specified in configAll.h, but can be overridden in config.h for boards with a<br />

nonstandard number of ports.<br />

PCs can use an alternative console with keyboard input and VGA output; see your<br />

PC workstation documentation for details.<br />

The excInit( ) routine is called to initialize exception handling. Other facilities are<br />

optionally initialized at this point, as specified by macros in configAll.h. (See also<br />

VxWorks Programmer’s <strong>Guide</strong>: Configuration.)<br />

If INCLUDE_WDB is defined, wdbConfig( ) in src/config/usrWdb.c is called. This<br />

routine initializes the agent’s communication interface, then starts the agent. For<br />

2<br />

37


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

information on configuring the agent and the agent’s initialization sequence, see<br />

the Tornado User’s <strong>Guide</strong>: Setup and Startup.<br />

If the INCLUDE_USR_APPL is defined, the code executes the USER_APPL_INIT<br />

macro. However, you must make sure the USER_APPL_INIT macro is a valid C<br />

statement.<br />

2.4 Mistakes To Be Avoided<br />

Most of the mistakes listed below could be summarized as doing the right thing in<br />

the wrong place or at the wrong time. Context matters.<br />

Forgetting About LOCAL_MEM_LOCAL_ADRS<br />

Many <strong>BSP</strong> writers assume that LOCAL_MEM_LOCAL_ADRS is zero and fail to<br />

include it in macros that need to be offset by the start of memory. Most users do not<br />

change the value of LOCAL_MEM_LOCAL_ADRS, but this problem tends to be<br />

copied and replicated throughout development projects.<br />

Doing Too Much in romInit.s<br />

Many <strong>BSP</strong> writers try to put too much device initialization code into romInit.s. Use<br />

the initialization in romInit.s as just a preliminary step. Handle the real device<br />

initialization in sysHwInit( ) in sysLib.c. See romInit.s: romInit( ), p.33.<br />

Doing Too Little in sysALib.s<br />

Many <strong>BSP</strong> writers believe that any initialization done in romInit.s only needs to be<br />

done once. The routine sysInit( ), in sysALib.s, should repeat all initialization<br />

done by romInit.s. It may skip memory controller setup in some situations. Failure<br />

to do this requires users to rebuild boot ROMs for simple configuration changes in<br />

their VxWorks images. See sysALib.s: sysInit( ), p.34.<br />

Modified Drivers Put in the Wrong Directory<br />

<strong>BSP</strong> writers frequently modify Wind River device drivers, as well as provide their<br />

own drivers. These <strong>BSP</strong>-specific drivers must be delivered in <strong>BSP</strong>-specific<br />

directories and not in the Wind River directories target/src/drv and target/h/drv.<br />

<strong>BSP</strong>-specific code belongs in the <strong>BSP</strong>-specific directory target/config/bspname. This<br />

38


2<br />

<strong>BSP</strong> Organization<br />

can have very undesirable effects for customers using multiple <strong>BSP</strong>s from different<br />

sources. Only Wind River original code is allowed in these directories.<br />

Confusing Configuration Options<br />

In the file config.h, the user should be presented with clear choices for configuring<br />

the <strong>BSP</strong>. Material where the user does not have a choice should not be in config.h,<br />

it should be in bspname.h. The user should not have to compute values to be<br />

entered into config.h. If a register needs to be loaded with the high 16 bits of an<br />

address, the user should enter the full address. The code does the computation of<br />

the value to load in the register. The user should not have to do this; see <strong>BSP</strong><br />

Contents, p.196.<br />

2<br />

Using Non-Maskable Interrupts (NMI)<br />

Because the wind kernel uses intLock( ) as the primary method for protecting<br />

kernel data structures, using non-maskable interrupts (NMI) should be avoided. If<br />

an NMI interrupt service routine (ISR) makes a call to VxWorks that results in a<br />

kernel object being changed, then protection is lost and undesirable behavior can<br />

be expected. For more information on ISRs at high interrupt levels, refer to the<br />

VxWorks Programmer’s <strong>Guide</strong>: Basic OS.<br />

Also note that a VxWorks routine marked as interrupt safe does not mean it is NMI<br />

interrupt safe. On the contrary, many routines marked as interrupt safe are actually<br />

unsafe for NMI.<br />

39


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

40


3<br />

Creating a New <strong>BSP</strong><br />

3.1 Introduction<br />

Creating a new <strong>BSP</strong> using tools available under Tornado requires that you handle<br />

the development in graduated steps, each building on the previous, as follows:<br />

1. Set up the basis of the development environment.<br />

2. Write the <strong>BSP</strong> pre-kernel initialization code.<br />

3. Start a minimal VxWorks kernel and add the basic drivers for timers, serial<br />

devices, and an interrupt controller.<br />

4. Start the target agent and connect the Tornado development tools.<br />

5. Complete the <strong>BSP</strong>. Topics include networking, boot ROMs, SCSI, caches, MMU<br />

initialization, and DMA.<br />

6. Generate a default project for use with the new project facility.<br />

This chapter provides a detailed description of each of the steps listed above.<br />

The goal of this procedure is not only the creation of a new <strong>BSP</strong> but the<br />

minimization of the time during which you do not have access to the Tornado<br />

development tools—in particular, the Wind Debug target agent (WDB agent).<br />

Because the WDB agent is linked to the kernel, it can share initialization code with<br />

the kernel. Thus, after the initialization code has run, you can start either the WDB<br />

agent, the VxWorks kernel, or both.<br />

Using the WDB agent, you can debug the VxWorks image to which it is linked.<br />

This is in contrast to a traditional ROM-monitor approach which requires that you<br />

first port the monitor to the board and then port the OS.<br />

41


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

The target agent’s linked-in approach has several advantages over the traditional<br />

approach:<br />

■<br />

■<br />

There is only one initialization code module to write. In a traditional<br />

ROM-monitor approach, you must write two initialization code modules: one<br />

for the monitor and one for the OS. In addition, the traditional approach<br />

requires non-standard modifications to resolve contention issues over MMU,<br />

vector table, and device initialization. 1<br />

The code size is smaller because VxWorks and the target agent can share<br />

generic library routines such as memcpy( ).<br />

■<br />

Traditional ROM monitors debug only in “system mode.” The whole OS is<br />

debugged as a single thread. The WDB agent provides, in addition to system<br />

mode, a fully VxWorks-aware tasking mode. This mode allows debugging<br />

selected parts of the OS (such as individual tasks), without affecting the rest of<br />

the system.<br />

How you download the WDB agent and VxWorks kernel depends on your phase<br />

of development. When writing and debugging the board initialization code, you<br />

must create your own download path. This is no better or worse than the<br />

traditional ROM-monitor approach in which you had to create the download path<br />

for porting the monitor itself. After you have the board initialization code working,<br />

how you proceed depends on the speed of your download path.<br />

If you have a fast download path, continue to use it for further kernel<br />

development. This is a win over a traditional ROM monitor approach which often<br />

forces you to use a serial-line download path. If you have a slow download path,<br />

you should burn into ROM the kernel, the agent, and as much generic VxWorks<br />

code as fits.<br />

Because the Tornado development tools let you download and execute code<br />

dynamically, you can download extensions (such as application code, new drivers,<br />

extra hardware initialization code, and the like) and use the WDB agent to debug<br />

the extensions. This is a win over a traditional monitor approach, which requires<br />

that you to download the entire kernel every time, even though most of the code<br />

has not changed.<br />

1. The traditional ROM-monitor approach is to modify the OS initialization code temporarily<br />

to ensure that the MMU, certain parts of the vector table, and the device used by the monitor<br />

are not reset. By running only one set of initialization code, these problem go away.<br />

42


3<br />

Creating a New <strong>BSP</strong><br />

3.2 Setting Up Your Development Environment<br />

Setting up your development environment means establishing a mechanism to<br />

download code to the target and then testing the downloaded code. It is usually<br />

best to start with some simple image test code rather than a full blown VxWorks<br />

image. To find out what compiler and linker flags you need, go to your reference<br />

<strong>BSP</strong> and build either vxWorks (a RAM image) or vxWorks_resrom_nosym (a<br />

ROM image).<br />

3<br />

Choosing a Technique for Downloading Code to the Target<br />

The following are some of the more common techniques for downloading code to<br />

the target:<br />

■<br />

■<br />

Using the download protocol supplied in the board vendor’s debug ROMs.<br />

The drawback of this approach is that downloading is often slow. The<br />

advantage is that it is easy to set up.<br />

Using a JTAG debugger such as a visionICE or visionPROBE emulator. The<br />

main drawback of this approach is that support is not available for all<br />

architectures and/or CPUs. However, this method allows for a quick<br />

download and also allows you to single-step through the initialization code.<br />

■<br />

Using a ROM emulator (such as NetROM from AMC). The drawback of this<br />

approach is that it can take time for you to learn how to use it. The advantages<br />

include fast download times, portability to most boards, and a communication<br />

protocol that lets debug messages pass from the target to the host through the<br />

ROM socket.<br />

After you have downloaded code to the target, examine memory and/or ROM to<br />

make sure it is loaded into the right place. The Wind River-supplied GNU tools nm<br />

and objdump can be used on your compiled images to see what should be in the<br />

target memory. Pay special attention to the addresses of the start of the text and<br />

data segments.<br />

Choosing a Method for Testing the Downloaded Code<br />

The next step is to establish a debugging mechanism to track the progress of your<br />

initialization sequence. The following are some of the more common techniques:<br />

■<br />

■<br />

Using a JTAG device such as visionICE or visionPROBE.<br />

Using the board’s native debug ROMs (if it has breakpoint support).<br />

43


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

■<br />

Using a logic analyzer to trace the processor’s address lines.<br />

■<br />

Writing a debugging library to do something like the following:<br />

– Flash an LED.<br />

– Write to persistent memory (local, off-board, or battery backed memory).<br />

– Transmit a character over a serial line in polled mode.<br />

– Send data up through the NetROM debug port.<br />

After you have chosen a debugging mechanism, check that you can jump to your<br />

code’s entry point and run it successfully. Your test code should set up the board’s<br />

RAM as needed and prove that it is working by writing to it and reading back the<br />

value. Your test program will probably use the same initialization code as<br />

VxWorks. For details on the files romInit.s and sysALib.s, see 3.3.1 Writing the <strong>BSP</strong><br />

Files, p.44.<br />

NOTE: If you are testing a debugging library on a ROM-based VxWorks image, be<br />

aware that the data and bss segments are not yet set up. In particular, libraries that<br />

depend on the correct initialization of global variables cannot work yet.<br />

3.3 Writing the <strong>BSP</strong> Pre-Kernel Initialization Code<br />

This section describes how to write the <strong>BSP</strong> files, build and download VxWorks,<br />

debug the initialization code, and how and when to start the WDB agent before<br />

you start the kernel.<br />

3.3.1 Writing the <strong>BSP</strong> Files<br />

Create a <strong>BSP</strong> directory by copying the <strong>BSP</strong> template files from<br />

target/config/templateCPU. Below is a file-by-file description of considerations to<br />

keep in mind when modifying the files.<br />

44


3<br />

Creating a New <strong>BSP</strong><br />

Makefile<br />

At a minimum, your makefile must define the following macros:<br />

CPU<br />

The target CPU, which must be the same as the reference <strong>BSP</strong>.<br />

3<br />

TOOL<br />

The host tool chain (such as gnu), which must be the same as the reference <strong>BSP</strong>.<br />

TGT_DIR<br />

The path to the target directory. The default is installDir/target.<br />

TARGET_DIR<br />

The <strong>BSP</strong> directory name.<br />

VENDOR<br />

The board manufacturer’s name.<br />

BOARD<br />

The board name.<br />

ROM_TEXT_ADRS<br />

The boot ROM entry address in hexadecimal. For most boards, this is set to the<br />

beginning of the ROM address area. However, there may be some hardware<br />

configurations that use an area at the start of ROM for the reset vector; thus, it<br />

should be offset accordingly. The offset is typically architecture dependent.<br />

Thus, the low order bytes of this macro can be copied from a reference <strong>BSP</strong>.<br />

ROM_WARM_ADRS<br />

The boot ROM warm entry address in hexadecimal. This is usually a fixed<br />

offset of 8 bytes beyond the cold boot entry point ROM_TEXT_ADRS. The code<br />

in sysToMonitor( ) should do an explicit jump to ROM_WARM_ADRS when a<br />

switch to the hardware ROM code is desired.<br />

ROM_SIZE<br />

The ROM area’s size in hexadecimal.<br />

RAM_LOW_ADRS 2<br />

The address at which to load VxWorks.<br />

RAM_HIGH_ADRS 2<br />

The destination address used when copying the boot ROM image to RAM.<br />

2. RAM_LOW_ADRS and RAM_HIGH_ADRS are absolute addresses, typically chosen to<br />

be at an architecture-specific offset from the start of DRAM. For a quick look at the VxWorks<br />

memory layout, see the memory layout diagram in the appendix of the VxWorks<br />

Programmer’s <strong>Guide</strong>.<br />

45


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

HEX_FLAGS<br />

Architecture-specific flags for the objcopy utility that generates S-record files.<br />

MACH_EXTRA<br />

Any extra machine-dependent files. Make it an empty declaration for now.<br />

! CAUTION: The hexadecimal addresses above should not include a leading 0x.<br />

bspname.h<br />

config.h<br />

sysLib.c<br />

Some additional architecture-specific macros might also be required in the<br />

makefile. For example, the i960 needs to know where to link the Initial Boot<br />

Record. For architecture-specific information, see the appropriate VxWorks<br />

Architecture Supplement or 4. Hardware <strong>Guide</strong>lines.<br />

See bspname.h, p.26.<br />

The basic description of config.h, p.16 applies, although some small modifications<br />

are needed. First, make sure the following code stub is present before the line that<br />

includes configAll.h:<br />

/* <strong>BSP</strong> version/revision identification, before configAll.h */<br />

#define <strong>BSP</strong>_VER_1_1 1<br />

#define <strong>BSP</strong>_VER_1_2 1<br />

#define <strong>BSP</strong>_VERSION "1.2"<br />

#define <strong>BSP</strong>_REV "/0" /* 0 for first revision */<br />

To start, add the following lines near the end of the header file:<br />

#undef INCLUDE_MMU_BASIC /* bundled mmu support */<br />

#undef INCLUDE_CACHE_SUPPORT /* cache support */<br />

Make sure the definitions of ROM_TEXT_ADRS, ROM_SIZE, and<br />

RAM_LOW_ADRS match those defined in the makefile.<br />

Make sure LOCAL_MEM_LOCAL_ADRS and LOCAL_MEM_SIZE are correctly<br />

defined.<br />

While sysLib.c is by far the largest <strong>BSP</strong> file, at this phase you should implement<br />

only the basics: sysModel( ), sysBspRev( ), sysHwInit( ), sysHwInit2( ), and<br />

sysMemTop( ). The routine sysBspRev( ) is new as of VxWorks 5.3. Implement this<br />

routine as follows:<br />

46


3<br />

Creating a New <strong>BSP</strong><br />

char * sysBspRev (void)<br />

{<br />

return (<strong>BSP</strong>_VERSION <strong>BSP</strong>_REV);<br />

}<br />

The file sysLib.c should also include the following stub drivers:<br />

3<br />

romInit.s<br />

#include "mem/nullNvram.c"<br />

#include "vme/nullVme.c"<br />

The sysHwInit( ) routine is the heart of sysLib.c, and most of your work is done<br />

here. It is the routine that resets all devices to a quiescent state so that they do not<br />

generate interrupts later on when interrupts are enabled.<br />

At power-up (cold start) the processor begins execution at romInit( ), which must<br />

be the first routine in the text segment of romInit.s. For warm starts, the processor<br />

begins execution at romInit( ) plus a small offset (see sysToMonitor( ) in sysLib.c).<br />

Most hardware and device initialization is performed later in the initialization<br />

sequence by sysHwInit( ) in sysLib.c. The job of romInit( ) is to perform the<br />

minimal setup needed to transfer control to romStart( ) (in config/all/bootInit.c):<br />

■<br />

Initialize the processor (this code is specific to the processor and not the board,<br />

and thus can be copied from a reference <strong>BSP</strong>):<br />

– Mask processor interrupts<br />

– Set the initial stack pointer to STACK_ADRS (defined in configAll.h)<br />

– Disable processor caches<br />

■<br />

Initialize access to target DRAM as needed for the following (this code is<br />

board-specific):<br />

– Wait states<br />

– Refresh rate<br />

– Chip-selects<br />

– Disabling secondary (L2) caches (if needed)<br />

At the end, romInit( ) jumps to romStart( ) in bootInit.c, passing the start type. The<br />

start type should be BOOT_COLD on a cold boot, or the parameter passed from<br />

sysToMonitor( ) on a warm boot.<br />

This file must also contain a data variable called sdata to mark the start of the data<br />

segment. This variable typically stores a string such as “start of data.”<br />

Refer to the template romInit.s file in the template <strong>BSP</strong> that accompanies this<br />

product.<br />

47


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

sysALib.s<br />

This file contains the entry point for RAM-based images such as vxWorks. The<br />

entry point, sysInit( ), performs the minimal setup necessary to transfer control to<br />

usrInit( ) (defined in config/all/usrConfig.c). This routine is similar to romInit( ).<br />

The sysInit( ) routine is largely the same for each architecture. As such, copying<br />

the code from a template <strong>BSP</strong> is the best way to start. The sysInit( ) routine<br />

typically just masks processor interrupts and sets the stack pointer. For processors<br />

whose stack grows down, the stack pointer is set to sysInit( ). For processors<br />

whose stack grows up, it is set to a few hundred bytes below sysInit( ). It then calls<br />

usrInit( ), passing it the parameter BOOT_WARM_AUTOBOOT. Most hardware<br />

and device initialization is performed later in the initialization sequence by<br />

sysHwInit( ) in sysLib.c.<br />

<strong>BSP</strong> routines should be coded in C when possible, but if there are compelling<br />

technical reasons for resorting to assembler, then place the routines in sysALib.s.<br />

config/all/usrConfig.c<br />

During development you will want to add debugging code and make other such<br />

modifications to the generic (non-<strong>BSP</strong>) configuration files. Rather than modifying<br />

the generic code directly, instead create local copies in the <strong>BSP</strong> directory as follows:<br />

1. First copy the files config/all/usrConfig.c and config/all/bootInit.c into your<br />

<strong>BSP</strong> directory. Next, add the following lines to your <strong>BSP</strong>’s Makefile, right after<br />

the definition of HEX_FLAGS:<br />

BOOTINIT<br />

USRCONFIG<br />

= bootInit.c<br />

= usrConfig.c<br />

This causes the makefile to use your copy of these generic configuration files<br />

when building VxWorks.<br />

2. Next, modify your copy of usrConfig.c to remove everything except the<br />

pre-kernel initialization code by using #if FALSE/#endif pairs so that<br />

usrExtra.c is not included, and the body of usrRoot( ) is empty:<br />

...<br />

#if FALSE<br />

#include "usrExtra.c"<br />

#endif<br />

...<br />

void usrRoot<br />

...<br />

{<br />

#if FALSE<br />

48


3<br />

Creating a New <strong>BSP</strong><br />

...<br />

#endif<br />

}<br />

The #include of usrExtra.c links in the other configuration files from<br />

src/config. You do not need these now, but you will need them later as you add<br />

features. For example, when you are ready to start working on the kernel and<br />

the target agent, you need to link in the appropriate configuration code as<br />

follows:<br />

3<br />

#if FALSE<br />

#include "usrExtra.c"<br />

#else<br />

#include "usrWdb.c"<br />

#endif<br />

3.3.2 Building and Downloading VxWorks<br />

The VxWorks image you load to the target depends on the download method you<br />

use. The primary images are as follows:<br />

vxWorks<br />

This image starts execution from RAM. It must be loaded into RAM by some<br />

external means such as the board’s native debug ROMs.<br />

vxWorks_rom<br />

This image starts execution from ROM, but its text and data segments are<br />

linked to RAM addresses. Early on it copies itself into RAM and continues<br />

execution from there.<br />

vxWorks_resrom_nosym<br />

This image executes from ROM. Only the data segment is copied into RAM.<br />

If your download path puts the image in RAM (such as when using a vendor<br />

debug ROM), use vxWorks. If your download path puts the image in ROM (such<br />

as when using NetROM), use either vxWorks_rom or vxWorks_resrom_nosym.<br />

The advantage of vxWorks_rom is that it can be more easily debugged because the<br />

software breakpoints can be set only on RAM addresses. The advantage of<br />

vxWorks_resrom_nosym is that it uses less target memory. The makefile for both<br />

ROM images lets you specify an optional .hex suffix (for example,<br />

vxWorks_rom.hex) to produce an S-record, rather than an object file.<br />

There is a file called depend.cputool containing the file dependency rules used by<br />

the makefile. The makefile automatically generates the dependency file if it does<br />

not already exist. If you add new files to the <strong>BSP</strong>, delete the dependency file and let<br />

the makefile regenerate it.<br />

49


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

After you have downloaded your code to the target, examine memory and/or<br />

ROM to make sure that the code is loaded into the right place. Use the nm and<br />

objdump utilities on the VxWorks image to see what should be in the target<br />

memory. Pay special attention to the addresses of the start of the text and data<br />

segments.<br />

3.3.3 Debugging the Initialization Code<br />

The beginnings of the ROM and RAM initialization sequences differ, but they are<br />

otherwise the same. Details of what each <strong>BSP</strong> procedure needs to do were<br />

provided in the previous section. This section reviews the steps of the initialization<br />

sequence and supplies tips on what to check if a failure occurs at a particular step.<br />

ROM Initialization<br />

This section describes the initialization sequence for the ROM-based VxWorks<br />

images vxWorks_rom and vxWorks_resrom_nosym.<br />

romInit.s: romInit( )<br />

At power-up (cold start) the processor begins execution at romInit( ), whose job is<br />

to perform the minimal setup necessary to transfer control to romStart( ) (in<br />

config/all/bootInit.c). Most hardware and device initialization is performed later<br />

in the initialization sequence by sysHwInit( ) in sysLib.c.<br />

bootInit.c: romStart( )<br />

The text and data segments are copied from ROM to RAM in one of the following<br />

ways:<br />

■<br />

For vxWorks_rom, both the text and data segments are copied to RAM.<br />

■<br />

For vxWorks_resrom_nosym, only the data segment is copied to RAM.<br />

After the copy, check that the data segment is properly initialized. For example:<br />

int thisVal = 17; /* some data segment variable */<br />

...<br />

if (thisVal != 17)<br />

somethingIsWrong();<br />

If something is wrong, check if RAM access is working properly. For example:<br />

50


3<br />

Creating a New <strong>BSP</strong><br />

int dummy;<br />

...<br />

dummy = 17;<br />

if (dummy != 17)<br />

somethingIsWrong();<br />

If RAM access is working, check that the data segment was copied into memory at<br />

the right offset. This is only a problem for vxWorks_resrom_nosym images. The<br />

romStart( ) routine assumed that the data is located at some architecture-specific<br />

offset from the end of the text segment in ROM, as the following code stub from<br />

bootInit.c shows:<br />

3<br />

#if (CPU_FAMILY == SPARC)<br />

bcopyLongs ((UINT *)(etext + 8), (UINT *) RESIDENT_DATA,<br />

#elif ((CPU_FAMILY == MIPS) || (CPU_FAMILY == PPC))<br />

bcopyLongs ((UINT *)(etext + 0), (UINT *) RESIDENT_DATA,<br />

#else<br />

bcopyLongs ((UINT *)(etext + 4), (UINT *) RESIDENT_DATA,<br />

#endif<br />

However, this offset can be different if you are using alternative tools to create your<br />

ROM image. In this case you may need to adjust the offset accordingly.<br />

The last thing romStart( ) does is call the generic initialization routine usrInit( ) in<br />

usrConfig.c. The one exception is the i960, which first jumps to sysInitAlt( ) (in<br />

sysALib.s) in order to reinstall the processor tables before jumping to usrInit( ).<br />

The rest of the initialization sequence is described in section Generic Initialization,<br />

p.52.<br />

RAM Initialization<br />

This section describes the initialization routine for the RAM-based VxWorks<br />

image.<br />

sysALib.s: sysInit( )<br />

The VxWorks entry point is sysInit( ), whose job is to perform the minimal setup<br />

necessary to transfer control to usrInit( ) (in usrConfig.c). Most hardware and<br />

device initialization is performed later in the initialization sequence by<br />

sysHwInit( ) in sysLib.c.<br />

51


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Generic Initialization<br />

The remainder of the initialization code is common to both ROM and RAM based<br />

images.<br />

usrConfig.c: usrInit( )<br />

From a <strong>BSP</strong> writer’s point of view, the main significance of usrInit( ) is that it clears<br />

the bss segment (so that uninitialized C global variables are now zero), and then<br />

calls sysHwInit( ) (in sysLib.c) to initialize the hardware. If memory has been set<br />

up properly, there is little that can go wrong in this routine.<br />

sysLib.c: sysHwInit( )<br />

This is the heart of the <strong>BSP</strong> initialization code. It must reset all hardware to a<br />

quiescent state so as not to generate uninitialized interrupts later when interrupts<br />

are enabled.<br />

usrConfig.c: usrInit( )<br />

After sysHwInit( ) has completed, control returns to usrInit( ). The last thing<br />

usrInit( ) does is call kernelInit( ) to start the VxWorks kernel. This is the end of<br />

the pre-kernel initialization code. The routine kernelInit( ) does not return. Rather,<br />

it starts the kernel with usrRoot( ) as the first task. It is deep within the<br />

kernelInit( ) routine that interrupts are finally enabled; serious confusion ensues if<br />

not all interrupt sources were disabled and cleared in sysHwInit( ).<br />

You can start the agent as this point if you want to bring up the kernel under<br />

control of the agent. This is an optional step which is not typically done. For more<br />

information, see 3.3.4 Starting the WDB Agent Before the Kernel, p.53.<br />

usrConfig.c: usrRoot( )<br />

The remainder of the VxWorks initialization is done after the kernel has been<br />

started in usrRoot( ). Details are covered in subsequent sections. In this phase, it is<br />

enough if usrRoot( ) can verify that sysHwInit( ) was properly written.<br />

If kernelInit( ) is called but execution fails to reach the start of usrRoot( ), one of<br />

two things are wrong. Either your sysMemTop( ) routine is returning a bogus<br />

address, or, more likely, some device has not been reset and is generating an<br />

interrupt. In the second case, you must modify sysHwInit( ) to reset the<br />

interrupting device.<br />

52


3<br />

Creating a New <strong>BSP</strong><br />

To find the source of the interrupt, start by figuring out the interrupt vector being<br />

generated, applying any of the following techniques:<br />

■<br />

■<br />

■<br />

Use a logic analyzer to look for instruction accesses to the interrupt vector<br />

table.<br />

Use an ICE to set breakpoints in the interrupt vector table.<br />

Modify sysHwInit( ) to mask suspected interrupt vectors via an interrupt<br />

controller.<br />

■<br />

Modify sysHwInit( ) to connect debug routines to the suspected interrupt<br />

vectors using intVecSet( ) (you cannot use intConnect( ) because it calls<br />

malloc( ) and the VxWorks memory allocator has not yet been initialized).<br />

At this point you have a working kernel, but no device drivers. The only drivers<br />

required by VxWorks is a timer and possibly an interrupt controller. Most <strong>BSP</strong>s<br />

also have serial drivers. Adding basic driver support to VxWorks is described in<br />

3.4 Using a Minimal Kernel, p.55.<br />

3<br />

3.3.4 Starting the WDB Agent Before the Kernel<br />

NOTE: This procedure applies only to images built from the command line.<br />

This step is optional and is rarely done at Wind River when creating a new <strong>BSP</strong>. The<br />

disadvantages to starting the agent before the kernel are:<br />

■<br />

■<br />

Once the hardware initialization code is written, bringing up the kernel takes<br />

less time than bringing up the agent. Because most developers consider a<br />

working kernel to be the bigger milestone, start with the kernel.<br />

Starting the agent before the kernel does not really help get the basic kernel<br />

working. This is because the basic kernel adds little to what you have written<br />

already; just a timer driver and possibly an interrupt controller, which are<br />

simple devices.<br />

■<br />

Starting the agent before the kernel limits you to system mode debugging.<br />

The only reason to start the agent early is if you have a very slow download<br />

environment. In that case, you may want to put everything in ROM as early as<br />

possible to save download cycles.<br />

Starting the agent before the kernel is described in Tornado User’s <strong>Guide</strong>: Setup and<br />

Startup. The following two sections provide important additional information.<br />

53


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Caveats<br />

Because the virtual I/O driver requires the kernel, add the following line to<br />

config.h:<br />

#undef INCLUDE_WDB_VIO<br />

There is an important caveat if you are planning to use the target agent’s serial-line<br />

communication path. When the kernel is first started, interrupts are enabled in the<br />

processor, but driver interrupt handlers are not yet connected. You must take care<br />

to ensure that the serial device you use for agent communication does not generate<br />

an interrupt. If your board has an interrupt controller, use it to mask serial<br />

interrupts in sysHwInit( ). Beware that the target agent tries to use all drivers in an<br />

“interrupt on first packet” mode. As a result, you should modify the serial driver<br />

to refuse to go into interrupt mode, even if the agent requests it.<br />

System-Mode Debugging Techniques<br />

After you have the agent working, you will want to use it to debug the VxWorks<br />

image to which it is linked. To save download time, you should link the VxWorks<br />

code you want to test into the ROM image. In particular, you should glance at<br />

section 3.4 Using a Minimal Kernel, p.55 to see what driver code to link with<br />

VxWorks. To avoid remaking ROMs, consider adding hooks to your <strong>BSP</strong> and<br />

driver routines as follows:<br />

void (*myHwInit2Hook)(void); /* declare a hook routine */<br />

...<br />

void sysHwInit2 (void)<br />

{<br />

if (myHwInit2Hook != NULL) /* and conditionally call it */<br />

{<br />

myHwInit2Hook();<br />

return;<br />

}<br />

... /* default code */<br />

}<br />

This allows you to replace the routine from the debugger dynamically. For<br />

example, to override the behavior of sysHwInit2( ) above, just create a new<br />

version of it called myHwInit2( ) in a module called myLib.o, and then type:<br />

(gdb) load myLib.o<br />

(gdb) set myHwInit2Hook = myHwInit2<br />

(gdb) break myHwInit2<br />

(gdb) continue<br />

However, if you start the agent before the kernel, you must start it after the call to<br />

sysHwInit( ). Thus, you cannot override sysHwInit( ). On the other hand, you<br />

54


3<br />

Creating a New <strong>BSP</strong><br />

might want to add additional hardware initialization code that is called before the<br />

kernel is started. In this case, you can add a hook right before the call to<br />

kernelInit( ). As an alternative to hooks, you can call routines from the debugger<br />

by using the GDB’s call procedure. For example:<br />

(gdb) call myHwInit2<br />

3<br />

The advantage of using hooks instead of the call mechanism is that:<br />

■<br />

Hooks let you avoid executing the original code.<br />

■<br />

Hooks are much faster.<br />

If your board has an “abort” button, consider connecting a debug routine to the<br />

abort interrupt. Then you can set a breakpoint on your interrupt handler from the<br />

debugger. This provides a way for you to gain control of the system if it appears to<br />

have died. In this case it is best to have the abort switch tied to a non-maskable<br />

interrupt (NMI).<br />

! WARNING: Only fatal interrupts such as “abort” can be connected to an NMI. If a<br />

device interrupt is connected to an NMI, the kernel will not work properly.<br />

3.4 Using a Minimal Kernel<br />

A minimal kernel involves adding just a few simple device drivers. Because these<br />

drivers involve connecting interrupt service routines, this section starts with some<br />

ISR guidelines.<br />

3.4.1 ISR <strong>Guide</strong>lines<br />

After the kernel is started, you can use the intConnect( ) routine and<br />

INUM_TO_IVEC macro to connect interrupt service routines (ISRs) to the interrupt<br />

vector table. For example:<br />

intConnect (INUM_TO_IVEC (intVec), proc, param);<br />

The intVec parameter is the interrupt vector, proc is the C routine to call in response<br />

to the interrupt, and param is a parameter to pass the proc routine. For more<br />

information, see the reference entry for intConnect( ).<br />

55


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

A common mistake made when writing ISRs is to omit the interrupt acknowledge<br />

needed to clear the interrupt source. The unfortunate result is the immediate<br />

generation of another interrupt as soon as the ISR completes.<br />

Non-maskable interrupts (NMIs) cannot be used in conjunction with most<br />

VxWorks library functions. They must be used and implemented with great care.<br />

For more information on ISRs at high interrupt levels, see the VxWorks<br />

Programmer’s <strong>Guide</strong>: Basic OS.<br />

! WARNING: ISRs must not call certain VxWorks routines. For a listing of the<br />

routines callable from interrupt level, see the ISR special limitations discussion<br />

included in the VxWorks Programmer’s <strong>Guide</strong>: Basic OS.<br />

3.4.2 Required Drivers<br />

The only driver required by VxWorks is the system clock, although certain<br />

architectures, such as the 80x86 and PowerPC, also require an interrupt controller<br />

driver. Implementing a system clock driver typically involves using one of the<br />

existing drivers from src/drv/timer (and src/drv/intrCtl if an interrupt controller<br />

driver is needed). If you are reusing an existing driver, all you need to do is<br />

perform board-specific hardware initialization in sysHwInit( ), and connect the<br />

interrupt by calling intConnect( ) in sysHwInit2( ).<br />

The timer drivers are simple devices that you can test by modifying usrRoot( ) to<br />

perform some action periodically, such as blinking an LED. For example:<br />

void myTestCode (void)<br />

{<br />

while (1)<br />

{<br />

taskDelay (5*sysClockRateGet()); /* every 5 seconds */<br />

sysFlashLed(); /* flash an LED */<br />

}<br />

}<br />

3.4.3 Serial Drivers<br />

Although not always required, most <strong>BSP</strong>s include a serial driver. Serial drivers<br />

have changed significantly with the introduction of Tornado (in fact, that was the<br />

major change made to the <strong>BSP</strong>s). For a description of these changes, see<br />

A. Upgrading a <strong>BSP</strong> for Tornado 2.0. The new serial drivers are located in the<br />

src/drv/sio directory. One of these drivers should be appropriate to your needs. If<br />

56


3<br />

Creating a New <strong>BSP</strong><br />

not, use the src/drv/sio/templateSio.c template driver as the basis for your own<br />

custom serial driver.<br />

Earlier, you removed most of the body of usrRoot( ) with #if FALSE/#endif pairs.<br />

Now, you need to move the #if FALSE line further down, below the point at which<br />

the serial devices are initialized.<br />

You should modify usrRoot( ) to spawn some application test code to test your<br />

drivers. For example, you can periodically print a message to the console:<br />

3<br />

void myTestCode (void)<br />

{<br />

extern int vxTicks;<br />

char * message = "still going...\n";<br />

while (1)<br />

{<br />

taskDelay (5*sysClockRateGet()); /* every 5 seconds */<br />

write (1, message, strlen (message)); /* print a message */<br />

}<br />

}<br />

3.5 The Target Agent and Tornado<br />

The debug agent is initialized by a call to wdbConfig( ). By default, this happens<br />

at the very end of usrRoot( ). However, you modified this usrRoot( ) to be empty<br />

(see config/all/usrConfig.c, p.48). To restore the agent, call wdbConfig( ) right after<br />

your serial-line initialization code. The default configuration for the target agent<br />

uses the network as a connection to the host. Unfortunately, networking is not yet<br />

available. Therefore, you must use an alternative method of connection. For<br />

information on how to do this, see the section on Alternative Back Ends in the<br />

Tornado Users <strong>Guide</strong>: Setup and Startup.<br />

3.6 Finishing the Port<br />

This section summarizes the various and diverse tasks essential to completing the<br />

port. Included is a discussion of cleanup, timers, networking, and other issues.<br />

57


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

3.6.1 Cleanup<br />

Up to now you have been using private copies of usrConfig.c and bootInit.c. Your<br />

<strong>BSP</strong> should work with the generic versions. To reinstall the generic versions,<br />

remove these lines from your <strong>BSP</strong>’s Makefile:<br />

BOOTINIT<br />

USRCONFIG<br />

= bootInit.c<br />

= usrConfig.c<br />

And then do a make clean.<br />

Previously you masked out unwanted configuration code with #if FALSE/#endif<br />

pairs. Now you need to eliminate the unwanted code in a more standard way. That<br />

is, you must undefine the appropriate macros in config.h. The file<br />

src/config/usrDepend.c lists macro dependencies you must keep in mind.<br />

3.6.2 NVRAM<br />

VxWorks defines an interface for reading and writing to a persistent storage area.<br />

This interface is called a non-volatile memory library. Several generic drivers exist<br />

in the target/src/drv/mem directory.<br />

3.6.3 Adding Other Timers<br />

Your driver should probably include an auxiliary clock driver as well as a<br />

high-resolution timestamp driver.<br />

The auxiliary clock is used by the VxWorks spy utility, and also by the Tornado<br />

host tool called the browser. For more information on the auxiliary clock interface,<br />

see the reference entries for the various sysAuxClk*( )routines, F. Generic Drivers,<br />

and the WindView User’s <strong>Guide</strong>: Creating a VxWorks Timestamp Driver.<br />

The high-resolution timestamp driver is currently used only by WindView, but<br />

writing it can be useful to you for future debugging. The interface can be found in<br />

the header file target/h/drv/timer/timestampDev.h.<br />

3.6.4 Network<br />

This manual describes how to use a “standalone” VxWorks image, vxWorks.st.<br />

This image has two properties:<br />

58


3<br />

Creating a New <strong>BSP</strong><br />

■<br />

It has a VxWorks symbol table linked in. This is no longer needed because<br />

Tornado uses a host-based symbol table for debugging information.<br />

■<br />

It links in the network subsystem, but does not initialize it.<br />

Instead of using a vxWorks.st image, continue to use vxWorks,orvxWorks_rom.<br />

To link in the network without initializing it, add a dummy conditional to<br />

usrConfig.c right before the call to usrNetInit( ):<br />

3<br />

if (FALSE) /* add this line */<br />

usrNetInit (BOOT_LINE_ADRS); /* so that this is not called */<br />

Then you can call usrNetInit( ) later, and use CrossWind to debug your network<br />

driver(s). It is easiest to get your network driver first working with the cache and<br />

MMU disabled.<br />

The following table in src/config/usrNetwork.c is used to configure the BSD 4.4<br />

network devices:<br />

#ifdef NETIF_USR_DECL<br />

NETIF_USR_DECL /* declarations from <strong>BSP</strong> */<br />

#endif<br />

...<br />

LOCAL NETIF netIf [] = /* network interfaces */<br />

{<br />

#ifdef NETIF_USR_ENTRIES /* Additional entries, from <strong>BSP</strong> */<br />

NETIF_USR_ENTRIES<br />

#endif<br />

#ifdef INCLUDE_DC<br />

{"dc", dcattach, (char*)IO_ADRS_DC, INT_VEC_DC, INT_LVL_DC,<br />

DC_POOL_ADRS, DC_POOL_SIZE, DC_DATA_WIDTH, DC_RAM_PCI_ADRS,<br />

DC_MODE },<br />

#endif /* INCLUDE_DC */<br />

#ifdef INCLUDE_EGL<br />

{"egl", eglattach, (char*)IO_ADRS_EGL, INT_VEC_EGL, INT_LVL_EGL},<br />

#endif /* INCLUDE_EGL */<br />

...<br />

}<br />

For END drivers, network devices are initialized by a table in the configNet.h file.<br />

The table name is endDrvTbl.<br />

#define DEC_LOAD_FUNC dec21x40EndLoad<br />

#define DEC_BUFF_LOAN 1<br />

/*<br />

* ::::::: \<br />

* :<br />

*/<br />

# define DEC_LOAD_STRING<br />

59


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

"0x81020000:0x80000000:0x12:0x12:-1:-1:-1:0:0x80800<br />

000"<br />

IMPORT END_OBJ* DEC_LOAD_FUNC (char*, void*);<br />

END_TBL_ENTRY endDevTbl [] =<br />

{ 0, DEC_LOAD_FUNC, DEC_LOAD_STRING, DEC_BUFF_LOAN, NULL, FALSE},<br />

{ 0, END_TBL_END, NULL, 0, NULL, FALSE},<br />

};<br />

As you can see, the drivers that are initialized are controlled by a set of macros.<br />

To add <strong>BSP</strong> support for an existing VxWorks network driver, modify config.h to<br />

define the corresponding macro and I/O parameters. To add support for custom<br />

BSD drivers, define the macro NETIF_USR_ENTRIES and NETIF_USR_DECL<br />

appropriately. END customers only need to add an appropriate entry to the<br />

endDrvTbl to include the driver. Refer to the specific driver documentation for the<br />

exact format and syntax of the drivers initialization string.<br />

Support for the VME-based standalone networking cards, Excelan EXOS-202 and<br />

the CMC ENP-10, has been dropped from the standard product as of Tornado 2.0.<br />

3.6.5 Cache, MMU, and DMA Devices<br />

The next step is to get the <strong>BSP</strong> working with caches and MMU enabled. For more<br />

information, see 5.6 Cache Considerations, p.101, and 4.5 Enabling the Virtual Memory<br />

Library, p.83. Cache and MMU configuration can strongly affect the behavior of<br />

DMA devices such as network drivers.<br />

3.6.6 Boot ROMs<br />

The boot ROMs use the VxWorks kernel. The two main differences between the<br />

bootrom image and the vxWorks image are:<br />

■<br />

■<br />

The bootrom image uses target/config/all/bootConfig.c instead of<br />

target/config/all/usrConfig.c. Both files are very similar, so to getting the boot<br />

ROM working involves essentially the same the steps previously described.<br />

The bootrom image is compressed by default. It is uncompressed and copied<br />

into RAM in bootInit.c.<br />

60


3<br />

Creating a New <strong>BSP</strong><br />

3.6.7 SCSI<br />

VxWorks supports SCSI-2 drivers; see I. Writing a SCSI-2 Device Driver. SCSI-1<br />

drivers are no longer supported.<br />

3<br />

3.6.8 Projects<br />

The Tornado documentation set contains the necessary information regarding<br />

creating, configuring, and building projects. These steps can all be handled<br />

through the project facility GUI. For information about working with the project<br />

facility GUI, see 6. Components and E. Component Language.<br />

61


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

62


4<br />

Hardware <strong>Guide</strong>lines<br />

4.1 Introduction<br />

VxWorks runs on many architectures and targets from a wide variety of vendors,<br />

including custom and embedded hardware, VMEbus, Multibus, and PCIbus<br />

single-board computers, and workstation and PC mother boards. VxWorks can<br />

also boot from many different UNIX and Windows hosts using a variety of<br />

communication media.<br />

With the number of combinations that have been configured, Wind River has<br />

gathered sufficient experience to make recommendations in board design to best<br />

suit the VxWorks run-time environment. However, this document should not be<br />

used to determine the desirability of potential or existing ports. Many<br />

considerations essential to such determinations, such as cost analysis, time to<br />

market, and power and cooling requirements, are beyond the scope of this<br />

document.<br />

This chapter enumerates run-time functional requirements, distills features of<br />

important run-time components, and warns against potential pitfalls. The primary<br />

objective of this chapter is to assist developers in selecting appropriate boards and<br />

components for VxWorks operation. The following issues are discussed in this<br />

chapter:<br />

■<br />

■<br />

■<br />

■<br />

architectural considerations<br />

memory<br />

bus<br />

devices<br />

The particulars of how an individual architecture implements these considerations<br />

are discussed in the VxWorks Architecture Supplement document for each<br />

63


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

architecture. This chapter is a general discussion of the issues and not an<br />

implementation-specific guide.<br />

4.2 Architectural Considerations<br />

At the core of any VxWorks run-time environment is the target architecture. This<br />

section is dedicated to the capabilities and run-time ramifications of architecture<br />

selection. Some general observations follow, but most details are covered in<br />

sections devoted to a particular architecture.<br />

For additional documentation that pertains to VxWorks architecture support, refer<br />

to the following:<br />

■<br />

the appropriate VxWorks Architecture Supplement document<br />

■<br />

VxWorks API Reference: Drivers, 5.5<br />

■<br />

VxWorks API Reference: OS Libraries, 5.5<br />

■<br />

Tornado User’s <strong>Guide</strong>, 2.2<br />

■<br />

<strong>BSP</strong> documentation (for a target similar to yours)<br />

■<br />

Wind River Technical Notes, available online through WindSurf<br />

4.2.1 Interrupt Handling<br />

Interrupts asynchronously connect the external world to the system, and are<br />

typically the most important aspect of real-time systems. VxWorks adopts a<br />

vectored interrupt strategy where applications “connect” ISRs (Interrupt Service<br />

Routines) to a unique vector generated by the interrupting component. VxWorks<br />

provides functions to dynamically program these vectors to contain the address of<br />

an extremely small and fast code stub that calls an application’s C-language ISR,<br />

and then returns control to the kernel.<br />

A frustrating complication to ordinary interrupt servicing is interrupt<br />

acknowledgment (IACK). Most system architectures provide for automatic<br />

interrupt acknowledgment. For the relatively few that do not address this issue,<br />

ISRs must manually acknowledge an interrupt through a register access or by<br />

some other awkward mechanism.<br />

Finally, interrupt latency may vary from architecture to architecture. Interrupt<br />

latency is the maximum amount of time from the initial processor interrupt request<br />

64


4<br />

Hardware <strong>Guide</strong>lines<br />

to the start of interrupt service processing. Both hardware and software contribute<br />

to interrupt latency. The hardware may prioritize external interrupts, thereby<br />

introducing an intrinsic latency to lower-priority interrupts. Architectures often<br />

have indivisible instructions whose execution times are surprisingly long.<br />

Especially problematic are cache push operations, which may take tens of<br />

uninterruptable microseconds. The VxWorks operating system also contributes to<br />

interrupt latency by inhibiting the processor’s ability to receive interrupts. While<br />

each architecture has optimized these interrupt locks to an absolute minimum, be<br />

aware that some variation in performance exists when comparing one architecture<br />

to another.<br />

For information on non-maskable interrupts (NMIs), see the discussion of<br />

interrupt service code in VxWorks Programmer’s <strong>Guide</strong>: Basic OS. Non-maskable<br />

interrupts are usable, but they must not call any VxWorks kernel routines as part<br />

of the service routine. This severely limits the functionality that can be used within<br />

an NMI handler.<br />

4<br />

4.2.2 Cache Issues<br />

Many recent architectures have introduced instruction and data caching to<br />

increase processor performance and reduce CPU bus activity. The most difficult<br />

aspect of memory caching is that the technology has often addressed the cache<br />

coherency problem inadequately.<br />

The cache coherency problem refers to cached information that is redundant with the<br />

information in memory. If another bus master or DMA device updates memory,<br />

the cached data no longer reflects the actual value in memory. Without sufficient<br />

hardware support, solving the coherency problem is left to the software.<br />

Unfortunately, cache management varies greatly from architecture to architecture.<br />

In some cases, the architecture provides cache management instructions; in others,<br />

cache management is bundled together with functions for managing virtual<br />

memory.<br />

VxWorks provides a cache library interface that is unified across disparate CPU<br />

architectures. This permits highly portable, high-performance device drivers to be<br />

implemented with VxWorks. For more information, see the reference entry for<br />

cacheLib and 5.8.1 Review of cacheLib Facilities, p.103.<br />

When considering hardware snooping, only full cache snooping is of benefit. Some<br />

processors implement partial snooping, but partial snooping does not meet our<br />

memory coherency requirements. Only when the snoop hardware makes the<br />

memory fully coherent is it useful for VxWorks.<br />

65


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

The combination of copyback cache without snooping is particularly dangerous,<br />

although the risk is reduced if all user buffers are positioned so that they do not<br />

share cache lines with any other buffer. The user can insure that the front end of<br />

any user buffer is aligned on a cache boundary by setting the variable<br />

memDefaultAlignment to the cache line size. This results in all malloc( ) requests<br />

being aligned on the start of a cache line.<br />

The user can protect the rear end of any buffer by increasing the size of the memory<br />

request by one cache line. This guarantees that no other buffer shares a cache line<br />

with this buffer. Having done all this, memory buffers for DMA operations are<br />

relatively safe from the effect of memory coherency in a copyback situation.<br />

Many new processors implement write pipes that can buffer write operations<br />

when the bus controller is busy. This requires device drivers to make use of the<br />

CACHE_PIPE_FLUSH macros for generic drivers. A CACHE_PIPE_FLUSH operation<br />

should be inserted between any I/O write operation and a I/O read operation. If<br />

a routine begins with an I/O read then you should assume that an I/O write<br />

operation precedes it.<br />

4.2.3 MMU Support<br />

VxWorks supports several different MMUs through a virtual memory library.<br />

Because virtual memory is inappropriate for some real-time applications,<br />

VxWorks can be configured to not include virtual memory support.<br />

For more information on VxWorks virtual memory support, see the following:<br />

■<br />

the reference entries for vmBaseLib and vmLib<br />

■<br />

■<br />

VxWorks Programmer’s <strong>Guide</strong>: Virtual Memory Interface<br />

VxWorks Programmer’s <strong>Guide</strong>: Configuration<br />

■<br />

4.5 Enabling the Virtual Memory Library, p.83<br />

4.2.4 Floating-Point Support<br />

Floating point is supported as a tasking extension to avoid costly context switch<br />

times for tasks that do not use floating-point operations. Tasks can be spawned<br />

with a special floating-point option, and context switch callouts provide the<br />

mechanism to initialize, save, and restore a floating-point context. By switching<br />

floating-point data and control registers in and out, each task effectively shares the<br />

single floating-point unit.<br />

66


4<br />

Hardware <strong>Guide</strong>lines<br />

Higher-level transcendental functions are supported in VxWorks in one of these<br />

ways:<br />

■<br />

■<br />

A portable version that avoids using any floating-point instructions is<br />

standard, but can be replaced with an optimized (assembly language) version<br />

for certain architectures with floating-point capabilities. See the discussion of<br />

the selection of optional features in the VxWorks Programmer’s <strong>Guide</strong>:<br />

Configuration.<br />

For floating-point intensive applications, coprocessors offer significant<br />

performance advantages.<br />

4<br />

4.2.5 Other Issues<br />

Other features worth consideration include the following:<br />

■<br />

■<br />

■<br />

The endian byte order selection is transparent to full VxWorks functionality.<br />

An architecture with indivisible read-modify-write operation, such as<br />

test-and-set, is necessary for high-performance backplane network<br />

communication.<br />

Restrict non-maskable interrupts to events that require no operating system<br />

support.<br />

4.3 Memory<br />

This section discusses the following issues:<br />

■<br />

■<br />

■<br />

■<br />

■<br />

■<br />

RAM<br />

ROM<br />

Ethernet RAM<br />

NVRAM<br />

parity checking<br />

addressing<br />

67


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

4.3.1 RAM<br />

VxWorks CISC processors require 1 MB of RAM for a development system that<br />

includes all of the standard VxWorks features, such as the shell, network, file<br />

system, loader, and others. RISC processors typically require more RAM space:<br />

2 MB of RAM is the minimum; 4 MB is encouraged. For a scaled-down production<br />

system, the amount of RAM required depends on the application size and the<br />

options selected.<br />

The primary configuration values controlling the usage of memory are<br />

LOCAL_MEM_LOCAL_ADRS, LOCAL_MEM_SIZE, USER_RESERVED_MEM,<br />

ROM_TEXT_ADRS, ROM_WARM_ADRS, and ROM_SIZE. For more information on<br />

these values, see 2.2.1 <strong>BSP</strong> Source and Include Files, p.12.<br />

4.3.2 ROM<br />

VxWorks CISC processors require a minimum of 128 KB of ROM, which is just<br />

sufficient for VxWorks compressed boot ROMs. RISC processors typically require<br />

greater ROM space; 256 KB of ROM should be considered a minimum. These<br />

figures do not include any ROM-resident application code.<br />

Applications running out of ROM are usually slow because of 16-bit or (more<br />

commonly) 8-bit data width, slow access times, and so on. VxWorks avoids this<br />

problem by typically copying the contents of the boot ROMs into RAM.<br />

For information on creating a ROM-resident VxWorks image, see the discussion of<br />

executing VxWorks from ROM in the VxWorks Programmer’s <strong>Guide</strong>: Configuration,<br />

and the Tornado User’s <strong>Guide</strong>: Cross-Development.<br />

The configuration macros ROM_TEXT_ADRS and ROM_SIZE control the actual<br />

usage of ROM memory space. For more information, see 2.2.1 <strong>BSP</strong> Source and<br />

Include Files, p.12.<br />

The macro ROM_WARM_ADRS is the warm boot entry point used by the<br />

sysToMonitor( ) routine. It is normally defined as a constant offset, normally 8<br />

bytes, above the cold boot entry point ROM_TEXT_ADRS.<br />

4.3.3 Ethernet RAM<br />

Some application designers have elected to provide dedicated pools of memory to<br />

DMA-based Ethernet chips. CPU access to its own memory is therefore<br />

unimpeded by incoming Ethernet packets, thus guaranteeing real-time response.<br />

68


4<br />

Hardware <strong>Guide</strong>lines<br />

Such dedicated pools of memory are supported by the associated VxWorks<br />

Ethernet drivers. These pools of memory should fully support 32-bit data width<br />

accesses, or network performance is seriously compromised.<br />

Refer to the man page for the relevant driver code for information about<br />

configuring dedicated DMA memory pools.<br />

4<br />

4.3.4 NVRAM<br />

VxWorks can use 255 bytes of non-volatile RAM (NVRAM) for storing the<br />

boot-line information. Without NVRAM, the correct boot-line must either be<br />

burned into the boot ROMs or typed in after every reset/power-up during<br />

development.<br />

NVRAM can be implemented with battery-backed static RAM, EEPROM, or other<br />

technology. A number of boards use the Mostek MK48T02, which contains a<br />

time-of-day clock (also optional) in addition to 2040 bytes of battery-backed static<br />

RAM.<br />

Refer to the man page for the appropriate memory driver for more information on<br />

configuring a specific driver. Almost all drivers use the configuration macros<br />

NV_RAM_SIZE, NV_BOOT_OFFSET, and NV_RAM_ADRS. These macros are<br />

usually defined in config.h, bspname.h, or configAll.h. For more information, see<br />

2.2.1 <strong>BSP</strong> Source and Include Files, p.12.<br />

4.3.5 Parity Checking<br />

VxWorks makes no direct use of memory parity checking on the RAM. If parity<br />

checking is desired or needed, it is usually left to the <strong>BSP</strong> or the user to enable<br />

parity and to implement a parity error handling routine. Some architectures may<br />

specify an interrupt or exception vector to be used for parity error handling.<br />

4.3.6 Addressing<br />

The address map for VxWorks itself is not important; however, a complex<br />

distribution of code and data within memory might not be supported by the tool<br />

chain.<br />

The critical addresses in the memory map are: RAM_HIGH_ADRS,<br />

RAM_LOW_ADRS, and ROM_TEXT_ADRS. (See configuration macros for RAM,<br />

described above).<br />

69


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

4.3.7 Bus<br />

This section describes issues of concern when considering the following bus types:<br />

■<br />

■<br />

■<br />

■<br />

VMEbus<br />

Multibus II<br />

PCI, cPCI, and PMC<br />

busless<br />

VMEbus<br />

This section discusses issues of concern to the <strong>BSP</strong> developer considering the<br />

VMEbus.<br />

VME Specification C.1.<br />

Addressing<br />

VME interoperability is crucial for the success of the standard. Special-purpose<br />

extensions to the bus should be confined to the user pins on rows A and C of the<br />

P2, and they should be clearly documented. Under no circumstance is it acceptable<br />

to deviate from the timings presented in the specification.<br />

The VME-64 Specification is a superset of earlier specifications. At this time Wind<br />

River does not provide support for the plug and play features provided in the<br />

VME-64 specification or any of its extensions.<br />

The choice of address map is not critical in VxWorks. Local addresses can obscure<br />

parts of the VME bus address space. Some boards cannot address low memory on<br />

the bus because their local address starts at 0. This is not a problem for VxWorks,<br />

because all VME device drivers are configurable. However, conflicting devices<br />

may be a system issue.<br />

Dynamic Bus Sizing on VMEbus Accesses<br />

There are three address types defined in the specification:<br />

■<br />

A16 short<br />

■<br />

A24 standard<br />

■<br />

A32 extended<br />

In addition, there are often data width restrictions to off-board devices.<br />

Many implementers offer different windows with different data widths (D16 or<br />

D32) to the same VME address.<br />

70


4<br />

Hardware <strong>Guide</strong>lines<br />

Especially useful are windows that break the wider D32 accesses into two D16<br />

accesses automatically. This can be achieved with the dynamic bus-sizing<br />

capability of some architectures (for example, 68K).<br />

Some boards require that a register be initialized to indicate data “direction”<br />

(read/write) in addition to the AM (Address Modifier). This is inconvenient.<br />

See config.h, p.16, for a standard set of configuration macros to declare master and<br />

slave access windows onto the VMEbus.<br />

Wind River does not provide direct support of 64-bit addressing or data. However,<br />

this does not preclude board specific routines from providing such support to the<br />

user.<br />

4<br />

Dual-Port Memory<br />

RMW<br />

Most CPU boards have local (on-board) RAM. Creating a slave access window on<br />

the VMEbus makes the local memory accessible by other CPUs and DMA devices<br />

on the bus. This is also called dual porting. It is required by systems that want<br />

backplane-shared memory to be on the local processor’s RAM. Such dual-ported<br />

memory should fully support RMW cycles as described below.<br />

Dual porting is also required for off board devices that DMA into target memory,<br />

such as the Excelan EXOS-302.<br />

It is useful if the dual-ported memory can be seen by the local processor at the<br />

memory’s external address, although this is often not provided (and is not used by<br />

VxWorks).<br />

Dual-port memory is also very useful during porting; it facilitates the use of<br />

backplane debugging.<br />

Read-modify-write (RMW) must be provided in an indivisible manner.<br />

The board must adhere to the RMW mechanism defined in the VME specification;<br />

namely, a master must keep the address strobe low between the read and the write<br />

portions of the cycle. A correctly functioning dual-ported slave board keeps the<br />

RMW indivisible across both ports by detecting an address strobe that remains<br />

low.<br />

Unfortunately, keeping the address strobe low is only viable if you are reading and<br />

writing the same single address. A more complicated indivisible instruction, such<br />

as CAS, that involves multiple addresses cannot use this, and thus has no correct<br />

mechanism for dual-ported memory. Because VxWorks uses only TAS, this is not<br />

an issue. Some vendors have added a LOCK pin to the P2 bus for this reason.<br />

71


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Arbitration<br />

However, the pin is not part of the standard and is therefore insufficient support<br />

for this mechanism. For most boards this is not an issue.<br />

Caching and/or snooping can be an issue for VME RMW cycles. The shared<br />

memory master board must not introduce any cache coherency problems. It must<br />

be non-cached, or protected by full snooping capabilities, for proper VME slave<br />

accesses.<br />

For some PowerPC implementations, it has been necessary to use bus arbitration<br />

as a global semaphore for VME RMW operations. When a board cannot generate,<br />

nor respond to RMW cycles, using the bus as a global semaphore works. Any<br />

board that cannot use RMW, arbitrates for and holds the VME bus while a read and<br />

write cycle is completed. In addition, the bus master board, where the shared<br />

objects are stored, must implement the same bus lockup protection, even if the<br />

master board can do RMW cycles correctly. This scheme is implemented in the <strong>BSP</strong><br />

sysBusTas( ) and sysBusTasClear( ) functions.<br />

The board should default to bus request level 3 and provide a jumper mechanism<br />

if alternative arbitration levels are supported.<br />

It is often convenient to be able to select the manner of bus-release that can be RWD<br />

(release when done), ROR (release on request), or RAT (release after timeout).<br />

Multiple bus request/grant levels may be critical for systems with many masters<br />

in the backplane; with round-robin arbitration it can guarantee timely access to the<br />

bus for each bus master.<br />

If masters on the same level are daisy chained, the masters far down the bus may<br />

become “starved.”<br />

Arbitration/System Controller<br />

The system controller functionality should be optional and selected by a jumper.<br />

The system controller should not be enabled through a software settable register.<br />

The ability for software to read the system controller state (on/off) is useful.<br />

The bus system controller should assert the bus RESET signal when a “local” reset<br />

is initiated.<br />

The system controller need not arbitrate all bus levels, but if it only arbitrates one<br />

level, it is usually level 3.<br />

It is the responsibility of the system controller to time out and assert the BERR<br />

signal for slave processors. Better implementations allow this timeout to be<br />

72


4<br />

Hardware <strong>Guide</strong>lines<br />

selected from as fast as 16 microseconds to as slow as forever. A system controller<br />

LED is useful for alerting the user to the state of the arbitration logic.<br />

Mailbox Interrupts<br />

Mailbox interrupts and location monitors are similar mechanisms that may be<br />

used as interprocessor synchronization methods.<br />

A mailbox allows the interrupter to pass some information, usually a short or long<br />

word, to the receiver, while a location monitor only causes an interrupt and has no<br />

capability to pass data.<br />

VxWorks uses these mechanisms for synchronization when transmitting network<br />

packets between nodes in the backplane. Without them, VxWorks must rely on an<br />

inefficient polling mechanism that degrades backplane network throughput. One<br />

mailbox or location monitor is used currently, but two or more would be better.<br />

VxWorks can use VME interrupts to drive the backplane driver; this is preferable<br />

to polling but not as good as mailbox interrupts.<br />

No information is actually passed by VxWorks when using mailbox interrupts;<br />

only their interrupt capability is used.<br />

4<br />

VMEbus Interrupts<br />

Although VxWorks does not require VMEbus interrupts, it is a good idea to<br />

support all VMEbus interrupts, especially if off-board Ethernet capability is<br />

required. It may be possible to jumper the enabling and disabling of these<br />

interrupts, but software control is preferable. Allowing software to read the<br />

interrupt state is valuable.<br />

VMEbus Interrupt Acknowledge<br />

VMEbus interrupt requests must be acknowledged by the receiver. While some<br />

implementers have chosen to force the ISR to acknowledge the interrupt, the more<br />

elegant and preferred solution is to have the hardware automatically acknowledge<br />

the request and present the CPU with the correct vector.<br />

Software interrupt acknowledgment is not recommended because it carries a<br />

significant performance penalty.<br />

VME interrupt generation capability is also desirable. This is especially true if the<br />

board is used in a backplane network with boards that do not have mailbox<br />

interrupts. The most important example of this is on a backplane with a Sun board<br />

running SunOS; if VME interrupt generation capability is not provided by the<br />

slave, the backplane driver on the SunOS side needs to poll.<br />

73


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Power Usage<br />

Extractors<br />

VLSI Chips<br />

The VMEbus standard specifies the maximum power draw per voltage level.<br />

Designers must adhere to these restrictions or clearly document additional power<br />

requirements.<br />

The typical maximum power consumption per board is about 7 watts. Boards that<br />

have requirements in excess of this should emphasize it.<br />

VME boards should have card extractors mounted on the front panel.<br />

A number of VLSI chips exist that offer complete VMEbus interface functionality.<br />

Multibus II<br />

This section discusses issues for the <strong>BSP</strong> developer using Multibus II.<br />

Multibus II Specification<br />

Multibus II is actually a collection of bus standards:<br />

■<br />

■<br />

■<br />

■<br />

IPSB. a message-passing bus for communication between boards, using<br />

geographical addressing<br />

ILBX. a memory expansion bus<br />

ISBX. a definition for modules that can be plugged into Multibus II boards<br />

Multibus II Transport Protocol Specification (Intel)<br />

■<br />

Multibus II Interconnect Interface Specification (Intel)<br />

Configuration<br />

There are four address spaces on the bus: memory, I/O, message, and interconnect.<br />

Multibus II boards do not use DIP switches or jumpers for configuration.<br />

Configuration options are set by accessing the target board’s MB II interconnect<br />

space. Typical options are memory-board start and end addresses.<br />

74


4<br />

Hardware <strong>Guide</strong>lines<br />

Hardware Interrupts<br />

Hardware bus interrupts are not used. Instead, messages are used to convey<br />

information (such as device ready) or the actual I/O data. Message passing<br />

provides a reliable and easily expandable means of sending information between<br />

Multibus II agents. All backplane communications between agents can be handled<br />

with messages. No master/slave memory interfaces are required – in fact, memory<br />

interfaces are discouraged for use in communicating between boards. Because<br />

messages contain data, a block of I/O data can be transferred in the same message<br />

as the status or attention information. No memory addressing conflicts arise on the<br />

bus and there are no bus memory caching problems because messages are sent<br />

between agents, not memory addresses.<br />

4<br />

Processor Number<br />

Initialization<br />

Multibus boards are slot independent. At system initialization, the system<br />

controller (slot 0) sends slot ID numbers to each board. The initialization software<br />

on each board then sets up message IDs.<br />

During initialization, any or all boards can use the interconnect space to locate<br />

specific boards on the bus. For example, each device driver can search the bus for<br />

boards that it “recognizes” and can control. This method allows board types and<br />

locations and the system configuration to be determined at run time. Interconnect<br />

registers and the data contained in interconnect records are defined by Intel.<br />

Vendors who comply with the Intel specification identify themselves (via<br />

interconnect data) as compliant. Non-compliant boards may be used; such boards<br />

identify themselves as non-compliant.<br />

Message Passing Protocol<br />

Device Drivers<br />

Intel has defined a transport protocol for use in sending messages; this protocol is<br />

used by many board vendors. This makes adding new device devices easy because<br />

the basic communication between agents uses existing message passing routines<br />

and conventions. There is usually no hardware-specific code that needs to be<br />

written to add a new device once the initial message-passing driver is in place.<br />

A <strong>BSP</strong> normally includes one hardware device driver for the MPC chip (message<br />

passing coprocessor) and a transport software module. All VxWorks I/O device<br />

drivers send or receive messages by communicating on a software level with the<br />

transport layer (or directly with the MPC driver, if necessary). The transport layer<br />

75


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

and MPC driver queue messages and deliver responses back to the appropriate<br />

device driver. Multiple devices can be controlled simultaneously since all<br />

messages contain source and destination addresses, as well as sequence numbers,<br />

etc., that keep track of message traffic.<br />

PCI, cPCI, and PMC<br />

Wind River provides drivers compliant with Rev 2.1 of the PCI Specifications.<br />

These drivers provide support for manual and automatic configuration and<br />

enumeration of devices. Also provided is a interrupt library module that handles<br />

the overloading of PCI interrupt sources. Refer to the reference entries for<br />

pciConfigLib, pciConfigShow, pciAutoCfg, and pciIntLib for more information.<br />

Wind River Technical Note #49 also contains information regarding PCI support.<br />

Busless<br />

When confronted with the task of porting VxWorks to a busless target, Wind River<br />

strongly recommends the use of a NetROM or In-Circuit Emulator. Emulator<br />

object file formats and operations are as varied as the vendors that sell them.<br />

Contact Wind River Systems for information on appropriate combinations.<br />

The initial goal should be to get serial line activity. Start small. Build a simple<br />

polled serial driver and build up from there. Take advantage of any LEDs that can<br />

be blinked as checkpoints in the code are passed. Use an oscilloscope to see that<br />

interrupts are occurring and being acknowledged correctly.<br />

See 3. Creating a New <strong>BSP</strong> for more information on strategies for dealing with the<br />

initial startup of a new <strong>BSP</strong>.<br />

4.4 Devices<br />

Devices should support both read and write access; it is both expensive and error<br />

prone for software to keep copies of registers or other data written to a device.<br />

Devices that have mandatory access timing requirements should not expect<br />

software to delay between accesses (error prone and non-portable), but should<br />

automatically suspend the next access.<br />

76


4<br />

Hardware <strong>Guide</strong>lines<br />

The rest of this section discusses more specific areas of concern for devices that<br />

may be used in your real-time system.<br />

4.4.1 Interrupts<br />

Interrupts are a major consideration in any real-time system. The issue of interrupt<br />

latency can have major influence on system design. The interrupt handler<br />

mechanism in VxWorks is designed to provide minimum interference between the<br />

interrupt event and the execution of the interrupt handler routine. A minimum<br />

response time is published in the benchmarks.<br />

All of this effort could go to waste if the hardware interrupt circuits are designed<br />

in a way that makes interrupt handling cumbersome or inefficient. This is one<br />

reason why certain hardware is not suited to real-time systems design.<br />

Another important fact is that the device drivers are often written to intentionally<br />

disable interrupts for a brief period of time. This is done to guard data variables<br />

that are shared (between task level code and the interrupt handler) from<br />

corruption. Ideally the driver can disable only the interrupt from the device the<br />

driver controls. However, because of some hardware with limiting designs, the<br />

driver must sometimes disable all interrupts on the board. This is not desirable,<br />

because no interrupts can be serviced during this lock-out period.<br />

Some devices are capable of supplying the interrupt vector during the interrupt<br />

acknowledge bus cycle. In addition, some of these devices can provide a modified<br />

vector, where certain bits are changed to indicate the exact cause of the interrupt<br />

within the device. This is a desirable feature because it allows the proper handler<br />

routine within the driver to be executed faster than if only a single shared handler<br />

routine is provided. (A single handler routine needs to poll the device to determine<br />

which of several possible events caused the interrupt).<br />

Many hardware designs include a special class of device: the interrupt controller.<br />

These devices “field” all of the interrupt sources of the board and provide<br />

programmable selection of interrupt parameters for each source. These parameters<br />

may be: the priority level the interrupt generates, the vector the interrupt<br />

generates, and whether the interrupt source is enabled or disabled. Some interrupt<br />

controllers can be programmed to provide round-robin arbitration of interrupt<br />

sources that are set to the same priority level.<br />

The following are guidelines for interrupt circuitry:<br />

(1) Choose devices that can provide the interrupt vector and modify the vector<br />

according to individual events. If not possible, then choose devices that<br />

provide a single vector.<br />

4<br />

77


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

(2) Interrupt controller devices are considered good features. They can replace or<br />

augment the requirement in (1) above. There are several on the market for<br />

which Wind River has support routines. If implemented in-house, make sure<br />

the device is well documented.<br />

(3) Each interrupt source on the board should have the capability to individually<br />

enable/disable the interrupt from reaching the processor. This is so the driver<br />

never needs to alter the CPU interrupt level. An interrupt controller device<br />

usually provides this feature. A simple control register can also be used to<br />

block interrupt signals from a device. Most devices contain an interrupt<br />

enable/disable bit in one of the programmable registers. However, this is not<br />

always true: Wind River has seen devices that have no mechanism for<br />

disabling their interrupt pin from being asserted.<br />

(4) All sources of interrupts must be in the de-asserted state after a hardware reset<br />

or power up. This requirement is generally wise practice, but is especially<br />

important in VxWorks. This is because of the way VxWorks is layered into<br />

modules of different functionality. If a device is asserting its interrupt signal<br />

after reset, some programming of the device or other circuits must be done, at<br />

kernel initialization time, to cause the device to de-assert its signal. The sort of<br />

device-specific knowledge needed to do this is usually contained only in the<br />

device’s driver. It is not appropriate to duplicate this sequence within the<br />

kernel initialization routines.<br />

The only other mandatory requirement for interrupt design is to provide a well<br />

diagramed and documented interrupt vector scheme. Even in a flexible<br />

open-ended design, documentation should mention default vectors and priorities<br />

(if selectable) for the devices on the board.<br />

Some people are confused about the terminology used in discussing interrupts.<br />

Interrupt level refers to an interrupt’s input priority. Priority levels are the means by<br />

which devices interrupt the processor. Interrupt vectors are the ID numbers used to<br />

identify the correct interrupt service routine in response to an interrupt. Drivers<br />

attach service routines to interrupt vectors. Drivers enable and disable interrupt<br />

levels. Also note that while it is normal for a driver to enable the interrupt level<br />

when it is initializing a device, it should not disable the interrupt level when<br />

disconnecting from the device. This is because other devices may share the same<br />

interrupt level.<br />

Wind River Technical Note #46 discusses the creation of standard interrupt controller<br />

devices for use in certain architectures. Please refer to this technical note for further<br />

information.<br />

78


4<br />

Hardware <strong>Guide</strong>lines<br />

4.4.2 System Clock<br />

A system clock interrupt is mandatory. The system clock for VxWorks requires an<br />

interrupt between 30 Hz and ~2 KHz.<br />

The default is 60 Hz and it is desirable to generate this frequency exactly. Relying<br />

on baud-rate generators often makes this precision unattainable.<br />

4<br />

4.4.3 Auxiliary Clock<br />

VxWorks uses an auxiliary clock from 30 Hz to ~2 KHz to profile CPU utilization.<br />

This is required by the spy utility. It is useful to have a 24-bit (or greater) counter<br />

driven at a high frequency (~10 MHz) for profiling performance.<br />

4.4.4 Timestamp Clocks<br />

Many of the generic timers in target/src/drv/timer include timestamp<br />

functionality. A timestamp driver provides a high-resolution time measurement<br />

facility, typically used by the WindView product. See the WindView User’s <strong>Guide</strong>:<br />

Creating a VxWorks Timestamp Driver for more information on the API.<br />

4.4.5 Serial Ports<br />

VxWorks currently requires one RS-232 serial port, which is needed during the<br />

development and debug phases. The device should be configurable to operate at a<br />

number of “standard” baud rates; 9600 is preferred. Standard communications<br />

parameters are 8 data bits, 1 stop bit, no parity, and no modem control lines. It is<br />

possible to boot VxWorks without a serial interface, and in production, it is<br />

conceivable that embedded systems will not have a serial interface.<br />

The preference is to consider the target board to be DCE. Therefore, the RS-232<br />

connectors should be one-to-one and not null-modem (pins 2 and 3 crossed). This<br />

allows for a straightforward connection to a standard terminal.<br />

VxWorks supports software flow control; hardware flow control signals are<br />

usually ignored. Therefore, only three lines (transmit, receive, and signal ground)<br />

are required for operation.<br />

The API for SIO type serial drivers has been expanded to include support for<br />

hardware flow control and for changing the operational parameters for each serial<br />

device. The user can alter the hardware options flag for each device in order to<br />

79


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

change the number of data bits, data parity, stop bits, and to enable or disable<br />

hardware flow control. The default settings are always to use 8 data bits, 1 stop bit,<br />

no parity, and no hardware flow control. The ioctl code for changing hardware<br />

options is SIO_HW_OPTS_SET (0x1005). The code SIO_HW_OPTS_GET (0x1006)<br />

can be used to read the current hardware options. See target/h/sioLib.h for the<br />

values assigned to the options flag bits. Not all drivers have been updated to<br />

respond to these new ioctl commands yet. Currently only the Zilog 8530 driver, the<br />

Motorola MC68681, and the Intel 8250 drivers have been fully updated with this<br />

feature.<br />

Additional serial ports may be provided by the hardware and required by the<br />

application, they are not required by VxWorks. If multiple serial ports are present,<br />

their baud rates should be independently settable.<br />

4.4.6 Ethernet Controllers<br />

VxWorks is very “network oriented,” at least during the development phase; thus,<br />

it is highly desirable to have a networking interface available. The interface can be<br />

used for booting and downloading application code as well as application-specific<br />

interprocessor communication. VxWorks provides a device-independent interface<br />

to Ethernet controllers via netLib, which permits the use of RPC and NFS and<br />

other Internet protocols.<br />

There are two basic classes of Ethernet devices on the market: those that share<br />

memory with the CPU and other bus devices, and those that maintain a private<br />

packet buffer hidden from the CPU.<br />

The devices that share memory with the CPU do so through DMA bus cycles. This<br />

implies that the device is sharing cycles on the bus while it is transmitting and<br />

receiving data. This can have a non-deterministic effect on the application.<br />

The devices that hide the packet buffer from the CPU typically require CPU<br />

processing to move the packet data in and out of the private buffer. This is<br />

commonly done with byte or word moves to or from a register on the device. This<br />

model may provide better deterministic behavior because the CPU is in complete<br />

control of the movement of packet data.<br />

Within the shared memory class of devices is another classification: those devices<br />

that only deal with contiguous memory, and those devices that deal with<br />

fragmented memory. Devices that can deal with fragmented memory are generally<br />

preferred for VxWorks, because the network interface driver exchanges mbufs with<br />

the protocol modules, and mbufs are basically memory fragments. If a device can<br />

80


4<br />

Hardware <strong>Guide</strong>lines<br />

only deal with contiguous memory, the driver must copy the packet data between<br />

mbufs and this contiguous memory, which can affect performance.<br />

If a device from the shared memory class is used, it is advantageous to select one<br />

that does not have any addressing or memory segment restrictions. This keeps the<br />

driver simpler, more efficient, and more generic.<br />

If data caching is an issue with the selected processor, it is advantageous if the<br />

Ethernet controller/DMA device and the CPU have hardware cache coherency<br />

support such as the snoop lines on the MC68040 and the Intel 82596, or if the<br />

Ethernet device and the memory it uses can be “marked” as non-cacheable. If<br />

hardware support is not available, the driver must take into consideration cache<br />

coherency, performing cache-invalidate or cache-flush operations at appropriate<br />

times. This makes the driver more complex and less generic.<br />

Designing a CPU board to include an Ethernet chip saves the expense of additional<br />

off-board networking hardware (in a “bus-full” environment) and, potentially, has<br />

a higher performance.<br />

A detailed description of writing a VxWorks END network device driver is<br />

included in H. Implementing a MUX-Based Network Interface Driver.<br />

4<br />

4.4.7 SCSI Controllers<br />

SCSI (Small Computer Systems Interface) controllers can be used to control hard<br />

disks, floppy disks, and tape drives. These devices can be used for local booting<br />

and data storage as required by the application. VxWorks provides a<br />

device-independent interface to SCSI controllers through scsiLib, which also<br />

permits the use of the MS-DOS and RT-11 compatible file systems and the<br />

“low-level” raw file system.<br />

The use of a SCSI controller with internal or external DMA capability is not<br />

required, but use of DMA greatly enhances the performance of the driver. The<br />

same cache coherency and addressing issues that apply to Ethernet controllers also<br />

apply to SCSI controllers.<br />

It is important that the SCSI controller selected support the type of SCSI target<br />

required by the application. If advanced SCSI features are important, the SCSI<br />

controller must be able to provide the required features.<br />

Wind River no longer supports its original SCSI-1 product. The SCSI-1 library and<br />

drivers are still present in the delivered product, but will not be included in future<br />

releases. Support in the form of technical questions or modifications is no longer<br />

provided. Full support is limited to the SCSI-2 libraries and drivers.<br />

81


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

A detailed description of writing a VxWorks SCSI device driver is included in<br />

I. Writing a SCSI-2 Device Driver.<br />

4.4.8 DMA Controllers<br />

DMA controllers can free the processor of lengthy copies to I/O devices or<br />

off-board memory and may optionally be used by SCSI device drivers.<br />

4.4.9 Reset Button<br />

A reset button should be provided that is functionally equivalent to a power-on<br />

reset. If operating in a bus-full environment, the reset signal may need to be<br />

propagated to the bus.<br />

4.4.10 Abort Button<br />

The ability to generate a non-maskable-interrupt (NMI) allows the user to retake<br />

control from a wayward interrupt-bound processor, without resetting the whole<br />

board.<br />

4.4.11 DIP Switches<br />

Selection of addressing and interrupts is more convenient with DIP or rotary<br />

switches than with jumpers. Software-readable DIP switches (jumpers) are an<br />

advantage during configuration.<br />

In general, it is preferable that all functions except enabling the system controller<br />

be software settable.<br />

4.4.12 User LEDs<br />

LEDs are useful debugging tools, especially on busless targets. They allow for<br />

quick visual inspection of a board to verify its functionality. With a row of LEDs,<br />

information such as error codes can be displayed. (The LEDs should be in an easily<br />

visible place, such as a front panel).<br />

82


4<br />

Hardware <strong>Guide</strong>lines<br />

4.4.13 Parallel Ports<br />

VxWorks provides simple support of parallel ports. Refer to directory<br />

target/src/drv/parallel for supported devices and capabilities.<br />

4<br />

4.5 Enabling the Virtual Memory Library<br />

Before proceeding with this section, review the vmBaseLib and vmLib reference<br />

entries and the VxWorks Programmer’s <strong>Guide</strong>: Virtual Memory Interface.<br />

The vmBaseLib (the base virtual memory support library) and the vmLib (the<br />

VxVMI Option) have similar <strong>BSP</strong> requirements. Because vmBaseLib is bundled<br />

with VxWorks, <strong>BSP</strong>s are written to include it by default. If the VxVMI Option is<br />

installed, the end user need only change INCLUDE_MMU_BASIC to<br />

INCLUDE_MMU_FULL in target/config/bspname/config.h to include the unbundled<br />

library in future builds.<br />

The rest of this section describes the changes you must make in the sysLib.c file<br />

and the config.h file for all supported targets with MMUs, and additional changes<br />

you must make for SPARC targets.<br />

! CAUTION: Due to a limitation in the current implementation of VxWorks, virtual<br />

addresses must equal physical addresses when using 68K MMUs.<br />

4.5.1 Changes to sysLib.c<br />

Virtual memory support has two requirements:<br />

■<br />

Add a physical memory description. This requires the inclusion of one header<br />

file and the definition of two variables. Start with the code example shown in<br />

Example 4-1, and change it as appropriate.<br />

– Local RAM is valid, writable, and cacheable. ROM is valid, read-only, and<br />

often non-cached. I/O devices are valid, writable, and non-cached. If<br />

applicable, VMEbus regions are valid, writable, and usually non-cached.<br />

Flash ROM is usually writable and non-cached if it can be written directly<br />

from the CPU.<br />

83


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

– Address and length parameters must be multiples of VM_PAGE_SIZE,<br />

defined as 8192 in configAll.h.<br />

– Because each mapped page requires a page table entry to be stored in<br />

physical memory, there is a physical memory size-dependent upper limit<br />

to the amount of address space that can be mapped. Do not map vast<br />

regions of VMEbus space. To be safe, do not map more than 32 MB per<br />

record.<br />

– When virtual memory support is enabled (see below), CPU accesses<br />

falling outside the physical memory description result in bus errors.<br />

Memory mapped devices (Ethernet, SCSI, serial, and others) are not<br />

accessible unless included in the sysPhysMemDesc[ ] array.<br />

■<br />

Add the following at the beginning of sysToMonitor( ):<br />

VM_ENABLE (FALSE); /* disable MMU */<br />

Example 4-1<br />

Additions to sysLib.c for Virtual Memory Support<br />

/* includes */<br />

#include "private/vmLibP.h"<br />

/* globals */<br />

PHYS_MEM_DESC sysPhysMemDesc [] =<br />

{<br />

/* adrs and length parameters must be page-aligned */<br />

/* RAM */<br />

{<br />

(void *) LOCAL_MEM_LOCAL_ADRS,<br />

(void *) LOCAL_MEM_LOCAL_ADRS,<br />

LOCAL_MEM_SIZE,<br />

VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE |<br />

VM_STATE_MASK_CACHEABLE,<br />

VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE<br />

},<br />

/* ROM */<br />

{<br />

(void *) ROM_BASE_ADRS,<br />

(void *) ROM_BASE_ADRS,<br />

ROM_SIZE,<br />

VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE |<br />

VM_STATE_MASK_CACHEABLE,<br />

VM_STATE_VALID | VM_STATE_WRITABLE_NOT | VM_STATE_CACHEABLE_NOT<br />

}, /* a16 VME */<br />

{<br />

(void *) SHORT_IO_ADRS,<br />

(void *) SHORT_IO_ADRS,<br />

84


4<br />

Hardware <strong>Guide</strong>lines<br />

0x10000, /* 64 Kbytes */<br />

VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE |<br />

VM_STATE_MASK_CACHEABLE,<br />

VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE_NOT<br />

}<br />

};<br />

int sysPhysMemDescNumEnt = NELEMENTS (sysPhysMemDesc);<br />

4<br />

4.5.2 Changes to config.h<br />

Define INCLUDE_MMU_BASIC to enable basic virtual memory support.<br />

4.5.3 Additional Requirements for SPARC Targets<br />

In SPARC <strong>BSP</strong>s, two global variables in sysLib.c, sysCacheLibInit and<br />

sysMmuLibInit, are used to select appropriate cache and MMU libraries. The<br />

following code segment illustrates this mechanism (Sun-4 MMU example):<br />

/* Sun-4 cache library */<br />

IMPORT mmuSun4LibInit();<br />

FUNCPTR sysCacheLibInit = (FUNCPTR) cacheSun4LibInit;<br />

FUNCPTR sysMmuLibInit = (FUNCPTR) mmuSun4LibInit;<br />

Sun-4 MMU<br />

The Sun-4 MMU page size is typically 8 KB, matching the definition of<br />

VM_PAGE_SIZE in target/config/all/configAll.h. Some hardware implementations<br />

use a different page size. For such a target, override the VM_PAGE_SIZE default<br />

value by adding the following #undef/#define sequence to<br />

config/bspname/config.h (this example assumes a 4 KB page size):<br />

#undef VM_PAGE_SIZE<br />

#define VM_PAGE_SIZE 4096<br />

The Sun-4 MMU supports only eight virtual memory contexts. Additionally, only<br />

66 MB of virtual address space may be mapped at any one time (shared among the<br />

various contexts) because of the finite size of the static RAM containing the<br />

translation tables.<br />

85


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

When defining the global mappings in sysPhysMemDesc[ ], make sure that the<br />

amount of virtual memory being mapped does not exceed 66 MB. Also keep in<br />

mind that additional virtual memory space may be mapped at run-time for private<br />

virtual memory in each of the eight contexts.<br />

SPARC Reference MMU<br />

The SPARC Reference MMU page size is 4KB. Because this does not agree with the<br />

default definition of VM_PAGE_SIZE in config/all/configAll.h, add the following<br />

#undef/#define sequence to config/bspname/config.h:<br />

#undef VM_PAGE_SIZE<br />

#define VM_PAGE_SIZE 4096<br />

Due to a 32-bit physical address assumption in vmLib, it is impossible to fully<br />

represent the 36-bit physical addresses of the SPARC Reference MMU model.<br />

Thus, for the current version of vmLib, physical addresses must be physical page<br />

numbers (that is, physical address shifted to the right by PAGE_SHIFT, or 12 bits).<br />

This affects calls to vmGlobalMap( ), vmMap( ), and vmTranslate( ), as well as<br />

specifications in the sysPhysMemDesc[ ] array. For each of these calls (and<br />

specifications), do the PAGE_SHIFT of the physical address.<br />

For supporting multiple contexts, the SPARC Reference MMU implements a<br />

fourth layer in an otherwise three-layer page table indexed by the current context<br />

number. This table is variable in size and is defined by the constants exported from<br />

the <strong>BSP</strong> as follows:<br />

mmuInitNumContexts<br />

Initial number of contexts in table (which is rounded up to a power of 2 as well<br />

as what fits on a physical page).<br />

mmuMaxNumContexts<br />

Maximum number of contexts in table (not necessarily different than<br />

mmuInitNumContexts).<br />

mmuContextTableAlign<br />

Alignment required for context table.<br />

Each of these can be determined from documentation of the particular SPARC<br />

Reference MMU chips. <strong>BSP</strong> designers may want to limit mmuMaxNumContexts<br />

to prevent the table from getting overly large (on implementations that allow a<br />

large number of context table entries).<br />

86


4<br />

Hardware <strong>Guide</strong>lines<br />

The following is an example of global variables defined in sysLib.c:<br />

/* export parameters of context table */<br />

int mmuInitNumContexts = TI390_SPARC_CONTEXTS;<br />

int mmuMaxNumContexts = TI390_SPARC_CONTEXTS;<br />

int mmuContextTableAlign = PAGE_SIZE;<br />

4<br />

87


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

88


5<br />

Driver <strong>Guide</strong>lines<br />

5.1 Introduction<br />

This chapter describes the general problems associated with writing device<br />

drivers. Additional information on specific device drivers can be found in Wind<br />

River Technical Notes as well as the following appendices:<br />

■<br />

F. Generic Drivers (serial, SIO, memory, timer, and so on)<br />

■<br />

G. Upgrading 4.3 BSD Network Drivers<br />

■<br />

H. Implementing a MUX-Based Network Interface Driver<br />

■<br />

I. Writing a SCSI-2 Device Driver<br />

The software distributed with the <strong>BSP</strong> Kit contains template versions of each<br />

driver type. These template files provide a framework of logic that is shared by<br />

most all drivers of that type. They also explain how that particular driver should<br />

interact with the VxWorks system itself.<br />

This chapter includes a general discussion of cache considerations for DMA driver<br />

design. However, see the appropriate VxWorks Architecture Supplement<br />

document for architecture-specific details of cache implementations.<br />

89


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

5.2 Design Goals<br />

Any design document must begin with a statement of objectives and goals. The<br />

first goal is real-time performance. Other goals include flexibility, maintainability,<br />

readability, and configurability.<br />

Designing for Performance<br />

Drivers must perform well enough to match the real-time kernel’s abilities.<br />

Designing for performance means many things. It certainly means using DMA and<br />

interrupts in an efficient manner. In coding, it means keeping the subroutine<br />

nesting at an optimum level. Too many subroutine calls and restore operations can<br />

reduce performance. This must be balanced against good use of subroutines to<br />

keep code size small and make the design easy to follow and understand.<br />

Designing for performance also means keeping interrupt latency to a minimum.<br />

Interrupt handlers must receive the greatest care in any design. Overall system<br />

performance is just as important as the specific drivers performance.<br />

Code Flexibility/Portability<br />

Flexibility in a device driver relates to adapting to new board configurations. Key<br />

elements here are structured design features and use of macros for all hardware<br />

accesses. Flexibility comes in two flavors: run-time flexibility and compile-time<br />

flexibility. Run-time flexibility usually sacrifices some amount of real-time<br />

performance for an object module that uses pointers to access routines to achieve<br />

the desired flexibility. Run-time flexibility is also called portability. Compile-time<br />

flexibility uses preprocessor macros to customize the system at compile-time for<br />

performance.<br />

Wind River recommends using both methods wherever possible. This gives<br />

compiled object modules the desired portability and still allows the same source<br />

code to be compiled with a different set of macros to generate an optimized<br />

module. The preferred method at Wind River is to use compile time macros to<br />

implement run-time vectored routines. This achieves both goals. A normally<br />

compiled object module will be customizable at run-time to achieve flexibility. Yet,<br />

that same source code can be used with redefined compile time macros to create a<br />

module optimized for performance.<br />

90


5<br />

Driver <strong>Guide</strong>lines<br />

Maintenance and Readability<br />

Most code work is maintenance. Thus, any effort that makes maintenance simpler<br />

is valuable. Adherence to coding standards and quality documentation makes<br />

code easy to read, easy to understand, and easy to maintain. The concern should<br />

be on why things happen. Poor quality documentation is just as bad as insufficient<br />

documentation. All new documentation should be reviewed by at least one other<br />

person.<br />

5<br />

Ease of Configuration<br />

Drivers should not limit the end-user’s options or requirements. Do not impose<br />

limits on the number of devices to be supported or other features. You may not be<br />

able to support all features or modes for a device, but the design should not<br />

preclude their support at a later time.<br />

Performance Testing<br />

All drivers must be tested for performance. In addition to writing the driver, the<br />

engineer must also consider test routines. This involves inserting debug<br />

information as well as benchmark tests. If a standard benchmark test is not<br />

available, then the engineer must consider writing one. Performance testing<br />

should be considered for all types of device drivers, ethernet, SCSI, serial, timers,<br />

interrupt controllers, and the like.<br />

Code Size<br />

In the embedded RTOS market, code size is important. Code size should be<br />

minimized through good structured design. Reducing code size can hurt<br />

performance. The engineer must balance the design to provide performance<br />

without excessive code size.<br />

Reentrancy<br />

Drivers should be fully re-entrant in order to support any number of devices.<br />

Drivers that limit the number of supported devices are not desirable. Instead of<br />

fixed arrays of device information, the user should create a structure for each new<br />

device and pass it to the driver for initialization and control. Alternatively, the<br />

91


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

driver can malloc( ) the structure for each device as part of the device initialization<br />

call. Access to global data structures must be protected by some form of<br />

synchronization. The usual synchronization methods include intLock( ),<br />

taskLock( ), or a mutex semaphore.<br />

#define NUM_LN 2<br />

LN_CTRL ln_softc[NUM_LN]; /* BAD IDEA */<br />

5.3 Design Problems<br />

This section discusses the design problems associated with the variety of hardware<br />

designs, memory-mapped chips, I/O-mapped chips, multi-function chips,<br />

multiple buses and interrupt controllers.<br />

Hardware Designs of All Types<br />

The variety of hardware designs is nearly unlimited. You cannot assume anything<br />

about the hardware connections designers invent. Designers continue to push the<br />

limits requiring software to play an increasing role in the overall system design.<br />

In an ideal world, your first encounter with a new chip would tell you most of<br />

what you need to know for all subsequently derived chips. Experience differs<br />

sharply from this ideal. The first hardware implementation and thus the first<br />

software driver is sure to require extensive modification by the time the technology<br />

has matured.<br />

Memory-Mapped Chips<br />

In memory-mapped systems, designers make choices about how to map the chip<br />

registers into the memory space. Systems using the same chip can map the device<br />

I/O registers in very different ways.<br />

Consider a simple serial chip with 4 byte wide registers. One designer might map<br />

them to 4 consecutive byte addresses. Another using a 16-bit memory system<br />

might map each register on a half-word boundary, using only the low order 8 bits<br />

of the 16-bit memory bus. In another system, the registers could be mapped to long<br />

92


5<br />

Driver <strong>Guide</strong>lines<br />

word addresses. Thus, there are three different implementations with three<br />

different addressing schemes.<br />

Consider also that the designer who chose the long word implementation might<br />

also have chosen to require the driver to use only long word read/write accesses.<br />

The driver cannot even assume that a byte read operation can be used to read a<br />

byte register.<br />

One solution to this problem is to require that all accesses to the chip be restricted<br />

to as few routines as possible. Further, each access to the chip should be declared<br />

in a preprocessor macro that can be redefined so as to meet the special<br />

requirements of any particular system.<br />

5<br />

I/O-Mapped Chips<br />

Most engineers had their first experiences on Motorola processors that use<br />

memory mapped I/O exclusively. However, there is another world of processors<br />

using a separate address space called I/O space. Unfortunately, the C language<br />

does not provide a means to specify if an address is a memory address or an I/O<br />

address. You have to use assembly language subroutines to access the special<br />

instructions to reach data in I/O space. You cannot write a direct expression in C<br />

to do that.<br />

Fortunately, the solution to the memory-mapped problem above also solves this<br />

problem. By defining the special hardware access macros to use a special I/O<br />

subroutine, you can handle devices mapped into I/O space.<br />

Multi-Function Chips<br />

Designers are fond of combining more and more channels (devices) per chip. Then<br />

they thought up the idea for ASIC chips combining multiple devices of different<br />

types into a single piece of silicon. The designers are only limited by imagination<br />

in the ways they can combine silicon building blocks together.<br />

Rather than write a driver for a complete ASIC, you should strive to write drivers<br />

as though each subsection is a separate device. It might be necessary, if<br />

undesirable, for one driver to require support from another driver. If this is the<br />

case, then this must be clearly documented in the dependent driver<br />

documentation. A single large monolithic driver for an entire ASIC is opposed to<br />

the goal of system scalability. The user should be able to exclude features that are<br />

not needed by the application.<br />

93


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Multiple Buses<br />

CPU Local Bus, VMEbus, VXI, QBus, SBus, PCI Local Bus: will it never end?<br />

Computers are getting more complex and it is reaching the embedded computer<br />

arena. Some buses define their own byte ordering differently from the local CPU<br />

byte ordering. You want your drivers to work on any bus with a minimum of<br />

configuration changes. Fortunately, the hardware access macros that were defined<br />

for flexibility come to the rescue once again. It is simple to define the macros to<br />

perform any byte swapping or other bus related operations.<br />

The most complex board system to date is the Motorola MVME-1600 board. The<br />

local bus is the PowerPC MPC bus. The MPC105 chip connects the MPC bus to a<br />

PCI bus. A PCI chip connects to an ISA Bus. A different PCI chip connects the PCI<br />

bus to a Motorola 68040 bus. From the 68040 Bus, there is a VME chip to interface<br />

to the VMEbus. One board, five different buses. VMEbus supports seven interrupt<br />

request levels and 256 possible vectors. PCI supports four interrupt levels. ISA<br />

supports 16 interrupt levels. PCI is little endian by definition. The 040 bus is big<br />

endian by definition. The MPC bus is ambidextrous (either ended).<br />

Interrupt Controllers<br />

Some hardware designs require special interrupt acknowledge steps. Sometimes<br />

interrupts are processed through cascaded chains of interrupt controllers requiring<br />

multiple steps with each interrupt just to reset or clear the interrupt controller<br />

hardware.<br />

With the rush to PCI bus devices, you must insure that all your interrupt service<br />

routines are compatible with chaining. This means that the driver code must<br />

determine if the device is actually asserting an interrupt request and if not then the<br />

code must exit immediately.<br />

Ideally, the device driver should not be concerned with connecting interrupt<br />

vectors. This is definitely an area of <strong>BSP</strong> responsibility. The driver interrupt service<br />

routine should be a global routine that the <strong>BSP</strong> connects to the vector as part of<br />

sysHwInit2( ). If a driver must be involved in the interrupt connect step, then this<br />

should be through a hardware abstraction macro. This needs to be a flexible<br />

interface so that different boards with different interrupt structures can be<br />

supported from the one driver.<br />

94


5<br />

Driver <strong>Guide</strong>lines<br />

5.4 Design <strong>Guide</strong>lines<br />

This section discusses guidelines you should follow when designing a driver for<br />

use with Wind River products. Included are discussions of function naming<br />

conventions, documentation standards, per-device and per-driver data structures,<br />

interrupt service routines, and access macros for chip registers.<br />

5<br />

Names and Locations<br />

Follow the Wind River driver naming convention. Be very careful about routine<br />

and variable names. Each module should have a distinctive prefix and every<br />

routine and variable declared must start with that prefix. The coding conventions<br />

document suggests the module-noun-verb method of name construction. You can<br />

also consider it as being proceeding from generic to specific going from left to<br />

right. Related routines must have a common root and be distinct from each other<br />

by their suffixes.<br />

A poor example:<br />

STATUS fooStartPoll (void);<br />

STATUS fooStopPoll (Void);<br />

Should be (assuming they both are related to a polling operation):<br />

STATUS fooPollStart (void);<br />

STATUS fooPollStop (void);<br />

Only Wind River generic drivers are stored in target/src/drv/xxx. This implies that<br />

all drivers are used by more than one <strong>BSP</strong>, or are expected to be used by more than<br />

one <strong>BSP</strong>. Third party <strong>BSP</strong> writers frequently assume that these directories are for<br />

all drivers, including theirs. Because the future is unpredictable, Wind River<br />

reserves all rights with respect to these directories. Third parties must place their<br />

drivers in the same directory as the <strong>BSP</strong>.<br />

Even Wind River special drivers are placed in the <strong>BSP</strong> directory. Usually these are<br />

modified versions of a generic driver. Sometimes they are just wrappers that<br />

declare a specialized set of macros and then #include the generic driver.<br />

95


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Documentation and Standards<br />

Describe the entire chip with all of its features and operating modes. Code<br />

maintainers need to determine the basis of the chip without resorting to a complete<br />

library search. Most manufacturers now have their data sheets on the World Wide<br />

Web. This makes finding data sheets easier, but a good one paragraph summary of<br />

the chip can save a lot of time spent searching and reading.<br />

Describe the driver modes and limitations. The module description should be an<br />

introduction to both the chip and the driver.<br />

Follow the Wind River coding standard. This enhances readability and eases<br />

maintenance. Have a technical writer review the documentation for clarity and<br />

grammar.<br />

Do a formal code review to check for adherence to the coding standards. There is<br />

no better way to insure quality and readability than to have someone else look at<br />

your code.<br />

Concentrate on documenting how the device and the driver work together. In<br />

addition to missing documentation, there is the problem of useless documentation.<br />

It is not unusual to see documentation that is trivial and redundant. A typical<br />

example would be:<br />

x = 0; /* clear x */<br />

fooReset (&myFoo); /* reset myFoo */<br />

These are not unusual examples. Assembly level programmers are used to<br />

documenting each line of code. In the C era, programmers tend to write comments<br />

preceding the code. The line by line comment model tends to have more useless<br />

documentation. Programmers are warned to avoid the problems with line by line<br />

running comments.<br />

Another point to consider is that the documentation that goes into the generated<br />

man pages is usually more important than comments in the body of the code. This<br />

is information for the user. It must be accurate and clear. Done right, the reader will<br />

understand what the code intends to accomplish. It becomes much easier to spot<br />

problems in code when you understand its goals clearly.<br />

Documentation should tell the engineer how to integrate the driver into the overall<br />

<strong>BSP</strong> package. All special external routines should be documented. Instructions on<br />

initializing the driver should be included. Actual examples of <strong>BSP</strong> integration code<br />

would be very helpful.<br />

96


5<br />

Driver <strong>Guide</strong>lines<br />

Per-Device Data Structure<br />

As part of an object-oriented design, each device should be represented in the<br />

system by a single structure with all the state information included. The object<br />

methods (subroutines) perform operations on objects using an object handle (a<br />

pointer to the data structure representing the object).<br />

New instances of a device object would be created by calling a device create<br />

function in the driver library (xxxDevCreate). During device creation time the<br />

driver should probe to verify that the device is actually present. If not present, the<br />

device creation operation should fail and return a null pointer.<br />

5<br />

Per-Driver Data Structure<br />

In keeping with an object oriented design methodology, there should be a structure<br />

to represent the driver itself. This structure would include all the driver state<br />

information (class variables). From a practical standpoint, having all the driver<br />

data in a single structure makes it easy to display from the CrossWind debugging<br />

tool.<br />

Driver Interrupt Service Routines<br />

Because there may be bus issues related to interrupts, drivers should not call<br />

intConnect( ) directly. The driver should define a macro that can be changed by the<br />

customer to call the correct interrupt connection routine, which may not be<br />

intConnect( ).<br />

#ifndef FOO_INT_CONNECT<br />

#define FOO_INT_CONNECT(vec, rtn, arg)<br />

#endif<br />

intConnect(vec, rtn, arg)<br />

Device driver ISRs must exit immediately if the device is not asserting interrupt.<br />

Do not assume that there is a one-to-one mapping between interrupt vectors and<br />

interrupt handlers. With PCI systems, it is quite likely that interrupt lines are used<br />

to service more then one device. Interrupt routines must examine the device and<br />

determine if it is actually generating an interrupt condition. If not, the interrupt<br />

handling code should exit as quickly as possible.<br />

97


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Access Macros<br />

Every access to chip registers should be made through macros that can be<br />

redefined to accommodate different access methods. Usually, just a read and a<br />

write macro should suffice. In some cases, a modify macro to change individual<br />

bits in a register is also needed. For example:<br />

M68681_READ(addr, pData)<br />

M68681_WRITE(addr, data)<br />

M68681_CLR_SET(addr, clear_bits, set_bits)<br />

Accesses to a command block in memory or on a bus must also be through a<br />

redefinable macro to accommodate byte swapping and address manipulation.<br />

Note that read macros are passed the address of where to return the value read.<br />

They do not return a value like a subroutine returns a value. This is deliberate.<br />

Macros written this way can be replaced by a simple statements, subroutine calls,<br />

or by a block statement. Macros written to return a value cannot be replaced by a<br />

C block statement. For example:<br />

xxx = M68681_READ (x); /* Limited */<br />

M68681_READ (x, &xxx); /* Better */<br />

Minimize preprocessor conditional expressions within code blocks. They should<br />

add to the readability of the code, not reduce it. If the conditional only changes the<br />

value of an argument to a routine, it should be done at the beginning of the file<br />

using a #define. Only conditional expressions that actually change the flow of logic<br />

should be within a function.<br />

In this example, the only change is to one argument of a subroutine call. Putting<br />

the conditional statements inside the subroutine only confuses the reader. It does<br />

this because it has absolutely no effect on the flow of execution.<br />

#ifdef INCL_FOO<br />

fooReset (&myFoo,<br />

#else<br />

fooReset (&yourFoo,<br />

#endif<br />

arg2, arg3, arg4);<br />

98


5<br />

Driver <strong>Guide</strong>lines<br />

To fix this situation, create a new macro that is the value of the argument. Define it<br />

at the head of the file in its proper place, then refer to it at the proper place in the<br />

code. This results in a subroutine that is much easier to understand at first sight.<br />

For example:<br />

/* A better way */<br />

#ifdef INCL_FOO<br />

# define THE_FOO myFoo<br />

#else<br />

# define THE_FOO yourFoo<br />

#endif<br />

. . .<br />

fooReset (&THE_FOO, arg2, arg3, arg4);<br />

5<br />

The general rule shall be to use conditional compilation if it really changes the flow<br />

of execution within the routine. If only argument values, variable names, or<br />

subroutine names are changed then use the technique above to define an<br />

intermediate macro.<br />

Be careful with macro names, neither too simple nor too complex. Both of the<br />

following examples are unsatisfactory:<br />

SIO_READ<br />

NS16550_CONTROL_REGISTER_BIT_7_CLEAR<br />

Do not use structures to declare hardware registers, or memory control blocks. Use<br />

macros for offset constants or to convert a base address into a register address.<br />

Structures are inherently non-portable. This is the single greatest source of failure<br />

when porting drivers across architectures. Even using the same toolchain, the<br />

default structure creation can vary from architecture to architecture. The C<br />

language specification does not specify a standard for structure element<br />

alignments.<br />

typedef struct { /* I8250_DEV */<br />

char CSR;<br />

char DATA;<br />

char MBR;<br />

} I8250_DEV;<br />

/* A better way */<br />

#define I8250_CSR 0<br />

#define I8250_DATA 1<br />

#define I8250_MBR 2<br />

99


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

5.5 Step by Step<br />

The general order shall be to design from the top down, but to implement and test<br />

from the bottom-up.<br />

Top-Down Design<br />

Top-down design means planning and documenting before starting any actual<br />

coding.<br />

■<br />

Template File<br />

Start from a template file or an existing driver. A template file is preferred.<br />

Starting from an existing file usually brings in all the problems of the other<br />

driver code. Wind River provides template files for all classes of drivers.<br />

■<br />

Module Description<br />

Find the chip manual and copy the introductory description of the chip into<br />

the module description body. Then, add paragraphs detailing how this driver<br />

is to work, which parts of the chip will be controlled, and the operating modes<br />

that will be supported.<br />

■<br />

Device Structures<br />

Start by defining a basic per-device data structure and a per-driver data<br />

structure. These structures define the state of the driver and each device. As<br />

structures, the debugger can display the complete state of either with a single<br />

print command.<br />

■<br />

Macro Definitions<br />

Document any macros that can be used to customize the driver for different<br />

applications, such as chip access macros, memory access macros, and the like.<br />

Tell the user what the macros do and how they are defined for the default<br />

situation.<br />

■<br />

Subroutine Declarations<br />

Declare all the subroutines you think the customer and <strong>BSP</strong> writer need to use<br />

this driver. Try to follow the device design with the software design as much<br />

as possible.<br />

■<br />

Block Out Functions<br />

Create the banners and declarations for all the routines you plan to write.<br />

Leave the bodies empty until you are really ready to write code. Write the<br />

subroutine description in the comment block. The comments in the comment<br />

100


5<br />

Driver <strong>Guide</strong>lines<br />

block are more important than those in the code body. They will help others to<br />

study the design without having to read the code bodies.<br />

Bottom-Up Implementation<br />

■<br />

■<br />

■<br />

■<br />

After planning the driver and laying out its skeleton of functions and data<br />

structures, you are ready to implement and test.<br />

Write the Code<br />

Start with device initialization. Write the code to accept a device structure and<br />

initialize it for use. Fill in the bodies to all the other low-level driver functions.<br />

You could do a test compile to check that all the necessary routines are<br />

declared. Examine the symbols in the object module to verify that only the<br />

desired external routines are unresolved.<br />

Test, Debug, Recompile<br />

The usual test, fix, and recompile cycle. Personal preferences guide this phase.<br />

Some code and test one routine at a time.<br />

Work One Layer at a Time<br />

Repeat the write, test, debug, recompile cycle for each layer of code. Thorough<br />

testing of each layer gives confidence in the project. Trying to write all the code<br />

at once can be unmanageable.<br />

Performance Testing<br />

Some set of benchmark tests should be used to verify that the device meets the<br />

usual customers expectations. A wide SCSI device that can only deliver<br />

5 MB/s net throughput is not going to please the customer very much. It might<br />

be necessary for the engineer to write a complete performance benchmark test<br />

as part of the overall project.<br />

5<br />

5.6 Cache Considerations<br />

The VxWorks cache library (cacheLib) was designed to hide architecture and<br />

target details from the rest of the system and to provide mechanisms to maintain<br />

cache coherency. Cache coherency means data in the cache must be in sync (or<br />

coherent) with that in RAM.<br />

101


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Device drivers are one of the module types in a VxWorks system that can have<br />

problems with data cache coherency. (Note that the CPU instruction cache<br />

coherency is maintained elsewhere in the system.) This document describes the<br />

issues of concern to the driver writer and describes how to use the cacheLib to deal<br />

with these issues.<br />

This document also describes how to enable the virtual memory library. This is<br />

necessary if you are using 68K or SPARC architectures. In these architectures, the<br />

VxWorks cache library controls the cache by calling the virtual memory library to<br />

manipulate the memory management unit (MMU).<br />

Only drivers using direct memory access (DMA) need to be concerned with cache<br />

issues. It is only in the area of DMA that caching is a consideration for a device<br />

driver. On architectures that do write-buffering, the driver needs to consider issues<br />

related to WRITE_PIPING.<br />

NOTE: If your target architecture includes an MMU, and you disable virtual<br />

memory support but enable the data cache, then cacheDmaMalloc( ) is unable to<br />

provide buffers safe from cache coherency issues.<br />

NOTE: If you use an MMU, the cache modes are controlled by the cache mode<br />

values in the sysPhysMemDesc[ ] table and not by the configuration macros<br />

USER_I_CACHE_MODE and USER_D_CACHE_MODE. It is a common mistake to<br />

assume these macros always control the cache operating mode.<br />

5.7 Helpful Hints<br />

■<br />

Avoiding printf( ) in drivers<br />

Avoid use of printf( ) in drivers, even for debugging purposes. Use logMsg( )<br />

instead. There may be system interactions between the driver and the I/O<br />

system that would cause printf( ) to crash the system.<br />

■<br />

Calling intConnect( )<br />

Do not call intConnect( )—or any other routine that calls malloc( )—from<br />

within sysHwInit( ). The memory partition library is not initialized and the<br />

system crashes.<br />

102


5<br />

Driver <strong>Guide</strong>lines<br />

5.8 Driver Use of the Cache Library<br />

Before reading this section, review the reference entry for cacheLib. This section<br />

describes how to maintain data cache coherency for device drivers by using the<br />

VxWorks cache library (cacheLib). It also describes the cacheLib mechanism for<br />

controlling the side effects of CPU write piping, and provides additional hints for<br />

handling cache-related issues in your device driver.<br />

5<br />

5.8.1 Review of cacheLib Facilities<br />

The cacheLib reference entries describe the library’s facilities in detail. This section<br />

provides a brief definition of the facilities discussed in this document. Remember<br />

that the cacheLib.h header file contains the function prototypes and macros need<br />

to make use of the cacheLib facilities. Include this file in your driver code.<br />

This document also references the following routine and macros:<br />

■<br />

The cacheDmaMalloc( ) routine allocates memory from the system. It<br />

attempts to use the underlying hardware features to provide a memory region<br />

that is safe from cache coherency issues. This memory region is guaranteed to<br />

start on a cache line boundary, and not to overlap cache lines with adjacent<br />

regions.<br />

■<br />

■<br />

■<br />

The CACHE_DMA_xxxx macros (such as CACHE_DMA_FLUSH) flush,<br />

invalidate, and learn attributes of memory regions provided by the<br />

cacheDmaMalloc( ) routine.<br />

The CACHE_DRV_xxxx macros (such as CACHE_DRV_INVALIDATE) flush,<br />

invalidate, and learn attributes of ordinary memory that the driver controls.<br />

The CACHE_USER_xxxx macros (such as<br />

CACHE_USER_IS_WRITE_COHERENT) flush and invalidate user memory that<br />

is outside the domain of the driver.<br />

5.8.2 Conducting Driver Analysis<br />

Each driver has a set of attributes that define its behavior relative to the cache. This<br />

section provides some guidelines for analyzing your driver for potential cache<br />

coherency problems. When you know the driver’s attributes, you can create a<br />

strategy for use of the cacheLib routines in the driver.<br />

103


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Before proceeding, determine if the device is DMA capable. Is the device capable of<br />

performing read or write accesses directly to memory that is shared with the CPU?<br />

If the answer is no, your driver might not need any of the cache-related facilities of<br />

the cacheLib. Cache issues affect only those devices that can access memory<br />

shared with the CPU.<br />

If the CPU architecture performs buffered writes, then you might need to deal with<br />

WRITE_PIPING even if the device does not include DMA. Device registers that are<br />

memory mapped should not be cached. In most hardware cases, there is a<br />

hardware mechanism provided that keeps I/O addresses from being cached.<br />

However, keep in mind that even a non-DMA type of device can still have issues<br />

related to write pipelining (see Driver Attributes, p.105).<br />

Shared Memory Types<br />

For DMA-type devices, the driver and the device share one or more memory<br />

regions. This shared memory can be of one of the following types:<br />

■<br />

■<br />

Memory that is allocated using the cacheDmaMalloc( ) routine. This memory<br />

is associated with the CACHE_DMA_xxxx macros and is under the control of<br />

the driver and the underlying hardware for cache issues.<br />

Memory that is allocated using the malloc( ) or memalign( ) routine or<br />

declared in the data or bss sections of the module (stack memory must never<br />

be shared with a device). This type of memory is associated with the<br />

CACHE_DRV_xxxx macros and is solely under the control of the driver for<br />

cache issues.<br />

Because you cannot control the positioning of data obtained by these methods,<br />

this type of memory has an inherent problem: the possibility of sharing a cache<br />

line with an adjacent region that does not belong to the driver. This means that<br />

flush and invalidate operations within this region can interfere with the<br />

coherency of the neighbor’s data in the shared cache lines. Therefore, restrict<br />

the use of this type of memory to exclude the first and last cache line in the<br />

region. Because the cache line size varies on different systems, this becomes a<br />

portability issue.<br />

By using memalign( ), it is possible to insure that buffers are cache line aligned<br />

at their starting address. If you need to protect the end of the buffer, you<br />

should increase the size of this request by at least one cache line size. This<br />

insures that the end of the buffer does not share a cache line with any another<br />

buffer.<br />

104


5<br />

Driver <strong>Guide</strong>lines<br />

■<br />

■<br />

Memory that is of unknown origin. This memory is associated with the<br />

CACHE_USER_xxxx macros and is outside the control of the driver. In other<br />

words, the driver does not really know how the memory was allocated, but the<br />

CACHE_USER_xxxx macros assume the memory was allocated using malloc( ).<br />

Memory that is of a fixed or special purpose. This memory is a special region<br />

that is provided by the target hardware and is intended for the exclusive use<br />

of a DMA-type device. This is usually done for performance reasons. This<br />

memory is not part of the system pool, and thus is not associated with the<br />

malloc( ) routine, the cacheDmaMalloc( ) routine, the data section, or the bss<br />

section. There are no cache macros associated with this type of memory. The<br />

hardware usually provides a means to make this entire region non-cacheable.<br />

5<br />

Driver Attributes<br />

This section lists the driver attributes you need to be aware of when planning your<br />

cacheLib strategy. Each attribute is given a name to simplify later discussion.<br />

Other than write pipelining, the attributes are of concern only to a DMA-type of<br />

device.<br />

WRITE_PIPING<br />

The CPU uses write pipelining. Write pipelining means that write operations of<br />

the CPU are held in a pipeline until the optimum state of the external bus<br />

occurs. Write pipelining is used on RISC architectures, such as MIPS. This<br />

technique can seriously affect your driver because it can delay the delivery of<br />

commands or data to the device your driver controls.<br />

This attribute is TRUE if the driver is to be run on a CPU that has a write pipe.<br />

USER_DATA_UNKNOWN<br />

The user data is in an unknown state. This attribute is TRUE if your driver<br />

passes data by address directly between the device and the driver’s user. In<br />

this case, data handed to the driver by the user is of an unknown cache state.<br />

An example of this is a pointer to a data buffer given to a SCSI disk driver for<br />

writing to the disk. In this case, the driver does not know if the buffer has been<br />

flushed to memory, or is still in cache. Conversely, data that is obtained from<br />

the device must be coherent between cache and memory before the pointer to<br />

that data can be given to the user for consumption.<br />

MMU_TAGGING<br />

The hardware provides MMU tagging of cache regions.This attribute is TRUE<br />

if an MMU that allows tagging of memory regions as non-cacheable is<br />

available on the target hardware.<br />

105


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

DEVICE_WRITES_ASYNCHRONOUSLY<br />

The hardware provides asynchronous write operations to shared memory.<br />

This attribute is TRUE if the device can perform write operations to shared<br />

memory asynchronously to driver activity.<br />

SHARED_CACHE_LINES<br />

The hardware allows both the driver and the device to write to a single cache<br />

line. If any single cache line can be written by both the driver and the device,<br />

this attribute is TRUE. An example of this is a shared data structure such as this<br />

one:<br />

struct<br />

{<br />

short command;<br />

short status<br />

};<br />

In this case, the driver is responsible for writing the command field and the<br />

device is responsible for writing the status field.<br />

SNOOPED<br />

The hardware provides bus snooping. This attribute is TRUE if the target<br />

hardware supports bus snooping. Bus snooping makes cache issues transparent<br />

to the driver. Only full bus snooping that maintains full coherency is<br />

supported. Some processors provide partial snooping that does not meet the<br />

requirements of full memory coherency. Without full snooping, this attribute<br />

must be FALSE.<br />

SHARED_POINTERS<br />

The device’s control model allows the driver and the device to exchange<br />

memory pointers. This attribute is TRUE if the driver and the device exchange<br />

memory pointers.<br />

5.8.3 Developing the cacheLib Strategy<br />

This section describes how to devise a cacheLib strategy based on your driver’s<br />

attributes.<br />

Before proceeding, establish the target range that the driver is to support—for<br />

example, a single target, multiple differing targets, or broad support. This decision<br />

affects your choice of cache strategy. For example, a driver intended for broad<br />

support can be restricted to certain cacheLib routines because target specifics are<br />

unknown. However, drivers intended to support only a single known target can<br />

be designed to use the cacheLib routines that make best use of the target hardware.<br />

106


5<br />

Driver <strong>Guide</strong>lines<br />

The level of cache library support designed into a driver must be well documented<br />

in the code. This is an important issue that must not be neglected.<br />

Many of the routines and macros in cacheLib are designed to hide the details of<br />

the underlying hardware. The macros might actually call routines within<br />

cacheLib, or they might do nothing at all. Their action depends on how certain<br />

function pointers are initialized at run-time. The run-time initialization of the<br />

cacheLib is determined by the code in the <strong>BSP</strong> modules, which are where the<br />

actual details of the caching hardware are known. This hiding of details allows<br />

drivers to be broadly targeted, which increases portability.<br />

Good driver design includes portability. The following subsections assume<br />

portability is a goal and discuss target-specific applications only minimally.<br />

5<br />

Flush and Invalidate Macros<br />

Generally, you need to add the flush and invalidate macros to your driver. The<br />

macro set you implement depends on the type of memory you need to control (see<br />

Shared Memory Types, p.104). The flush macro is used on memory locations that are<br />

given to the device for subsequent reading by the device. The invalidate macro is<br />

used before the driver reads from memory locations that were written by the<br />

device.<br />

Portable drivers use flush and invalidate macros wherever needed. The macros are<br />

written to perform null operations if they are not needed on the particular target.<br />

WRITE_PIPING Attribute<br />

The cacheLib macro CACHE_PIPE_FLUSH flushes the write pipeline of the CPU.<br />

Typically, you add this macro to appropriate locations throughout your driver.<br />

Appropriate locations are after one or more commands have been written to the<br />

device. Device commands that require immediate delivery are most important.<br />

These commands are commonly found in initialization sequences or in interrupt<br />

handlers (where an interrupt condition requires clearing).<br />

Deciding when this macro needs to be used requires in-depth knowledge of the<br />

device you are programming. Some devices are not affected by the delays caused<br />

by a write pipeline. Such devices do not require the pipeline flush macro in the<br />

driver. Other devices do not function correctly without a tight synchronization<br />

with the driver. Such devices require liberal use of the pipeline flush macro<br />

throughout the driver.<br />

107


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

It is recommended that you use CACHE_PIPE_FLUSH between an I/O write<br />

operation and a following I/O read operation. Successive writes or reads should<br />

not require any special protection. It is only when switching from writing to<br />

reading that pipeline flushing becomes essential.<br />

Note that flushing of the write pipeline does not mean the cache is automatically<br />

flushed to memory as well. You must still handle cache issues within the driver.<br />

Conversely, flushing or disabling the cache does not automatically flush or disable<br />

the write pipeline. The write pipeline is first in the hierarchy.<br />

SNOOPED Attribute<br />

This attribute is transparent to all memory types. Portable drivers use the<br />

appropriate flush and invalidate macros. However, if SNOOPED is TRUE, the<br />

macros evaluate to null operations. Target-specific drivers do not need flush or<br />

invalidate macros.<br />

Some systems implement partial snooping. They can read snoop and only<br />

invalidate cache data on a write. This does not meet the requirements for fully<br />

coherent memory. In this case, the SNOOPED attribute is FALSE not TRUE.<br />

MMU_TAGGING Attribute<br />

This attribute is transparent to the memory type obtained using the<br />

cacheDmaMalloc( ) routine. Portable drivers use the CACHE_DMA_FLUSH and<br />

CACHE_DMA_INVALIDATE macros. However, if MMU_TAGGING is TRUE, the<br />

macros evaluate to null operations. Target-specific drivers do not need<br />

CACHE_DMA_FLUSH or CACHE_DMA_INVALIDATE macros.<br />

This attribute does not typically affect memory obtained using the malloc( )<br />

routine, the data section, or the bss section. Therefore, appropriate use of the<br />

CACHE_USER_xxxx and CACHE_DRV_xxxx flush and invalidate macros is<br />

required, as described in Flush and Invalidate Macros, p.107.<br />

USER_DATA_UNKNOWN Attribute<br />

With this attribute, your driver must maintain cache coherency of any data that is<br />

passed directly between the device and the user. For outgoing data, first flush the<br />

user data from the cache with the CACHE_USER_FLUSH macro before<br />

commanding the device to access the data. For incoming data, first invalidate the<br />

108


5<br />

Driver <strong>Guide</strong>lines<br />

cache for the device data using the CACHE_USER_INVALIDATE macro before<br />

passing the data to the user.<br />

DEVICE_WRITES_ASYNCHRONOUSLY Attribute<br />

This attribute is only of concern when combined with the SHARED_CACHE_LINES<br />

attribute; see the next two sections.<br />

5<br />

SHARED_CACHE_LINES Attribute<br />

The driver can easily function with this attribute as long as the driver can<br />

synchronize all operations to the data fields that may share a cache line (if the<br />

driver cannot synchronize the operations, see the next section). If the device cannot<br />

write to the data fields until explicitly commanded by the driver, the driver can<br />

sequence the use of flush macros, invalidate macros, and device commands in a<br />

manner that ensures data integrity.<br />

DEVICE_WRITES_ASYNCHRONOUSLY and SHARED_CACHE_LINES Attributes<br />

The combination of DEVICE_WRITES_ASYNCHRONOUSLY and<br />

SHARED_CACHE_LINES attributes can cause problems. Because the driver cannot<br />

synchronize the write operations of the device, the potential exists for data<br />

corruption. This happens if the device performs a write operation, then the driver<br />

performs a flush operation. In this sequence, the data value written by the device<br />

is wiped out by the cache line flush operation.<br />

For this set of attributes, the driver cannot use the general CACHE_DRV_FLUSH<br />

and CACHE_DRV_INVALIDATE macros because the driver can no longer control<br />

the integrity of the shared memory. The shared memory must be obtained using<br />

the cacheDmaMalloc( ) routine. Furthermore, this routine must provide memory<br />

that is write-coherent because the driver cannot perform any flush operations. The<br />

driver can check the attributes of the memory provided by cacheDmaMalloc( ) by<br />

using the CACHE_DMA_IS_WRITE_COHERENT macro. If this macro evaluates to<br />

FALSE, the driver cannot function reliably and should abort.<br />

109


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

SHARED_POINTERS Attribute<br />

This attribute is only a problem if the memory shared between the driver and the<br />

device was obtained using the cacheDmaMalloc( ) routine. Because this routine<br />

can invoke MMU or other special hardware services, the address of the provided<br />

memory can be a virtual address. The device, however, can deal only in physical<br />

addresses.<br />

In this case, use the CACHE_DMA_VIRT_TO_PHYS and<br />

CACHE_DMA_PHYS_TO_VIRT macros to convert between driver-viewed<br />

addresses and device-viewed addresses.<br />

5.8.4 Additional Cache Library Hints<br />

Here are some additional hints for using the cache library:<br />

■<br />

■<br />

Before adding any cacheLib support to your driver, ensure that the driver<br />

works reliably with the data cache turned off. You will not experience cache<br />

coherency problems with the data cache disabled. When you begin to add<br />

cacheLib support, you can enable the data cache. Any changes to the driver’s<br />

reliability can then be attributed to cache issues.<br />

Ensure that the driver works with cacheLib support on a single target first,<br />

using target-specific knowledge to guide the strategy. When this has been<br />

achieved, you can then modify the driver’s cacheLib strategy for broader,<br />

target-independent support.<br />

110


6<br />

Components<br />

6.1 Introduction<br />

Tornado 2.x introduces a new configuration method better suited to handling the<br />

increasing complexity of the VxWorks environment. This method uses Tornado<br />

2.x’s graphical configuration tool, the project facility, to provide users with a view<br />

into the configurable world of VxWorks. The project facility workspace displays a<br />

hierarchically organized list of optional software components that can easily be<br />

configured into VxWorks using point-and-click technology. (For Tornado 2.x,<br />

downloadable applications do not use components.)<br />

For most users, this GUI-level view of the configurable system is enough to satisfy<br />

their development needs. However, the project facility includes an API and a<br />

language, the Component Description Language (CDL), that are used to define<br />

components, their parameters, their dependencies, and their relationships with<br />

other components. This chapter discusses how to use these building blocks, the<br />

API and the CDL, to create or modify the software components that, when<br />

selected, are configured into your VxWorks system image or application.<br />

Components are a high-level means of grouping code and configuration data into<br />

units of functionality, such as “message logging.” Bootable projects are collections<br />

of components, their configuration parameter values, and their build options. In<br />

Tornado 2.x, using the project facility is the only way to manipulate projects; in<br />

other words, projects cannot be configured from the command line. (For more<br />

information about how to use the project facility, see the Tornado User’s <strong>Guide</strong>:<br />

Projects.)<br />

The traditional approach for configuring VxWorks, based on configuration header<br />

files, has become less and less effective coping with the rapidly increasing<br />

complexity of the software. When VxWorks 5.0 was released, there were about<br />

111


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

twenty optional components that could be configured into the VxWorks system<br />

image. By the release of VxWorks 5.4, there were nearly 300, a number that does<br />

not include components offered by third party vendors. Using configuration<br />

header files contributed to development issues in three areas:<br />

Usability. As the system grew in complexity, it became increasingly difficult to<br />

visualize what was in the system. Reading through and modifying lines and lines<br />

of configuration source code became a challenge. Moreover, there was no<br />

mechanism to warn you if the system was misconfigured.<br />

Scalability. Looking at the configuration header files offered no visibility into<br />

dependencies among components. If you do not know what the dependencies are,<br />

you cannot know what is needed nor what can be left out.<br />

New releases. Configuration conflicts among system components occurred when<br />

releasing new product versions, third party components, and customer<br />

modifications because all source code changes occurred in the same two files,<br />

usrConfig.c and configAll.h.<br />

The implementation of the project facility as the configuring tool eliminates the<br />

problems above.<br />

The remainder of this chapter discusses how to work with the Component<br />

Description Language (CDL) and how to release and integrate new components<br />

into the system. Some of the examples in this chapter draw comparisons between<br />

the traditional use of configuration header files and the Tornado 2.x project facility<br />

to illustrate differences between the two schemes, as well as show their<br />

complementarity.<br />

This manual assumes you are already familiar with the functioning of Tornado,<br />

including its project facility. For more information, see the Tornado User’s <strong>Guide</strong>:<br />

Projects.<br />

NOTE: This release does not restrict you from using the configuration header files<br />

to configure VxWorks and applications. In some circumstances, using config.h and<br />

configAll.h complements the project facility.<br />

112


6<br />

Components<br />

6.2 Component Description Language<br />

In the past, the only information in the configuration header files describing a<br />

component was its preprocessor macro (for example, INCLUDE_NFS). Tornado 2.x<br />

introduces the Component Description Language (CDL) which allows for the<br />

graphical presentation of more useful information about each component, such as:<br />

■<br />

■<br />

■<br />

any hierarchical grouping with related components<br />

associated dependencies on other components<br />

configurable properties<br />

■<br />

how it is integrated into an existing system (for component releases)<br />

This information is organized by CDL objects. There are five classes:<br />

– the component object<br />

– the parameter object<br />

– the folder object<br />

– the selection object<br />

– the initialization group object<br />

Because components are the central building block of your configuration, they are<br />

discussed first. This section then provides a look at each of the CDL objects and<br />

their respective properties.<br />

6<br />

6.2.1 Components<br />

Components are basic units of configurable software. They are the smallest,<br />

scalable unit in a system. Through the project facility, the user can include or<br />

exclude a component, as well as modify some of its characteristics.<br />

The CDL uses component description files (CDFs) to describe software components<br />

in a standard way. Each CDF carries the suffix .cdf. Writing conventions for<br />

component description files are presented in 6.3.1 CDF Conventions, p.126. One file<br />

can define more than a single component.<br />

113


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

In Tornado 2.x, a code generator outputs the system configuration files, basing<br />

them only on those components selected for configuration by the user. The overall<br />

configuration of a project is the list of included components and their properties.<br />

Details of how the project facility and code generator work can be found in the<br />

Tornado User’s <strong>Guide</strong>: Projects.<br />

In the past, you thought of components as the code and parameters included in the<br />

system by making modifications to the configuration files (config.h or<br />

configAll.h), as follows:<br />

#define INCLUDE_FOO<br />

For Tornado 2.x, you describe a component by defining its properties in a CDF, as<br />

follows:<br />

Component INCLUDE_FOO { // Define a component called INCLUDE_FOO.<br />

NAME<br />

Foo example component<br />

SYNOPSIS This is just an example component<br />

... // other properties<br />

}<br />

Component properties fall into one of the following four categories:<br />

■<br />

■<br />

■<br />

Code. This can be a combination or subset of object code (modules) and source<br />

code (configlettes and stubs) used in the build of a project.<br />

Configuration Information. CDL provides a rich set of properties to be used to<br />

describe a component. These can be specified, altered, added, or eliminated.<br />

Parameters are configurable properties expressed as data types. These are<br />

typically preprocessor macros used within a component’s configuration code.<br />

There is a separate CDL object used to define parameters.<br />

Integration Information. These properties control how a component is<br />

integrated into an executable “system image,” for example, an initialization<br />

routine and a description of when in the initialization sequence that routine<br />

should be called.<br />

Integration properties also define dependencies among components, replacing<br />

the #ifdef/#endif statements that proliferated in previous versions of<br />

Tornado.<br />

114


6<br />

Components<br />

■<br />

User Presentation. A number of properties control how a component is<br />

presented to the user, that is, how a component appears in the Tornado GUI.<br />

For example, presentation properties define characteristics as basic as a<br />

component’s name and a brief synopsis of the component’s functionality. They<br />

also affect where in the project facility component hierarchy a component,<br />

folder, or selection is displayed.<br />

You can also specify HTML reference pages as support material for a particular<br />

component.<br />

6.2.2 CDL Object Types, p.115 goes into greater detail about the various properties<br />

and their uses.<br />

For more information about working with component description files, see<br />

6.3 Creating Components, p.125 and 6.4 Releasing Components, p.135.<br />

6<br />

6.2.2 CDL Object Types<br />

The Component Description Language supports a number of object classes.<br />

With the proliferation of components, a means of grouping them into related<br />

subsystems has been developed—called folders and selections, each of which is<br />

described by a CDL object. A means of specifying a component’s initialization<br />

order is provided by initialization groups, another object type. Of course, CDL<br />

provides an object to define a component and its properties. And there is an<br />

additional object type for defining parameters, which are component properties<br />

expressed as data types.<br />

Figure 6-1 shows the project facility component hierarchy. Entries (components,<br />

selections, and folders) appear in boldface in the project facility component<br />

hierarchy when they are included in the configuration, in “plainface” when they<br />

are not included, and in italics when they are not installed (that is, when a CDF<br />

already describes a component, but the component’s modules have not been<br />

installed.)<br />

For the complete syntax of each CDL object type, see E.1 Component Description<br />

Language (CDL), p.231.<br />

115


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Figure 6-1<br />

The Project Facility Component Hierarchy<br />

Folder<br />

Selection<br />

Component<br />

Folders<br />

Folders provide a directory-type hierarchy for grouping components that are<br />

logically related. The WDB agent subsystems, the ANSI components, and the<br />

POSIX subsystems are components grouped in folders. In the project facility,<br />

folders are represented by the file folder icon, as shown in Figure 6-1.<br />

Folders can contain more than one component. Before Tornado 2.x, component<br />

grouping was usually accomplished by nesting include statements, for example:<br />

#ifdef INCLUDE_ANSI_ALL<br />

#define INCLUDE_ANSI_ASSERT /* ANSI-C assert library functionality */<br />

#define INCLUDE_ANSI_CTYPE /* ANSI-C ctype library functionality */<br />

#define INCLUDE_ANSI_LOCALE /* ANSI-C locale library functionality */<br />

...<br />

#endif<br />

For Tornado 2.x, the ANSI functionality is contained in a folder described in CDL,<br />

as follows:<br />

116


6<br />

Components<br />

Folder FOLDER_ANSI {<br />

NAME<br />

ANSI C components (libc)<br />

SYNOPSIS ANSI libraries<br />

CHILDREN INCLUDE_ANSI_ASSERT \<br />

INCLUDE_ANSI_CTYPE \<br />

INCLUDE_ANSI_LOCALE \<br />

INCLUDE_ANSI_MATH \<br />

INCLUDE_ANSI_STDIO \<br />

INCLUDE_ANSI_STDLIB \<br />

INCLUDE_ANSI_STRING \<br />

INCLUDE_ANSI_TIME \<br />

INCLUDE_ANSI_STDIO_EXTRA<br />

DEFAULTS INCLUDE_ANSI_ASSERT INCLUDE_ANSI_CTYPE \<br />

INCLUDE_ANSI_MATH INCLUDE_ANSI_STDIO \<br />

INCLUDE_ANSI_STDLIB INCLUDE_ANSI_STRING \<br />

INCLUDE_ANSI_TIME<br />

}<br />

6<br />

Folders offer greater flexibility in grouping components than the pre-Tornado 2.0<br />

method. Previously, #ifdef statements meant that all of the specified #defines were<br />

included simultaneously. Now, folders allow groups to include more than just a<br />

default set of components that are included together (as defined in Tornado 2.x by<br />

the DEFAULTS property of the folder object); components can be added and<br />

removed from the configuration individually (as defined by the CHILDREN<br />

property of the folder object).<br />

Folder information largely affects user presentation. It is not related to<br />

initialization group hierarchy, and thereby the startup sequence, which depend<br />

solely on a component’s initialization group. Folders can contain one or more<br />

components, selections, and other folders; they do not have parameter or<br />

initialization group objects associated with them.<br />

The following properties describe a folder:<br />

NAME<br />

A readable name, the one that appears next to the folder icon in the project<br />

facility component hierarchy.<br />

SYNOPSIS<br />

A brief description of the folder.<br />

CHILDREN<br />

Components, folders, and selections belonging to this folder are called children.<br />

DEFAULTS<br />

The default component(s) that would be included if the folder were “added”<br />

without any overrides. Folder groupings can affect configuration when a<br />

folder is added, because components specified by a folder’s DEFAULTS<br />

property are added all at once.<br />

117


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Figure 6-2<br />

Include Folder Dialog Box<br />

You can ascertain the default components specified for a folder by looking at<br />

the associated CDF, or by viewing the Include Folder dialog box (Figure 6-2),<br />

which is opened by double-clicking on a particular folder in the project facility<br />

component hierarchy. The Include Folder dialog box displays only those<br />

components that are not already configured. If a component is specified as a<br />

default, it appears checkmarked in a newly opened window. To see a complete<br />

set of default values, you would have to uninclude all components in the<br />

folder.<br />

NOTE: Use folder objects only when creating a new grouping of components (new<br />

or existing). Do not modify existing folders in order to include new components.<br />

CDL accommodates that by prepending an underscore to a property name, for<br />

example, _CHILDREN. See 6.4 Releasing Components, p.135 for more information.<br />

For a hierarchical listing of the folders distributed with Tornado 2.x, see E.2 Folder<br />

Hierarchy, p.236.<br />

Selections<br />

Selections are similar to folders, but they are components that implement a<br />

common interface, for example, serial drivers, the WindView timestamp<br />

mechanism, and the WDB communication interface. These components provide<br />

alternatives for the same service, and one or more can be selected for configuration<br />

118


6<br />

Components<br />

in a single project. In the project facility, they are represented by the checkbox icon,<br />

as shown in Figure 6-1.<br />

Prior to Tornado 2.0, there were #ifdef/#else constructs that implemented the<br />

same feature. In this example from Tornado 1.0.1, the user has a choice of the<br />

timestamp device to use with WindView:<br />

#ifdef INCLUDE_USER_TIMESTAMP<br />

... /* user timestamp driver */<br />

#elif defined(INCLUDE_TIMESTAMP)<br />

... /* system timestamp driver */<br />

#else<br />

... /* DEFAULT: sequential timestamp driver */<br />

#endif<br />

6<br />

Selection information, like that for folders, is for user presentation only. It is not<br />

related to initialization group hierarchy, and thereby the startup sequence.<br />

Selections contain one or more components only.<br />

Selections behave like folders, except they add a count for a range of available<br />

components; for example, a selection containing three components might tell the<br />

user only one can be configured at a time, or perhaps two of three. Because of the<br />

count, selections do not contain folders or other selections; nor do they have<br />

parameter or initialization group objects associated with them.<br />

The following properties describe a selection:<br />

NAME<br />

A readable name, the one that appears next to the selection icon in the project<br />

facility component hierarchy.<br />

SYNOPSIS<br />

A brief description of the selection.<br />

COUNT<br />

Set a minimum and maximum count from available options.<br />

CHILDREN<br />

Components from which to select.<br />

DEFAULTS<br />

The default component(s), depending on the count.<br />

119


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

For Tornado 2.x, the same feature captured by the Tornado 1.0.1 code above, would<br />

be written in CDL as follows:<br />

Selection SELECT_TIMESTAMP {<br />

NAME<br />

select timestamping<br />

COUNT 1-1<br />

CHILDREN INCLUDE_SYS_TIMESTAMP \<br />

INCLUDE_USER_TIMESTAMP \<br />

INCLUDE_SEQ_TIMESTAMP<br />

DEFAULTS INCLUDE_SEQ_TIMESTAMP<br />

}<br />

There are three timestamp drivers available, as indicated by the three values for the<br />

CHILDREN property. The COUNT permits a choice of one, that is, a minimum and<br />

a maximum of 1.<br />

Components<br />

The component object class defines the source and object code associated with a<br />

component, much of the integration information, and any associated parameters.<br />

In the project facility, components are represented by the building block icon, as<br />

shown in Figure 6-1.<br />

Previously, this kind of information was included in usrConfig.c or src/config/*<br />

files and surrounded by #ifdef/#endif statements, as follows:<br />

#ifdef INCLUDE_LOGGING<br />

logInit (consoleFd, MAX_LOG_MSGS);<br />

#endif /* INCLUDE_LOGGING */<br />

Tornado 2.x configuration files contain only the information necessary to build the<br />

application or VxWorks, and not all the code related to the hundreds of other<br />

components that could be included. Furthermore, dependencies among<br />

components can be detected and the related components can be automatically<br />

added by the project facility. It does this by analyzing the global symbols in each<br />

associated object module and knowing within which components they are<br />

contained. The same message logging component above could be written in CDL<br />

as follows:<br />

Component INCLUDE_LOGGING {<br />

NAME<br />

message logging<br />

SYNOPSIS Provides logMsg support<br />

MODULES logLib.o<br />

INIT_RTN logInit (consoleFd, MAX_LOG_MSGS);<br />

CFG_PARAMS MAX_LOG_MSGS<br />

HDR_FILES logLib.h<br />

}<br />

120


6<br />

Components<br />

The component object includes the greatest number of properties. The more<br />

commonly used properties are described below; definitions for the rest can be<br />

found in E.1.1 Component Properties, p.232:<br />

NAME<br />

A readable name, the one that appears next to the component icon in the<br />

project facility component hierarchy.<br />

SYNOPSIS<br />

A brief description of the component.<br />

The next four properties are all related to the configuring of code in a project:<br />

MODULES<br />

Object files associated with the component.<br />

CONFIGLETTES<br />

Common configuration source files having source code that typically makes<br />

use of parameters associated with the component.<br />

<strong>BSP</strong>_STUBS<br />

Generic configuration source files that are copied into the <strong>BSP</strong> directory upon<br />

first use. The user can then make <strong>BSP</strong>-specific alterations to the copied files<br />

without affecting other <strong>BSP</strong>s. Note that a modified stub file is shared by all<br />

projects using the same <strong>BSP</strong> as a base.<br />

6<br />

NOTE: Source code can come in the form of a <strong>BSP</strong> stub. <strong>BSP</strong> stubs are supported<br />

in Tornado 2.2; however, stubs are not supported for earlier releases of Tornado 2.x.<br />

HDR_FILES<br />

Header files associated with your configlette code or initialization routine.<br />

These are header files that must be included in order for your configlette or<br />

initialization routine to compile.<br />

ARCHIVE<br />

The archive file in which to find object modules stored other than in the<br />

standard location.<br />

The following property provides configuration information:<br />

CFG_PARAMS<br />

A list of configuration parameters associated with the component, typically a<br />

list of macros. Each must be described separately by its own parameter object.<br />

The next group of properties control integration of the component into the system<br />

image. There is initialization information and dependency information, such as<br />

121


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

that conveyed by linked symbols, required #includes and #excludes, and if/then<br />

#includes:<br />

INIT_RTN<br />

A one-line initialization routine.<br />

LINK_SYMS<br />

A list of symbols to look up in order to include components from an archive.<br />

REQUIRES<br />

A list of component(s) that do not otherwise have structural dependencies and<br />

must be included if this component is included. Typically, list only those<br />

components that cannot be detected from MODULES, that is, by their<br />

associated object files, for example, components with configlettes only or those<br />

that reference other components through function pointers. In this latter case,<br />

REQUIRES can specify a selection.<br />

EXCLUDES<br />

A list of components that can not be included if this component is being<br />

included.<br />

INCLUDE_WHEN<br />

Sets a dependency to automatically include the specified component(s) when<br />

this component is included (that is, it handles nested includes).<br />

INIT_BEFORE<br />

Call the initialization routine of this component before the one specified by this<br />

property. This property is effective only in conjunction with _INIT_ORDER.<br />

_INIT_ORDER<br />

The component belongs to the specified initialization group. This property<br />

places the specified component at the end of the INIT_ORDER property list of<br />

the initGroup object.<br />

Like NAME and SYNOPSIS before them, the following properties also affect user<br />

presentation:<br />

HELP<br />

List reference pages associated with the component.<br />

_CHILDREN<br />

This component is a child component of the specified folder.<br />

_DEFAULTS<br />

This component is a default component of the specified folder. This property<br />

must be used in conjunction with _CHILDREN.<br />

122


6<br />

Components<br />

Parameters<br />

Parameters are one of the user’s primary means of configuring a system. Typically,<br />

one or more parameters control a component’s features. As an example, we can<br />

consider the maximum number of log messages in the logging queue. In Tornado<br />

1.0.1, this was in target/config/configAll.h as:<br />

#define MAX_LOG_MSGS 50<br />

For Tornado 2.x, use the parameter object class to describe those parameters listed<br />

by a particular component’s CFG_PARAMS property. The logging example is as<br />

follows:<br />

6<br />

Parameter MAX_LOG_MSGS {<br />

NAME max # queued messages<br />

TYPE uint<br />

DEFAULT 50<br />

}<br />

The following properties describe a parameter:<br />

NAME<br />

A readable name, the one that appears below the list of parameter IDs in the<br />

Params tab of the project facility’s Properties window, as shown in Figure 6-3.<br />

Figure 6-3<br />

The Properties Window<br />

TYPE<br />

The type of parameter, that is, int, uint, bool, string, exists, or untyped.<br />

123


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Exist type parameters are #defined if their value is TRUE and #undefined if<br />

FALSE.<br />

DEFAULT<br />

The default value of the parameter, which appears above the list of parameter<br />

IDs in the Params tab of the project facility Properties window, as shown in<br />

Figure 6-3.<br />

Initialization Groups<br />

A component must include information that controls how it is integrated into an<br />

executable “system image,” for example, an initialization routine and a description<br />

of when in the initialization sequence that routine should be called. Initialization<br />

groups or initGroups assemble related components for initialization and, thus,<br />

define the system startup sequence. Initialization group hierarchy is run-time<br />

related only and has no impact on the GUI.<br />

For Tornado 1.0.1, the initialization order was determined in<br />

target/config/all/usrConfig.c or target/src/config/*.c files and surrounded by<br />

#ifdef/#endif statements, as follows:<br />

#if defined(INCLUDE_EXC_HANDLING) && defined(INCLUDE_EXC_TASK)<br />

excInit (); /* initialize exception handling */<br />

#endif /* defined(INCLUDE_EXC_HANDLING) && defined(INCLUDE_EXC_TASK) */<br />

#ifdef INCLUDE_LOGGING<br />

logInit (consoleFd, MAX_LOG_MSGS); /* initialize logging */<br />

#endif /* INCLUDE_LOGGING */<br />

...<br />

The <strong>BSP</strong> file sysLib.c determined (and still does) the order of most board hardware<br />

initialization.<br />

An initGroup is a routine from which components and other initGroups are called.<br />

The code in the routine is determined by the included components and their<br />

initialization code fragments. For example:<br />

InitGroup usrIosExtraInit {<br />

INIT_RTN usrIosExtraInit ();<br />

SYNOPSIS extended I/O system<br />

INIT_ORDER INCLUDE_EXC_TASK \<br />

INCLUDE_LOGGING \<br />

...<br />

}<br />

124


6<br />

Components<br />

In the example, the components INCLUDE_EXC_TASK, INCLUDE_LOGGING, and<br />

INCLUDE_PIPES are part of the initGroup usrIosExtraInit. If those components are<br />

included, then their initialization routines are called in the order specified as part<br />

of this initialization group.<br />

The code in an initGroup is synthesized by the project facility into the file<br />

prjConfig.c, always part of every <strong>BSP</strong> project. To see a system’s initialization<br />

sequence, build the project and examine the generated code in prjConfig.c.Tosee<br />

the default initialization sequence, see E.3 Project Initialization Order, p.238.<br />

The following properties describe an initialization group:<br />

NAME<br />

SYNOPSIS<br />

The NAME property can be used to provide a short name for the initGroup;<br />

however, it does not appear anywhere in this release of the GUI. The<br />

SYNOPSIS property is used to provide a brief, readable definition of the<br />

initialization group.<br />

INIT_RTN<br />

The initialization routine that initializes an associated component(s).<br />

INIT_ORDER<br />

Components and initGroups belonging to this initialization group listed in the<br />

order in which they are to be initialized.<br />

6<br />

6.3 Creating Components<br />

This section instructs you how to define your own component or modify an<br />

existing one. You must follow certain conventions when using the CDL. After<br />

describing your component in a component description file, you must place the file<br />

in the proper path, ensuring that the project facility reads the information and<br />

properly includes the component in the hierarchy.<br />

125


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

6.3.1 CDF Conventions<br />

Follow these conventions when working with component description files:<br />

■<br />

■<br />

■<br />

■<br />

■<br />

■<br />

■<br />

All component names are of the form INCLUDE_FOO.<br />

All folders names are of the form FOLDER_FOO.<br />

All selection names are of the form SELECT_FOO.<br />

Parameter names should not match the format of any other object type, but are<br />

otherwise unrestricted. For example, you can use FOO_XXX, but not<br />

INCLUDE_FOO.<br />

All initGroup names should be of the form initFoo. However, Wind River<br />

initGroups use the form usrFoo (for backwards compatibility.)<br />

All component description files have a .cdf suffix.<br />

All .cdf file names begin with two decimal digits, that is, 00xxxx.cdf. These first<br />

two digits control the order in which .cdf files are read within a directory.<br />

6.3.2 CDF Precedence and Paths<br />

The component description files are read at two points:<br />

■<br />

when a project is created<br />

■<br />

after component description files are changed and the project build occurs<br />

The order in which CDFs are read is important to the user. If two files describe the<br />

same property of the same component, the one read last overrides all earlier ones.<br />

The intent is to allow component description files to have some precedence level.<br />

Files read later have higher precedence than those read earlier.<br />

Precedence is established in two complementary ways:<br />

– CDF files reside in certain directories, and those directories are read in a<br />

specified order.<br />

– Within one of these directories, CDFs are read in alphanumeric order.<br />

The project facility sources all .cdf files in any of the following directories. These<br />

directories are read in the order in which they’re presented:<br />

(1) comps/vxWorks<br />

Contains all generic VxWorks components.<br />

126


6<br />

Components<br />

(2) comps/vxWorks/arch/arch<br />

Contains all architecture-specific VxWorks components (or component<br />

overrides).<br />

(3) config/bsp<br />

Contains all <strong>BSP</strong>-specific components.<br />

(4) the project directory<br />

Contains all other components.<br />

Within a directory, to control alphanumeric order, a two digit number is prepended<br />

to each .cdf file. Wind River reserves the first 50 numbers, that is 00xxxx.cdf<br />

through 49xxxx.cdf. The remaining numbers, 50 through 99, are reserved for third<br />

parties. The xx in the .cdf files above are placeholders for these numbers. (That is,<br />

0n+1 overrides 0n.)<br />

This method of setting precedence allows project, <strong>BSP</strong>, and CPU<br />

architecture-specific overrides of generic components or parameters. If a <strong>BSP</strong><br />

provider wanted to change the maximum number of files that can be open<br />

(NUM_FILES) to 75 from the default value of 50, it could be done in a <strong>BSP</strong>-specific<br />

CDF, as follows:<br />

6<br />

Parameter NUM_FILES {<br />

DEFAULT 75<br />

}<br />

If you are creating a new CDF, you must place it in the appropriate path, based on<br />

the nature of the contents and the desired level of precedence. Your choices of<br />

paths are listed above in the discussion about precedence:<br />

– comps/vxWorks for generic VxWorks component descriptions only<br />

– comps/vxWorks/arch/arch for architecture-specific VxWorks component<br />

descriptions<br />

– config/bsp for board-specific component descriptions<br />

– the project directory for all other files<br />

6.3.3 Defining a Component<br />

This section describes the process of defining your own component. To allow for<br />

the greatest flexibility, there is no convention governing the order in which<br />

properties describe a component or the sequence in which CDL objects are entered<br />

127


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

into a component description file. The following steps taken to create the<br />

component INCLUDE_FOO are a suggested order only; the sequence is not<br />

mandatory. Nor is there meant to be any suggestion you use all of the properties<br />

and object classes described.<br />

Step 1:<br />

Name and Provide a Synopsis<br />

To create your new component, first name it and provide a synopsis of its utility.<br />

Component INCLUDE_FOO {<br />

NAME<br />

foo component<br />

SYNOPSIS this is just an example component<br />

...<br />

In the imaginary component INCLUDE_FOO, the NAME property is foo<br />

component. SYNOPSIS informs the user that “this is just an example component.”<br />

NAME and SYNOPSIS affect user presentation only; they have no bearing on<br />

initialization sequence or dependencies.<br />

Step 2:<br />

Describe the Code-Related Elements<br />

Next, describe your component’s code portions by defining any modules and<br />

source configlettes that should be configured in during the build.<br />

NOTE: <strong>BSP</strong> stubs are supported for Tornado 2.2 however, they cannot be defined<br />

for earlier Tornado 2.x releases.<br />

If your imaginary component INCLUDE_FOO has an object module associated<br />

with it, use the MODULES property to specify it. You can specify any number of<br />

modules this way. In the following example, fooLib.o and fooShow.o are listed:<br />

...<br />

MODULES<br />

HDR_FILES<br />

ARCHIVE<br />

CONFIGLETTES<br />

...<br />

fooLib.o fooShow.o<br />

foo.h<br />

fooLib.a<br />

fooConfig.c<br />

Tornado 2.x offers visibility into component dependencies by graphically<br />

presenting component relationships in the Include Components and Exclude<br />

Components windows of the project facility (see Figure 6-4).<br />

128


6<br />

Components<br />

Figure 6-4<br />

Include Components Window<br />

6<br />

The project facility automatically analyzes object module dependencies in order to<br />

calculate component dependencies; for example, if fooLib.o has an unresolved<br />

global for logMsg( ), an automatic dependency upon the component<br />

INCLUDE_LOGGING is detected. For components not shipped in object module<br />

format, CDL supports the explicit listing of component dependencies. If the source<br />

portion contains a call to logMsg( ), the project facility does not detect the<br />

dependency; instead, an explicit dependency upon INCLUDE_LOGGING should<br />

be declared using the REQUIRES property. See Step 6.<br />

If your module is not located in the standard path, use the ARCHIVE property to<br />

specify the archive name, for example, /path/fooLib.a. (For additional instructions<br />

concerning the use of ARCHIVE, see Step 10.)<br />

NOTE: Third parties should create their own archives; do not modify Wind River<br />

archives.<br />

Use the HDR_FILES property to specify any .h files associated with the component,<br />

like foo.h. These files are emitted in prjConfig.c, providing the initialization<br />

routine with a declaration.<br />

If there is source code that should be compiled as part of the component, put it in<br />

a .c file and specify the file name in the CONFIGLETTES property, for example,<br />

fooConfig.c. Component parameters should be referenced in the configlette or in<br />

the initialization routine; otherwise they have no effect.<br />

129


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Step 3:<br />

Set Up Initialization<br />

If your component must be initialized, use the INIT_RTN property of the<br />

component object class to specify the initialization routine and its arguments to be<br />

called, as in fooInit(arg1, arg2). If your component needs more than a single line of<br />

initialization, create or add the initialization code to a .c file and use the<br />

CONFIGLETTES property instead. By associating a configlette with an<br />

initialization routine, you are securing the configlettes place in the initialization<br />

sequence.<br />

...<br />

INIT_RTN<br />

...<br />

fooInit(arg1, arg2);<br />

If you are not using the MODULES property of the component object, use the<br />

LINK_SYMS property to include your object module from a linked archive. The<br />

system generates an unresolved reference to the symbol _fooRtn1, causing the<br />

linker to resolve it by extracting your module from the archive.<br />

...<br />

LINK_SYMS<br />

...<br />

_fooRtn1<br />

Step 4:<br />

Establish the Initialization Sequence<br />

Initialization order is important. You can control when in the initialization<br />

sequence your component is initialized with the _INIT_ORDER property. A<br />

component (or initGroup) that is bound to an existing initGroup using the<br />

_INIT_ORDER property is, by default, initialized last within that group. This is<br />

typically the desired effect; however, you can override this behavior by explicitly<br />

using the INIT_BEFORE property.<br />

...<br />

_INIT_ORDER<br />

INIT_BEFORE<br />

...<br />

usrRoot<br />

INCLUDE_USER_APPL<br />

In the example, INCLUDE_FOO is declared a member of the usrRoot initGroup.<br />

INIT_BEFORE has been used for fine control, and INCLUDE_FOO is initialized<br />

before INCLUDE_USER_APPL.<br />

Alternatively, you can create a new initialization group and declare<br />

INCLUDE_FOO a member; however, you would have to declare the new initGroup<br />

a member of an existing initGroup. For more information on initialization groups,<br />

see E. Component Language.<br />

130


6<br />

Components<br />

NOTE: INIT_BEFORE only affects ordering within the initGroup. Do not reference<br />

a component that is not in the initGroup; this has no effect at all.<br />

Step 5:<br />

NOTE: The INIT_AFTER property has no effect in the Tornado 2.x implementation.<br />

See E.3 Project Initialization Order, p.238 for the default initialization sequence for<br />

Tornado 2.x.<br />

Link Helpful Documentation<br />

Specify related reference entries (in HTML format) with the HELP property.<br />

6<br />

...<br />

HELP<br />

...<br />

fooMan.html<br />

By default, a build automatically includes reference entries related to values<br />

declared by the MODULES and INIT_RTN properties. In the case of<br />

INCLUDE_FOO, in addition to fooMan.html, which is specified by HELP, the build<br />

associates the fooLib and fooShow libraries and the fooInit( ) routine.<br />

Step 6:<br />

Define Dependencies<br />

Use the REQUIRES, EXCLUDES, and INCLUDE_WHEN properties to explicitly<br />

declare dependencies among components. (See Step 2 to learn how the project<br />

facility automatically configures object module-related dependencies.)<br />

The project facility does not detect implicit dependencies when a component is not<br />

shipped in object module format. Likewise, no dependencies are detected when<br />

symbols are referenced by pointers at run-time. Both circumstances require you to<br />

declare dependencies explicitly.<br />

...<br />

REQUIRES<br />

EXCLUDES<br />

INCLUDE_WHEN<br />

...<br />

INCLUDE_LOGGING<br />

INCLUDE_SPY<br />

INCLUDE_POSIX_AIO INCLUDE_POSIX_MQ<br />

In the example, REQUIRES declares that INCLUDE_LOGGING must be configured<br />

along with INCLUDE_FOO. EXCLUDES declares the INCLUDE_SPY cannot be<br />

configured with INCLUDE_FOO. And INCLUDE_WHEN tells the system that<br />

whenever the components INCLUDE_POSIX_AIO and INCLUDE_POSIX_MQ are<br />

included, then INCLUDE_FOO must also be included.<br />

131


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

NOTE: In general, the project facility is designed to increase flexibility when<br />

selecting components, that is, to increase scalability; specifying a REQUIRES<br />

relationship reduces flexibility. Be sure that using REQUIRES is the best course of<br />

action in your situation before implementing it.<br />

Step 7:<br />

List Associated Parameters<br />

In the component object, use the CFG_PARAMS property to declare all associated<br />

parameters, for example, FOO_MAX_COUNT.<br />

...<br />

CFG_PARAMS<br />

...<br />

FOO_MAX_COUNT<br />

Step 8:<br />

Define Parameters<br />

For each parameter declared by CFG_PARAMS, create a parameter object to<br />

describe it. Provide a name using the NAME property.<br />

Use the TYPE property to specify the data type, either int, uint, bool, string, exists,<br />

or untyped.<br />

Use the DEFAULT property to specify a default value for each parameter.<br />

Parameter FOO_MAX_COUNT {<br />

NAME<br />

Foo maximum<br />

TYPE<br />

uint<br />

DEFAULT 50<br />

}<br />

! CAUTION: A component is considered misconfigured if it contains a parameter<br />

without an assigned value. Be sure to assign default values, unless there is no<br />

reasonable default and you want to force the user to set it explicitly.<br />

Step 9:<br />

Define Group Membership<br />

A component must be associated with either a folder or selection, otherwise it is<br />

not visible in the project facility GUI. Assign a component to a folder because of its<br />

logical inclusion in the group defined by the folder, based on similar or shared<br />

functionality, for example. By including a component in a folder, you make it<br />

possible for the user to load it simultaneously with other components in its group<br />

by declaring them as default values for the folder, using the folder object’s<br />

DEFAULTS property.<br />

...<br />

_CHILDREN<br />

...<br />

FOLDER_ROOT<br />

132


6<br />

Components<br />

The _CHILDREN property declares that INCLUDE_FOO is a child component of<br />

folder FOLDER_ROOT. The prepended underscore (“_”) serves to reverse the<br />

relationship declared by the property CHILDREN. You can also use _DEFAULTS in<br />

conjunction with _CHILDREN to specify a component as a default component of a<br />

folder. For more information about this CDL convention, see 6.4 Releasing<br />

Components, p.135.<br />

If you think a component is becoming too complex, you can divide it into a set of<br />

components assigned to a folder or selection object. In the following example,<br />

INCLUDE_FOO has been specified as part of a selection. You can add or remove the<br />

group from your configuration as a unit rather than by its individual components.<br />

For folders, the DEFAULTS property specifies the base set of components that are<br />

included if the group is configured without any overrides.<br />

For selections, the DEFAULTS property specifies the components that are included<br />

to satisfy the count (declared by the COUNT property), if you provide no<br />

alternative values.<br />

In a selection group, the COUNT property specifies the minimum and maximum<br />

number of included components. If the user exceeds these limits the system flags<br />

the selection as misconfigured.<br />

6<br />

Selection SELECT_FOO {<br />

NAME<br />

Foo type<br />

SYNOPSIS Select the type of desired FOO support<br />

COUNT 0-1<br />

CHILDREN INCLUDE_FOO_TYPE1 \<br />

INCLUDE_FOO_TYPE2 \<br />

INCLUDE_FOO_TYPE3<br />

DEFAULTS INCLUDE_FOO_TYPE1<br />

}<br />

Step 10:<br />

Create a Dummy Component<br />

The project facility analyzes archives only when they are associated with included<br />

components. This creates a chicken and egg problem: in order to know about a<br />

particular archive, the project facility would need to analyze components before<br />

they are actually added. In other words, if you add a component declared with an<br />

ARCHIVE property, the configuration analysis is done without knowing what the<br />

value of ARCHIVE is. So, if your component includes an archive with several object<br />

modules, you should create a dummy component that is always included, making<br />

it possible for the project facility to know that a new archive should be read. Call<br />

such a component INSTALL_FOO. It should contain only NAME, SYNOPSIS, and<br />

ARCHIVE properties. The user cannot add other components from the same<br />

archive until INSTALL_FOO is added.<br />

133


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

! CAUTION: Do not alter Wind River-supplied CDFs directly. Use the naming<br />

convention to create a file whose higher precedence overrides the default<br />

properties of Wind River-supplied components.<br />

Step 11:<br />

Generate the Project Files<br />

The project configuration file (prjConfig.c) for each project is generated by the<br />

project facility based on two things:<br />

■<br />

the set of components selected by the user from the component hierarchy<br />

■<br />

the information in the related component description files<br />

To generate this file, click the Build button in the Build tab of the project facility.<br />

NOTE: Generated project files (prjConfig.c) are free of the preprocessor #ifdefs<br />

found in the traditional static configuration files, and, therefore, are easier to read.<br />

6.3.4 Modifying a Component<br />

Modify the properties of existing components by re-specifying them in any higher<br />

priority CDF file. Third-party CDF files are by convention read last and therefore<br />

have the highest priority. Use the naming convention to create a high-precedence<br />

CDF file that overrides the default properties of Wind River components. See<br />

6.3.2 CDF Precedence and Paths, p.126 for the file naming and precedence<br />

conventions.<br />

In the following example, the default number of open file descriptors<br />

(NUM_FILES) in the standard Wind River component INCLUDE_IO_SYSTEM has<br />

been modified. The normal default value is 50.<br />

Parameter NUM_FILES {<br />

DEFAULT 75<br />

}<br />

By adding these example lines of code to a third-party CDF file, by removing and<br />

adding the component if it is already in the configuration, and by re-building the<br />

project, the value of NUM_FILES is changed to 75. The original Wind River CDF<br />

file, 00vxWorks.cdf, is not changed; the default property value is changed because<br />

the third-party file has higher precedence. Other property values remain the same<br />

unless specifically redefined.<br />

134


6<br />

Components<br />

! CAUTION: Do not alter the Wind River-supplied source configlette files in<br />

target/config/comps/src. If necessary, use a <strong>BSP</strong>- or project-specific CDF to cancel<br />

its declaration as CONFIGLETTES and to define <strong>BSP</strong>_STUB (available for Tornado<br />

2.2 only) instead. A copy of the generic file is then placed into the <strong>BSP</strong> directory,<br />

and it can be altered without impacting other <strong>BSP</strong>s, or changing the original file.<br />

! CAUTION: Do not alter Wind River-supplied CDFs directly. Use the naming<br />

convention to create a file whose higher precedence overrides the default<br />

properties of Wind River-supplied components.<br />

6<br />

6.4 Releasing Components<br />

The process of releasing a Tornado component has been designed to preclude<br />

modification of existing configuration files. New component description files<br />

should be independent of existing files, with two exceptions:<br />

■<br />

New component objects must be bound into an existing folder or selection.<br />

■<br />

New component object initialization routines must be associated with an<br />

existing initGroup.<br />

A particular CDL convention makes it possible to bind a new component object to<br />

an existing folder or selection and to an existing initGroup without modifying the<br />

existing elements. By prepending an underscore (“_”) to certain component<br />

properties, you can reverse the meaning of the property. For example, if there is<br />

already a folder FOLDER_EXISTING and an initGroup initExisting, you can bind<br />

a new component to them (without modifying them), as follows:<br />

Component INCLUDE_FOO<br />

...<br />

_CHILDREN FOLDER_EXISTING<br />

_INIT_ORDER initExisting<br />

}<br />

The property _CHILDREN has the opposite relationship to FOLDER_EXISTING as<br />

CHILDREN; that is, _CHILDREN identifies the “parent.” In other words, it<br />

produces the same effect as FOLDER_EXISTING having the component<br />

INCLUDE_FOO on its list of children—without any modifications being made to<br />

the CDF containing the FOLDER_EXISTING object.<br />

135


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

If your project or VxWorks system image includes Tornado components from a<br />

previous release (that is, earlier than version 2.0), then, to ensure backwards<br />

compatibility, use the old INCLUDE_XXX format to create the component ID. In<br />

6.3.3 Defining a Component, p.127, INCLUDE_FOO is both a component ID, as well<br />

as the name of the preprocessor macro used in the old-style configuration.<br />

You can release more than one component at a time, because more than one<br />

component can be defined by a single CDF. You can release any number of CDFs<br />

simultaneously.<br />

6.4.1 Testing New Components<br />

There are several tests one can run to verify that components have been written<br />

correctly:<br />

■<br />

Check Syntax and Semantics<br />

This command-line test is the simplest verification test. First edit the file<br />

installDir/host/resource/tcl/app-config/Project/cmpTestLib.tcl, setting the<br />

TCL variable bspFile to a valid <strong>BSP</strong> directory name (for example, mv162).<br />

Then run the cmpTest script.<br />

% cd $(WIND_BASE)/host/resource/tcl/app-config/Project<br />

% wtxtcl<br />

wtxtcl> source cmpTestLib.tcl<br />

wtxtcl> cmpTest<br />

The cmpTest script tests for syntax and semantics errors in your .cdf files (in<br />

fact, in all .cdf files). Based on test output, make the required modifications.<br />

Keep running the script until you have removed the errors.<br />

■<br />

Check Component Dependencies<br />

You can test for “scalability bugs” in your component by running the cmpInfo<br />

script as follows:<br />

wtxtcl> cmpInfo <br />

This reports back to you the component’s subtree (other components needed<br />

by your component) and its supertree (other components that need your<br />

component).<br />

136


6<br />

Components<br />

■<br />

Check the Project Facility Component Hierarchy<br />

Verify that selections, folders, and new components you have added are<br />

properly included by making a visual check of the project facility component<br />

hierarchy.<br />

Open the project facility and go to the VxWorks view.<br />

Look at how your new elements appear in the folder tree. Check the<br />

parameters associated with a component and their parameter default values<br />

by invoking the Properties window.<br />

If you have added a folder containing components, and have included that<br />

folder in your configuration, the project facility component hierarchy should<br />

display in boldface all components listed as defaults for that folder (that is,<br />

values for the DEFAULTS property). Verify that the resulting image builds and<br />

boots.<br />

6<br />

6.4.2 Packaging a Component<br />

For details on packaging, see 10.3 Component Packaging, p.200.<br />

137


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

138


7<br />

Validation Testing<br />

7.1 Introduction<br />

This chapter describes the Board Support Package (<strong>BSP</strong>) Validation Test Suite (<strong>BSP</strong><br />

VTS). The <strong>BSP</strong> VTS is a collection of host-initiated test programs that exercise a<br />

target machine. The purpose of these tests is provide an objective (although not<br />

exhaustive) report that you can use to judge the basic functionality of a VxWorks<br />

<strong>BSP</strong>. To help ensure the repeatability of the tests, the <strong>BSP</strong> VTS is highly automated.<br />

Once started, a <strong>BSP</strong> test requires no user intervention.<br />

This version of the <strong>BSP</strong> VTS runs in a Tornado environment only, and it supports<br />

both UNIX and Windows hosts. To provide portability between UNIX and<br />

Windows hosts, the <strong>BSP</strong> VTS scripts are written in Tcl/WTX functions. These tests<br />

exercise the basic functionality of <strong>BSP</strong>s and detect and report defects found in<br />

them.<br />

If these basic tests are inadequate to your needs, you can edit the source code to<br />

enhance the existing tests or to add new tests of your own. However, if you choose<br />

to modify the <strong>BSP</strong> VTS, you should leave the basic set of tests intact. These basic<br />

tests are the standard by which <strong>BSP</strong>s are judged.<br />

Other Documentation<br />

For reference information on the <strong>BSP</strong> VTS and its component tests, see the<br />

reference entries provided in J. <strong>BSP</strong> Validation Test Suite Reference Entries. For<br />

information on the Tcl language, see the Tornado User’s <strong>Guide</strong>: Tcl or any standard<br />

Tcl reference, such as Practical Programming in Tcl and TK by Brent B. Welch, or Tcl<br />

and the Tk Toolkit by John Ousterhout.<br />

139


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

7.2 Background<br />

This section is intended to provide background information on the <strong>BSP</strong> VTS,<br />

including design goals, the tools used to implement them, and the general<br />

configuration of a test environment.<br />

7.2.1 Design Goals<br />

The following is a list of design goals that guided the implementation of the <strong>BSP</strong><br />

VTS. Being aware of these goals should help you better understand how to set up<br />

the tests, run the tests, and interpret the results. You should also keep these design<br />

goals in mind if you decide to modify the <strong>BSP</strong> VTS.<br />

■<br />

■<br />

■<br />

■<br />

■<br />

■<br />

■<br />

Tornado Compatible. The <strong>BSP</strong> VTS should be run on Tornado release 2.0 or<br />

later.<br />

Broadly Usable. The <strong>BSP</strong> VTS should be usable by as wide a range of users as<br />

possible (board vendors, end-user customers, and Wind River developers). In<br />

addition, the tests should be able to handle both bus-full (VME) and standalone<br />

configurations.<br />

Portable. The <strong>BSP</strong> VTS should be both target- and host-architecture portable.<br />

Repeatable. All the tests should be repeatable. Thus, for a given test<br />

environment, the tests should behave the same no matter where or when they<br />

are run.<br />

Automatic. The user should be able to run <strong>BSP</strong> VTS from a single invocation<br />

(command), and the test results should be collected in a test log. The user<br />

should be able to run a subset of the tests from a single invocation.<br />

<strong>BSP</strong>-Specific. The <strong>BSP</strong> VTS should only be concerned with those aspects of<br />

VxWorks pertaining to <strong>BSP</strong> implementation and configuration.<br />

Host-Controlled. The test environment should include a single test host, a<br />

VxWorks-supported host computer suitably equipped and configured with<br />

the necessary hardware and software to permit the <strong>BSP</strong> VTS to execute<br />

correctly. This includes:<br />

– appropriate host tools (compilers and the like)<br />

– a complete Tornado development environment<br />

– a complete <strong>BSP</strong> Developer’s Kit at the correct release level<br />

– the complete source to the <strong>BSP</strong> under test<br />

140


7<br />

Validation Testing<br />

■<br />

■<br />

The test host should control the execution of the tests. This is necessary,<br />

because no assumptions can be made about the target, other than that it is<br />

capable of running VxWorks and interacting with the target server on the host<br />

and the target’s console serial port.<br />

Second Target Capable. The network, busTas, and rlogin tests require the use<br />

of a second target board, the reference board. This reference board must run a<br />

previously validated <strong>BSP</strong>.<br />

Target Shell Capable. The target server <strong>BSP</strong> VTS rlogin test requires a<br />

VxWorks target shell.<br />

7<br />

7.2.2 Validation Test Suite Software Architecture<br />

Single Target<br />

This section describes the typical <strong>BSP</strong> VTS software architecture for a single target<br />

and for multiple targets.<br />

Figure 7-1 shows the overall configuration for a single target.<br />

Figure 7-1<br />

Example <strong>BSP</strong> VTS Software Architecture: Single Target<br />

Host (UNIX/Windows)<br />

Target (VxWorks)<br />

target server<br />

connection<br />

test<br />

script<br />

target<br />

server<br />

ttya or<br />

com1<br />

target<br />

agent<br />

VxWorks<br />

/tyCo/0<br />

The typical test scenario is as follows:<br />

1. The Tcl/WTX test script runs on the UNIX /Windows host.<br />

2. The script attaches to the target server, which uses the target server back end<br />

communication link to communicate with the target through the target agent.<br />

If serial communication is required, the script uses a serial line on the host (ttya<br />

141


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

on UNIX or com1 on Windows) to open a channel to the target’s /tyCo/0 or any<br />

other port that is configured as console.<br />

3. When console interaction with the target is required, the script communicates<br />

with each target by sending WTX or WindSh commands and reading the<br />

console output.<br />

Multiple Targets<br />

Figure 7-2 shows the overall configuration of a two-target test system.<br />

Figure 7-2<br />

Example <strong>BSP</strong> VTS Software Architecture: Two Targets<br />

Host (UNIX/Windows)<br />

Target 0 (VxWorks)<br />

target<br />

server<br />

target server<br />

connection<br />

ttya or<br />

com1<br />

target<br />

agent<br />

VxWorks<br />

test<br />

script<br />

/tyCo/0<br />

Target 1 (VxWorks)<br />

target<br />

server<br />

target server<br />

connection<br />

target<br />

agent<br />

VxWorks<br />

ttyb or<br />

com2<br />

/tyCo/0<br />

The typical test scenario is as follows:<br />

1. The Tcl/WTX test script runs on the UNIX or Windows host.<br />

142


7<br />

Validation Testing<br />

2. The script attaches to the first target server, which uses the target server back<br />

end communication link to communicate with Target 0 through the target<br />

agent. If serial communication is required, a channel from ttya (UNIX) or com1<br />

(Windows) to Target 0’s /tyCo/0 or any other port that is configured as console<br />

is opened via the first serial line.<br />

3. The script attaches to the second target server, which uses the target server<br />

back end communication link to communicate with Target 1 through the target<br />

agent. If serial communication is required, a channel from ttyb (UNIX) or com2<br />

(Windows) to Target 1’s /tyCo/0 or any other port that is configured as console<br />

is opened via the second serial line.<br />

4. When console interaction with the target is required, the script communicates<br />

with each target by sending WTX or WindSh commands and reading the<br />

console output.<br />

7<br />

7.3 Configuring the <strong>BSP</strong> VTS<br />

This section describes the following:<br />

■<br />

■<br />

■<br />

the required hardware configuration<br />

installing the <strong>BSP</strong> VTS<br />

configuring the system: the host, the target, VxWorks, and the <strong>BSP</strong> VTS itself<br />

Read this section in conjunction with Tornado User’s <strong>Guide</strong>: Setup and Startup.<br />

7.3.1 Hardware Setup<br />

Bus-full<br />

The <strong>BSP</strong> VTS assumes a minimum target system setup. This can be either a bus-full<br />

environment (traditional) or a standalone configuration. For some tests, such as<br />

the backplane tests, a second CPU board is required.<br />

Figure 7-3 shows a typical bus-full configuration, which consists of the following:<br />

Chassis<br />

A card cage with backplane, typically a VMEbus, and a power supply.<br />

143


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

CPU board<br />

The single-board computer (the target) to which VxWorks has been ported.<br />

This board runs the <strong>BSP</strong> under test.<br />

Ethernet board<br />

An Ethernet controller board (some CPU boards include an on-board Ethernet<br />

controller).<br />

Serial port<br />

One or more serial ports on the workstation and target. This is required for<br />

initial setup and test execution and for the serial port tests.<br />

Figure 7-3<br />

Typical <strong>BSP</strong> Test Configuration: VME<br />

File Server Workstation Chassis<br />

VxWorks<br />

target CPU<br />

Ethernet<br />

board<br />

RS-232<br />

Ethernet<br />

Standalone Board<br />

Figure 7-4 shows a typical standalone configuration:<br />

CPU board<br />

The standalone computer board (the target) to which VxWorks has been<br />

ported. This board runs the <strong>BSP</strong> under test. It can include an Ethernet<br />

controller.<br />

Serial port<br />

One or more serial ports on the workstation and target. This is required for<br />

initial setup and test execution and for the serial port tests.<br />

144


7<br />

Validation Testing<br />

Figure 7-4<br />

Typical <strong>BSP</strong> Test Configuration: Standalone<br />

File Server Workstation Standalone Board<br />

VxWorks<br />

target CPU<br />

RS-232<br />

7<br />

Ethernet<br />

The <strong>BSP</strong> VTS supports VxWorks in standalone ROM. To do this, the <strong>BSP</strong> VTS<br />

checks for and uses a standalone ROM image when booting the target. However,<br />

the <strong>BSP</strong> VTS can do this only if you have built the VxWorks standalone image with<br />

the necessary configuration macros for allowing a target server connection with<br />

the target. For example, for a network connection between a VxWorks standalone<br />

target and the target server, the macros INCLUDE_NETWORK,<br />

STANDALONE_NET, and INCLUDE_WDB must be defined.<br />

All tests applied to a VxWorks target require a target server running on the host for<br />

that target. Target server back end communication with the target can be through<br />

Ethernet or serial connection using SLIP or any other valid communication<br />

mechanism for which the target server can be configured. For more information<br />

about configuring the target server, see the Tornado User’s <strong>Guide</strong>: Target Server<br />

(Windows Version) or the Tornado User’s <strong>Guide</strong>: Setup and Startup (UNIX Version).<br />

Given this connection, the <strong>BSP</strong> VTS can build and load the test library (pkLib.o)<br />

through the target server. For more information, see Configuring VxWorks, p.148.<br />

7.3.2 Installing the <strong>BSP</strong> VTS<br />

The general procedures for installing the <strong>BSP</strong> VTS are the same as those for<br />

installing any other Wind River product. See the Tornado Getting Started <strong>Guide</strong> for<br />

145


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

software installation instructions. If the reference <strong>BSP</strong> has not previously been<br />

installed, refer to the installation instructions that came with that <strong>BSP</strong>.<br />

Directories and Files<br />

Host Support<br />

The <strong>BSP</strong> VTS tests are in the host/src/test/bspVal/src/tests directory. The Tcl source<br />

files on which the <strong>BSP</strong> VTS is built reside in the host/src/tcl directory. The source<br />

files for the tclserial library reside in host/src/test/tclserial. The binaries for tools<br />

and the execution script that runs the <strong>BSP</strong> VTS reside in the host/hostType/bin<br />

directory. The configuration files for <strong>BSP</strong> VTS reside in the<br />

host/resource/test/bspVal directory.<br />

The <strong>BSP</strong> VTS is implemented in Tcl, version 7.6. The <strong>BSP</strong> VTS script starts as a<br />

UNIX shell script and later runs a Tcl script under the wtxtcl shell, which is a<br />

binding of the WTX protocol to the Tcl language. In essence, the <strong>BSP</strong> VTS script<br />

runs as a tool attached to the target server(s).<br />

The tclserial library provides a set of functions that allow communication with a<br />

serial port. There is no need to generate the Tcl binary and tclserial libraries if you<br />

are using a supported host configuration. Wind River pre-installs the Tcl binaries<br />

and the tclserial libraries in host/hostType/bin for the supported host<br />

configurations. 1<br />

Complete source code is included to facilitate maintenance and extension. Tcl and<br />

the tclserial library are portable and can be compiled on hosts other than the<br />

supported hosts.<br />

The complete source code for Tcl is available in the host/src/tcl directory. To build<br />

and test Tcl for a host not supported by Wind River, run make for the selected<br />

hostType in this directory. Although Tcl should build without errors, the self-test<br />

may report certain errors that do not significantly affect the operation of the <strong>BSP</strong><br />

VTS.<br />

To build the tclserial library, run make for the selected hostType in the<br />

host/src/test/tclserial directory.<br />

1. The tclserial library is a shared or dynamically linked library, whichever is appropriate to<br />

the platform (pkgtclserial.so on a Solaris or SunOS system, pkgtclserial.sl on HP-UX,<br />

pkgtclserial.dll on Windows).<br />

146


7<br />

Validation Testing<br />

NOTE: Wind River made several modifications to the Tcl source files, to allow Tcl<br />

to be ported to various hosts. Wind River makes no guarantee regarding the<br />

validity of the changes. Because Tcl is public domain software, it is not completely<br />

supported by Wind River. The porting of Tcl to various hosts is complete to the<br />

extent that the supplied test scripts have been run and tested on the specified hosts.<br />

Any use of Tcl beyond this purpose has not been tested, and is not supported.<br />

7.3.3 System Configuration<br />

This section describes how to configure the host system, the target hardware,<br />

VxWorks, and the <strong>BSP</strong> VTS itself.<br />

7<br />

Configuring the Host System<br />

In addition to the <strong>BSP</strong> VTS, the host requires the standard Tornado development<br />

environment. For information on configuring the host system, see Tornado User’s<br />

<strong>Guide</strong>: Setup and Startup.<br />

Configuring the Target Hardware<br />

The VxWorks target hardware requires only minimal configuration. The <strong>BSP</strong> VTS<br />

runs in a Tornado environment. For the most part, it uses the target server<br />

connection to communicate with the target. The tests that use console output<br />

require that the serial console be connected to the host. 2 The rlogin, network, and<br />

busTas tests require that the host be connected to two serial consoles.<br />

NOTE: The target server(s) must be up and running before starting the <strong>BSP</strong> VTS.<br />

A few tests, such as error1.tcl and bootline.tcl, must reboot the target. Therefore,<br />

before running <strong>BSP</strong> VTS for the first time, you should boot VxWorks manually to<br />

check that the boot parameters are set correctly. In addition, before starting the <strong>BSP</strong><br />

VTS, make sure the VxWorks target is powered up and responding to the console.<br />

However, the target need not be booted.<br />

2. You must be able to reboot the target and communicate with it over the serial console from<br />

the host. Remember this when you configure and build the boot ROM image for the target.<br />

147


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

The serial.tcl test requires a loopback connection to terminate all free serial ports<br />

(those not used by the VxWorks console or SLIP). To do this, run a jumper from the<br />

transmit/output line to the receive/input line. For ports with hardware<br />

handshaking, you might also need to run a jumper from the RTS to the CTS line.<br />

! WARNING: The scsi.tcl test works by writing and then reading back each location<br />

on the SCSI drive. This erases the drive. Make sure you specify the appropriate<br />

SCSI drive before running this test.<br />

Configuring VxWorks<br />

Running the <strong>BSP</strong> VTS requires a number of supplemental C functions. The source<br />

for these functions is supplied in target/src/test/bspVal/pkLib.c. The <strong>BSP</strong> VTS<br />

looks for the object version of this code in target/config/bspname/pkLib.o. If the<br />

<strong>BSP</strong> VTS does not find this object file, it automatically copies the source to the<br />

target/config/bspname directory and compiles it. If you make any changes to<br />

pkLib.c, you must copy the file to target/config/bspname and recompile it.<br />

The majority of the <strong>BSP</strong> VTS tests can work using the default VxWorks<br />

configuration. The exceptions are listed below:<br />

network<br />

Requires a second target that can run ping and pkUdpEchoTest. When<br />

building the VxWorks image for the reference board (slave target), define the<br />

INCLUDE_PING macro. The VxWorks image running on both the targets<br />

should have INCLUDE_NET_SHOW macro defined.<br />

timestamp<br />

Requires that you defined INCLUDE_TIMESTAMP before you built the<br />

VxWorks image and pkLib.o. If this macro is not defined, the <strong>BSP</strong> VTS skips<br />

the timestamp tests. No fatal error is generated.<br />

rlogin<br />

Requires the use of a target shell. Before you build the VxWorks image for this<br />

test, you must define the following macros:<br />

– INCLUDE_SHELL<br />

– INCLUDE_RLOGIN<br />

– INCLUDE_SHOW_ROUTINES<br />

– INCLUDE_NET_SYM_TBL<br />

– INCLUDE_LOADER<br />

148


7<br />

Validation Testing<br />

scsi<br />

Requires that VxWorks image and pkLib.o must be built with SCSI support<br />

included. For most <strong>BSP</strong>s, you can do this by defining INCLUDE_SCSI.<br />

busTas<br />

Requires that the VxWorks image for both targets include shared memory<br />

components. Define the following macros:<br />

– INCLUDE_SM_NET<br />

– INCLUDE_SM_SEQ_ADDR<br />

– INCLUDE_SM_NET_SHOW<br />

Also, the VxWorks image for one target should define SM_OFF_BOARD as<br />

TRUE, and the other as FALSE.<br />

For more information, see the test descriptions in J. <strong>BSP</strong> Validation Test Suite<br />

Reference Entries.<br />

7<br />

Configuring the <strong>BSP</strong> VTS<br />

The <strong>BSP</strong> VTS is configurable through several parameters implemented as shell<br />

environment variables. All of these parameters are defined in configuration files<br />

(explained below), with one exception. The optional environment variable<br />

TEST_LOG_FILE provides a means for the user to specify where the <strong>BSP</strong> VTS test<br />

logs should be saved. Use the appropriate shell command to set this variable to the<br />

filename (including a full path) to which the test results should be logged. When<br />

this variable is not set, the tests are logged to<br />

target/config/bspname/vtsLogs/bspValidationLog.PID. In either case, the screen<br />

output is copied to the same location as the log file, and is named the same as the<br />

log file with _screenDump appended to the filename.<br />

The configuration parameters that control the behavior of the <strong>BSP</strong> VTS on a single<br />

target reside in the host/resource/test/bspVal/bspName.T1 file. If a test requires two<br />

targets, the host/resource/test/bspVal/bspName.T2 file supplies the parameters for<br />

the second target. 3<br />

These parameters include the path to the VxWorks image to be booted, the<br />

characteristics of the host and target, and the details of how the test should<br />

proceed. Many of the parameters are optional or have default values that are<br />

reasonable in most situations. Some of the parameters are applicable only to<br />

3. When creating a bspname.T1 or bspname.T2 file, you can copy the mv147.T1 and mv147.T2<br />

files and edit the copies as needed.<br />

149


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

certain tests. Target-specific parameters use the prefixes T1_ and T2_ to distinguish<br />

one target from another.<br />

Table 7-1 through Table 7-2 summarize the configuration parameters that can be<br />

set in the bspName.T1 or bspName.T2 files. For parameters whose default values are<br />

listed, the default values take effect even if the parameters are not defined. In<br />

addition, you might need to modify configuration parameters for your serial<br />

connections and timeout values. The rest of this section describes these<br />

parameters.<br />

For additional information on the configuration parameters, read the comments in<br />

the bspName.T1 or bspName.T2 files. For information on which parameters are<br />

relevant to specific tests, see the reference entries provided in J. <strong>BSP</strong> Validation Test<br />

Suite Reference Entries.<br />

Configuring Serial Connections<br />

You might need to modify the following serial-connection parameters to suit your<br />

host:<br />

{T1, T2}_SER_DEVICE<br />

The host name for the serial device connection.<br />

{T1, T2}_SER_BAUD<br />

The baud rate of the serial device connection.<br />

Alternatively, you may specify the serial connection parameters as command line<br />

options in bspVal. See the listing in J. <strong>BSP</strong> Validation Test Suite Reference Entries for<br />

details.<br />

Configuring Timeout Values<br />

The following configuration parameter determines how long the <strong>BSP</strong> tests should<br />

wait for VxWorks to boot:<br />

{T1, T2}_TMO_BOOT<br />

Timeout for booting.<br />

If the VxWorks prompt does not appear within the allotted time after attempting<br />

to boot, a FATAL ERROR is logged. Therefore, you might need to increase this<br />

timeout if, for example, the target boots over Serial Line Internet Protocol (SLIP).<br />

Additionally, there are optional timeout parameters associated with individual<br />

tests. These parameters contain the letters TMO in the macro name. You might<br />

need to increase these timeouts for boards with large devices, slow access times, or<br />

both. These parameters are set in the bspName.T1 and bspName.T2 files located in<br />

host/resource/test/bspVal.<br />

150


7<br />

Validation Testing<br />

Table 7-1<br />

Validation Test Suite Configuration Parameters: Target Boot Parameters<br />

Parameter Default Description<br />

{T1, T2}_BOOT_B N/A inet on backplane (b)<br />

{T1, T2}_BOOT_DEVICE N/A boot device<br />

{T1, T2}_BOOT_E N/A inet on Ethernet (e)<br />

{T1, T2}_BOOT_F N/A flags (f)<br />

{T1, T2}_BOOT_FILE N/A VxWorks image to boot<br />

7<br />

{T1, T2}_BOOT_G N/A gateway inet (g)<br />

{T1, T2}_BOOT_H N/A host inet (h)<br />

{T1, T2}_BOOT_HOST N/A host name<br />

{T1, T2}_BOOT_O N/A other (o)<br />

{T1, T2}_BOOT_PROCNUM N/A processor number<br />

{T1, T2}_BOOT_PW N/A password<br />

{T1, T2}_BOOT_S N/A startup script (s)<br />

{T1, T2}_BOOT_TN N/A target name (tn)<br />

{T1, T2}_BOOT_U N/A user (u)<br />

Table 7-2<br />

Validation Test Suite Configuration Parameters: Target-Specific Parameters<br />

Parameter Default Description<br />

T1_BOOT_LOCAL_BUS_ERR_MSG N/A Local bus error message keyword(s) at boot ROM<br />

level. See bootline.tcl.<br />

T1_BOOT_LOCAL_ERR_ADRS N/A Local memory address that causes bus error at the<br />

boot ROM level. See bootline.tcl.<br />

T1_BOOT_OFFBOARD_BUS_ERR_MSG N/A Off-board bus error message keyword(s) at boot ROM<br />

level. See bootline.tcl.<br />

T1_BOOT_OFFBOARD_ERR_ADRS N/A Off-board address that causes bus error at boot ROM<br />

level. See bootline.tcl.<br />

T1_BUS_MASTER TRUE Indicates which target is the bus master. See<br />

busTas.tcl.<br />

151


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Table 7-2<br />

Validation Test Suite Configuration Parameters: Target-Specific Parameters (Continued)<br />

Parameter Default Description<br />

T1_CATASTROPHIC_ERR_MSG N/A Catastrophic bus error message keyword(s). See<br />

error2.tcl.<br />

T1_COUNT_ADRS not used Master’s address of shared counter. See busTas.tcl.<br />

T1_DIV_ZERO_MSG N/A Divide by zero error message keyword(s). See<br />

error1.tcl.<br />

T1_EXTRA_AUXCLK 25 Another rate to test. See auxClock.tcl.<br />

T1_EXTRA_SYSCLK 20 Another rate to test. See sysClock.tcl.<br />

T1_LOCAL_BUS_ERR_MSG N/A Local bus error message keyword(s). See error1.tcl.<br />

T1_LOCAL_ERR_ADRS N/A Local memory address that causes a bus error. See<br />

error1.tcl.<br />

T1_MODEL N/A Expected result of sysModel( ). See model.tcl.<br />

T1_OFFBOARD_BUS_ERR_MSG N/A Off-board bus error message keyword(s). See<br />

error1.tcl.<br />

T1_OFFBOARD_ERR_ADRS N/A Off-board address that causes a bus error. See<br />

error1.tcl.<br />

T1_SCSI_BUFSIZE 65536 Buffer size (in bytes). See scsi.tcl.<br />

T1_SCSI_ID N/A ID of SCSI device to test. See scsi.tcl.<br />

T1_SCSI_LUN N/A Logical Unit Number of device to test. See scsi.tcl.<br />

T1_SCSI_NBBUF 0 Number of buffers used by SCSI test function. See<br />

scsi.tcl.<br />

T1_SCSI_NBLOOP 0 Number of loops used by SCSI test function. See<br />

scsi.tcl.<br />

T1_SEM_ADRS not used Master’s address of shared semaphore. See<br />

busTas.tcl.<br />

{T1, T2}_SER_BAUD N/A Default baud rate of target console. See bspVal.<br />

{T1, T2}_SER_DEVICE N/A Host name for the serial device connected to the target<br />

console. See bspVal.<br />

{T1, T2}_TAS_DELAY 20 Busy-wait delay used during test-and-set test. See<br />

busTas.tcl.<br />

152


7<br />

Validation Testing<br />

Table 7-2<br />

Validation Test Suite Configuration Parameters: Target-Specific Parameters (Continued)<br />

Parameter Default Description<br />

T1_TMO_SLICES 4 Timestamp test measurements intervals. See<br />

timestamp.tcl.<br />

T1_TMO_TIMESTAMP 300 Duration of timestamp timer test (in seconds). See<br />

timestamp.tcl.<br />

T1_TMO_SCSI 3600 Timeout for testing SCSI (in seconds). See scsi.tcl.<br />

{T1, T2}_TMO_BOOT 60 Timeout for booting VxWorks (in seconds).<br />

7<br />

T2_UDP_TRANS 5000 Number of UDP packets to send. See network.tcl.<br />

7.4 Running the <strong>BSP</strong> VTS<br />

Each test in the <strong>BSP</strong> VTS exercises one or more of the basic <strong>BSP</strong> functions. For the<br />

most part, the source for these tests (implemented as Tcl/WTX scripts) is contained<br />

in the host/src/test/bspVal/src/tests directory. However, if a procedure is shared by<br />

a number of tests, that code is stored in the host/src/test/bspVal/src/lib directory.<br />

These shared procedures handle things such as booting VxWorks, reporting<br />

PASS/FAIL results, and so forth.<br />

For example, <strong>BSP</strong> VTS tests for the system clock and the auxiliary clock are stored<br />

in the files tests/sysClock.tcl and tests/auxClock.tcl. Both of these files call<br />

procedures in lib/clockLib.tcl. In addition, many <strong>BSP</strong> tests use functions within<br />

target/src/test/bspVal/pkLib.c, a library of C functions that execute on the<br />

VxWorks target (although the host retains control of the progression of tests).<br />

These C functions serve as low-level support routines.<br />

7.4.1 Starting the <strong>BSP</strong> VTS<br />

The <strong>BSP</strong> VTS runs from either a Windows or a UNIX host. After starting a bash<br />

shell, running the <strong>BSP</strong> VTS from a Windows host is almost exactly the same as<br />

running it from a UNIX host.<br />

153


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

NOTE: The <strong>BSP</strong> VTS needs exclusive access to the serial device specified as<br />

T1_SER_DEVICE in bspname.T1 (or T2_SER_DEVICE in bspname.T2). Thus, you<br />

must quit all applications or modules that access the specified serial device before<br />

you can run a <strong>BSP</strong> VTS test. In addition, the T1_SER_DEVICE (or T2_SER_DEVICE)<br />

serial device must be the one to which the target console is connected.<br />

Windows Hosts<br />

UNIX Hosts<br />

To run the <strong>BSP</strong> VTS on a Windows host:<br />

1. Change directories to:<br />

windbase\host\x86-win32\bin<br />

windbase is the directory pointed to by the WIND_BASE environment variable.<br />

2. Edit bashrc.bspVal to configure the Tornado environment. The instructions<br />

are in the file.<br />

3. Invoke the bash shell:<br />

bash -rcfile bashrc.bspVal<br />

After the bash shell responds with a prompt (bash$), type in the bspVal<br />

command exactly as you would on a UNIX host (described below). For example:<br />

bash$ bspVal tgtSvr1 -b mv147 -s tgtSvr2 -sb mv147 -all<br />

To start the <strong>BSP</strong> VTS test, run the UNIX shell script host/hostType/bin/bspVal on<br />

the host.<br />

For example:<br />

% bspVal tgtSvr1 -b mv147 -s tgtSvr2 -sb mv147 -all<br />

The host should respond:<br />

<strong>BSP</strong> VALIDATION TEST<br />

-------------------<br />

Target server<br />

: tgtSvr1<br />

<strong>BSP</strong><br />

: mv147<br />

Second target server<br />

: tgtSvr2<br />

Second <strong>BSP</strong><br />

: mv147<br />

Log file<br />

: /folk/lyle/bspValidationLog.671<br />

Model Test :<br />

sysModel() return value : PASS<br />

154


7<br />

Validation Testing<br />

sysProcNumGet Test :<br />

sysProcNumGet() return value : PASS<br />

. . .<br />

The bspVal shell script sets up a default environment and then calls bspVal.tcl, the<br />

Tcl script that runs the individual tests.<br />

The bspVal script runs in batch mode only. Using command-line options, you can<br />

specify the tests you want to run. The example above uses the -all option to run all<br />

the tests in the <strong>BSP</strong> VTS. For more information on running bspVal, see the<br />

reference entry provide in J. <strong>BSP</strong> Validation Test Suite Reference Entries.<br />

NOTE: To abort testing, enter the tty interrupt character (usually CTRL+C)fromthe<br />

host. This stops the test on the host, although the target board might continue to<br />

execute local tasks. In this case, you might need to reboot the target board.<br />

7<br />

7.4.2 Monitoring a <strong>BSP</strong> Test<br />

At startup, the <strong>BSP</strong> VTS prints a header to standard output. This header displays<br />

the names of the target server, the <strong>BSP</strong>, and the log file. At the start of each test, the<br />

<strong>BSP</strong> VTS prints the test name. As subtests within a test are completed, the <strong>BSP</strong> VTS<br />

prints the name of the subtest along with some PASS/FAIL status information. The<br />

PASS/FAIL messages are also written to a log file, which is also used to catch the<br />

output of commands such as ifShow or smNetShow.<br />

Normally, if a test fails, all the other tests still run. However, some errors are fatal.<br />

In this case, the <strong>BSP</strong> VTS aborts and displays a fatal error message, such as:<br />

FATAL ERROR: error in ioctl() command<br />

If you set the environment variable TEST_LOG_FILE to the name of a writable file,<br />

the <strong>BSP</strong> VTS appends its output to this file. To monitor the <strong>BSP</strong> VTS on a second<br />

terminal, run tail -f on the file. For more information on log files, see the bspVal<br />

reference entry provided in J. <strong>BSP</strong> Validation Test Suite Reference Entries.<br />

Example 7-1<br />

Testing the Auxiliary Clock<br />

This example demonstrates the use of the <strong>BSP</strong> VTS to test the auxiliary clock. Note<br />

that the example shown in this section is a test run on the MVME147 <strong>BSP</strong>. This<br />

example is useful for showing how to work with the <strong>BSP</strong> VTS on a single target.<br />

1. Verify that the target board can boot VxWorks. Using the Tornado launcher,<br />

start a target server and open a WindSh. From the WindSh, verify that there is<br />

communication with the target.<br />

155


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

2. Modify the configuration parameters in host/resource/test/bspVal/mv147.T1.<br />

Parameters with the prefix T1_ must be set up appropriately for your<br />

environment and the mv147 <strong>BSP</strong>. (The T2_ parameters in mv147.T2 are for a<br />

second target and are not needed for the auxiliary clock test.) To match the<br />

mv147 <strong>BSP</strong>, set the auxiliary clock speed as follows:<br />

T1_EXTRA_AUXCLK=4321 ;<br />

export T1_EXTRA_AUXCLK<br />

3. Copy pkLib.c from target/src/test/bspVal to the VxWorks target directory<br />

(target/config/mv147 in this example), and use the VxWorks Makefile to make<br />

pkLib.o. The pkLib.o object file is loaded on to the target during the test. Note<br />

that the <strong>BSP</strong> VTS script handles these steps automatically if it does not find a<br />

pkLib.o in the bspname directory.<br />

4. Check that the mv147 target is connected to the appropriate serial port of the<br />

host, connected to the network, and turned on.<br />

5. Execute bspVal on the host, specifying the auxClock test on the command<br />

line. The running time of this test is approximately seven minutes.<br />

% bspVal tgtSvr -b mv147 auxClock<br />

The screen display is:<br />

<strong>BSP</strong> VALIDATION TEST<br />

-------------------<br />

Target server<br />

<strong>BSP</strong><br />

Log file<br />

: tgtSvr<br />

: mv1604<br />

: /tmp/bspValidationLog.19938<br />

Auxiliary Clock Test :<br />

auxClk at 4321 hertz (rate = 4327 error = 0%)<br />

auxClk at 40 hertz (rate = 40 error = 0%)<br />

auxClk at 5000 hertz (rate = 5001 error = 0%)<br />

auxClk at 60 hertz (rate = 60 error = 0%)<br />

sysAuxClkDisable() disables auxClk<br />

sysAuxClkRateSet() parameter checking<br />

sysAuxClkRateGet() return value<br />

: PASS<br />

: PASS<br />

: PASS<br />

: PASS<br />

: PASS<br />

: PASS<br />

: PASS<br />

Tests RUN 7<br />

Tests PASSED 7<br />

Tests FAILED 0<br />

Tests SKIPPED 0<br />

156


7<br />

Validation Testing<br />

The log file contents are:<br />

<strong>BSP</strong> Validation Test Suite version 2.0<br />

-------------------------------------<br />

<strong>BSP</strong> Validation Test Started : Wed Aug 27 08:14:25 PDT 1997<br />

Test started : Wed Aug 27 08:14:26 PDT 1997<br />

Auxiliary Clock Test :<br />

optional extra auxClk rate selected is 4321<br />

dafault auxClk rate is 60<br />

minimum auxClk rate is 40<br />

maximum auxClk rate is 5000<br />

## Starting auxClk test at 4321 hertz rate ##<br />

1 second through auxClk test: ticks1=4510<br />

11 seconds through auxClk test: ticks2=47804<br />

141 seconds through auxClk test: ticks3=610388<br />

corrected value for 120 ticks is 519290<br />

ticks divided by rate = 120<br />

auxClk at 4321 hertz (rate = 4327 error = 0%)<br />

## Starting auxClk test at 40 hertz rate ##<br />

1 second through auxClk test: ticks1=120<br />

11 seconds through auxClk test: ticks2=520<br />

141 seconds through auxClk test: ticks3=5722<br />

corrected value for 120 ticks is 4802<br />

ticks divided by rate = 120<br />

auxClk at 40 hertz (rate = 40 error = 0%)<br />

## Starting auxClk test at 5000 hertz rate ##<br />

1 second through auxClk test: ticks1=4995<br />

11 seconds through auxClk test: ticks2=55152<br />

141 seconds through auxClk test: ticks3=705447<br />

corrected value for 120 ticks is 600138<br />

ticks divided by rate = 120<br />

auxClk at 5000 hertz (rate = 5001 error = 0%)<br />

## Starting auxClk test at 60 hertz rate ##<br />

1 second through auxClk test: ticks1=150<br />

11 seconds through auxClk test: ticks2=750<br />

141 seconds through auxClk test: ticks3=8554<br />

corrected value for 120 ticks is 7204<br />

ticks divided by rate = 120<br />

auxClk at 60 hertz (rate = 60 error = 0%)<br />

sysAuxClkDisable() disables auxClk<br />

sysAuxClkRateSet() parameter checking<br />

sysAuxClkRateGet() return value<br />

End of test : Wed Aug 27 08:23:54 PDT 1997<br />

: PASS<br />

: PASS<br />

: PASS<br />

: PASS<br />

: PASS<br />

: PASS<br />

: PASS<br />

7<br />

157


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Final Results are :<br />

Tests RUN 7<br />

Tests PASSED 7<br />

Tests FAILED 0<br />

Tests SKIPPED 0<br />

End of <strong>BSP</strong> Validation Test : Wed Aug 27 08:23:54 PDT 1997<br />

6. Study the results. In the output shown above, the <strong>BSP</strong> passed all seven of the<br />

sub-tests in the auxiliary clock test. Thus, it passed the test as a whole. For<br />

more information on validating the results of the <strong>BSP</strong> VTS, see K. <strong>BSP</strong><br />

Validation Checklists.<br />

158


8<br />

Writing Portable C Code<br />

This chapter describes how to write compiler-independent portable C code. The<br />

goal is to write code that does not require changes in order to work correctly with<br />

different compilers.<br />

Wind River has conducted an analysis of its own VxWorks code base, with an eye<br />

to compiler independence issues. This chapter is based on the findings of that<br />

analysis.<br />

The code changes proposed in this chapter do not cover the native host tools,<br />

including VxSim and any other tools that are compiled both by native compilers<br />

and by cross-compilation.<br />

This chapter also does not cover C++ portability; there are fundamental differences<br />

in the GNU and Diab C++ implementations. Future editions of this document will<br />

address the portability of C++ code.<br />

Background<br />

While the ANSI C and compiler specifications are detailed, they still allow each<br />

compiler to implement the standard differently. The result is that much source<br />

code is not truly portable among compiler systems. In order for the compiler to<br />

generate code in a specific manner, engineers must insert special<br />

non-ANSI-defined instructions into the code.<br />

The information in this chapter is part of Wind River’s effort to support multiple<br />

compiler systems without requiring major source changes, and to add support for<br />

new compiler systems in the future without creating compatibility conflicts.<br />

159


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Analysis of Wind River’s existing code base reveals three main areas where<br />

non-ANSI compiler features are used to generate run-time code:<br />

■<br />

■<br />

■<br />

packed structure definitions<br />

in-line assembly code<br />

alignment of data elements<br />

NOTE: This chapter is limited in scope to insuring that code is portable specifically<br />

between the GNU and Diab compilers.<br />

NOTE: The scope of this chapter is further limited to specify GCC version 2.96 and<br />

Diab version 5.0 as the baseline compilers. Earlier versions are not truly compatible<br />

with each other and may not have all the necessary support to implement the<br />

conventions introduced here.<br />

8.1 Portable C Code<br />

8.1.1 Data Structures<br />

Some structure definitions are bound by external restrictions. It is common<br />

practice to use a structure definition to document the register layout of hardware<br />

devices. Using a structure to define the layout of data packet contents received<br />

from another system is also common. This can create problems because the ANSI<br />

specification allows compilers to insert padding elements within structure<br />

definitions in order to optimize data element accesses. In these situations, doing so<br />

would make the structure declaration incompatible with the expectations and<br />

restrictions of the outside world. The compiler offsets from the start of the structure<br />

to the start of the data element would not match what is expected. A method is<br />

required for identifying certain structures as requiring special compiler treatment,<br />

while allowing other structures to be optimized for efficiency.<br />

The common term for a structure definition without any padding is packed. Each of<br />

the major compilers has a means to specify packing for a structure, but there is no<br />

single recognized standard. GNU and Diab use an attribute statement as part of<br />

the declaration. Microsoft compilers use #pragma statements.<br />

To specify packing in a compiler-independent manner a macro has been created for<br />

use when defining the structure. The _WRS_PACK_ALIGN(x) macro is used as an<br />

160


8<br />

Writing Portable C Code<br />

attribute declaration. It is placed after the closing curly brace, but before any<br />

instance declarations or initializers. By including the vxWorks.h header file in your<br />

compilation, a toolchain specific header file is included to define this macro<br />

appropriately for the compiler tool being used.<br />

For example:<br />

struct aPackedStruct {<br />

UINT32 int1;<br />

INT16 aShort;<br />

INT8 aByte;<br />

} _WRS_PACK_ALIGN(1);<br />

struct aPackedStruct {<br />

UINT32 int1;<br />

INT16 aShort;<br />

INT8 aByte;<br />

} _WRS_PACK_ALIGN(1) anInstance = {0x1, 2,3};<br />

8<br />

typedef struct {<br />

UINT8 aByte;<br />

UINT16 aShort;<br />

UINT32 aLong;<br />

} _WRS_PACK_ALIGN(1) myPackedStruct;<br />

Specify Field Widths<br />

Always use specific field widths within a packed structure declaration. The basic<br />

data type int does not have a specific size and should be avoided. The same rule<br />

applies for long, unsigned, and char. The vxWorks.h header file defines basic data<br />

types with explicit sizes. Use these data types in any packed structure (INT8,<br />

INT16, INT32, UINT8, and so on). In general, think ahead to architectures with<br />

more than a 32-bit native integer.<br />

Avoid Bit Fields<br />

Do not include bit field definitions within a packed structure. Compilers are<br />

permitted to start labeling bits with either the least significant bit or the most<br />

significant bit. This issue can be dealt with easily by using macro constants to<br />

define the specific bit pattern within the data field.<br />

161


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

For example:<br />

struct aPackedStruct {<br />

UINT32 int1;<br />

INT16 aShort;<br />

INT8 aByte;<br />

} _WRS_PACK_ALIGN(1) anInstance={0x1,2,3};<br />

/* Bits in the aByte field */<br />

#define ABYTE_ERROR<br />

#define ABYTE_OFLOW<br />

#define ABYTE_UFLOW<br />

#define ABYTE_DMA<br />

#define ABYTE_POLL<br />

0x01<br />

0x02<br />

0x04<br />

0x08<br />

0x10<br />

8.1.2 In-Line Assembly<br />

In-line assembly is a more difficult issue because it involves both the compiler and<br />

the assembler. In Wind River’s case, the code base fortunately uses MIT assembler<br />

syntax throughout, which many assemblers are compatible with. In-line assembly<br />

in portable C code is by its nature not portable across architectures. Thus, the real<br />

question for in-line assembly is compiler portability.<br />

The current compilers differ significantly about how to include assembly<br />

instructions without interfering with, or suffering interference from, the<br />

compiler’s optimization efforts. In the absence of an ideal solution, in-line<br />

assembly should only be used if it does not interact with the surrounding C code.<br />

This means that acceptable in-line assembly does not interact with C variables or<br />

return values. Code that cannot meet this limitation should be written entirely in<br />

assembly language.<br />

The vxWorks.h header file defines a _WRS_ASM macro to be used to insert in-line<br />

assembly instructions in a C function.<br />

For example (PowerPC):<br />

VOID foo (void)<br />

{<br />

routineA (args);<br />

_WRS_ASM(“ eieio; isync;”);<br />

routineB (args);<br />

}<br />

Assume that the compiler is not free to optimize or reorder in-line assembly code<br />

with respect to surrounding C code.<br />

162


8<br />

Writing Portable C Code<br />

8.1.3 Static Data Alignment<br />

Sometimes it is necessary to align a global static data element or structure on a<br />

specific boundary type. This typically happens with CPU-specific data structures<br />

that need cache boundary alignment.<br />

To handle this situation, another toolchain-specific macro has been introduced.<br />

The macro _WRS_DATA_ALIGN_BYTES(bytes) aligns the following data element<br />

with the byte alignment specified.<br />

For example:<br />

_WRS_DATA_ALIGN_BYTES(16) int myData = 0xFE00235F;<br />

This alignment macro should only be used with global data that has been<br />

initialized. Uninitialized data may not be placed in the data section, and the macro<br />

may not have the desired effect. Uninitialized data can be handled at runtime<br />

using memalign( ) or other suitable functions.<br />

8<br />

8.1.4 Runtime Alignment Checking<br />

Checking the Alignment of a Data Item<br />

You may need to know the alignment of a particular data item at runtime. Most<br />

compilers provide an extension for accessing this information, but there is no<br />

recognized standard for it. In the case of Wind River source code, the macro<br />

_WRS_ALIGNOF(x) is used to return the alignment of an item in byte units.<br />

if (WRS_ALIGNOF(itemA) < 4)<br />

{<br />

printf (“Error: itemA is not longword aligned”);<br />

}<br />

Verifying Pointer Alignment<br />

Pointers can be deliberately cast to be a pointer to a different type of object with<br />

different alignment requirements. Strict type checking at compile time is beneficial,<br />

but there are situations in which this checking must be performed at runtime. For<br />

this purpose, the macro _WRS_ALIGN_CHECK(ptr, type) is provided. This macro<br />

evaluates to either TRUE or FALSE. TRUE is returned if the pointer ptr is aligned<br />

163


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

sufficiently for an item of type type. The test is normally done by examining<br />

low-order bits of the pointer’s value.<br />

void * pVoid;<br />

if (!WRS_ALIGN_CHECK(pVoid, long))<br />

{<br />

printf (“Error: pVoid is not longword aligned”);<br />

}<br />

Unaligned Accesses and Copying<br />

You may need to access data that may not be correctly aligned at runtime. It is<br />

recommended in this situation that you copy the data to a structure or other area<br />

that is properly aligned. After the data has been copied, it can be accessed without<br />

the possibility of causing unaligned access exceptions. The macro provided for this<br />

purpose is _WRS_UNALIGNED_COPY(pSrc, pDst, size). While the standard<br />

VxWorks bcopy( ) function could be used for this purpose, most compilers can do<br />

short copies more efficiently on their own. Using the macro is therefore desirable<br />

for performance reasons.<br />

The following example shows both _WRS_ALIGN_CHECK and<br />

_WRS_UNALIGNED_COPY used together to check an unknown pointer. If it is<br />

sufficiently aligned, the pointer can be cast to some other type and the item can be<br />

accessed directly. If the pointer is not aligned, the unaligned macro is used to copy<br />

the data element to a usable variable location.<br />

struct structA {<br />

long item1;<br />

long item2;<br />

char item3;<br />

} itemA;<br />

void * pVoid;<br />

long aLong;<br />

if (WRS_ALIGN_CHECK(pVoid, (struct structA)))<br />

{<br />

/* Alignment is okay, reference directly */<br />

aLongItem = ((struct structA *)pVoid)->item2;<br />

}<br />

else<br />

{<br />

/* alignment is not okay, use unaligned copy */<br />

_WRS_UNALIGNED_COPY(pVoid,&aLong,sizeof(aLong));<br />

}<br />

164


8<br />

Writing Portable C Code<br />

8.1.5 Other Issues<br />

Follow Strict ANSI Compilation<br />

Compilation units should be compiled with strict ANSI protocols in effect. This<br />

requires detailed prototype declarations. For the GNU compiler system, the<br />

compiler flags should include the following:<br />

-Wall -W -Wmissing-declarations -Wstrict-prototypes -Wmissing-prototypes<br />

Remove Compiler Warnings<br />

8<br />

Portable code must be as free of warnings as possible. Apply the strictest possible<br />

code checking and fix all reported warning situations. Compilers identify<br />

non-portable code issues well when doing error checking.<br />

Avoid Use of Casts<br />

Each and every cast represents a potential error. It is a common practice to use a<br />

cast to fix warnings reported by the compiler. However, each instance must be<br />

examined carefully to insure that a cast is the appropriate action. Often a warning<br />

indicates an actual error in argument passing that must be corrected. Using a cast<br />

overrides the compiler’s ability to detect an actual error in data usage that may<br />

prove to be significant.<br />

Avoid inline Keyword<br />

The C inline keyword is to be avoided until the GNU and Diab compilers can<br />

implement it in a consistent manner. The current ANSI Specification, C99, does call<br />

for an inline keyword. However, at this time, neither compiler fully supports this<br />

specification. Although each accepts the inline keyword, there are subtle but<br />

significant differences in the implementation. An update to this document will be<br />

issued when support for the inline keyword is available.<br />

165


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Avoid alloca( ) Function<br />

Many compilers support the alloca( ) function as an extension to the C language.<br />

This normally allocates storage from the stack, as any declared variable would.<br />

Since the storage area is on the stack, this area does not need to be freed, as the<br />

stack is restored upon exiting the function.<br />

While alloca( ) is widely used in code from other OS programming models, it does<br />

not suit VxWorks very well. While other OSs may support automatic stack<br />

expansion and stack checking, VxWorks does not. In embedded programming,<br />

predictable timing and stack usage can be very important. Code for VxWorks<br />

should definitely avoid the use of the alloca( ) function. Allocate the storage<br />

directly on the stack, or use malloc( ) and free( ) if necessary.<br />

Take Care with void Pointer Arithmetic<br />

It is common to use pointer arithmetic on void pointer data types. Because the size<br />

of a void item should be unspecified, the ANSI standard does not allow this<br />

practice. The GNU compiler, however, did allow it and assumed the data size to be<br />

one byte, the same as a char data type.<br />

For example, the following code fragment is faulty:<br />

{<br />

void * pVoid;<br />

pVoid += 1; /* WRONG */<br />

pVoid++; /* WRONG */<br />

pVoid = pVoid + sizeof(char); /* WRONG */<br />

}<br />

The example above is faulty because ANSI pointer arithmetic is based on the size<br />

of the object pointed to. In the case of a pointer to a void, the size is undefined. For<br />

the first faulty statement in the example above, the only correct implementation is<br />

as follows:<br />

{<br />

void * pVoid;<br />

pVoid = (char *)pVoid + 1; /* RIGHT */<br />

(char *)pVoid++; /* WRONG */<br />

(char *)pVoid += 1 /* WRONG */<br />

}<br />

166


8<br />

Writing Portable C Code<br />

The last two statements in the example above are still faulty because ANSI does<br />

not allow casts to be used for an lval type expression.<br />

Use volatile and const Attributes<br />

Proper use of the volatile and const attributes can result in better error detection<br />

by the compiler. The volatile keyword is essential for all data elements whose<br />

value can be changed by an agent outside of the current thread of execution. (For<br />

example, a device performing DMA, another task sharing the data, or an interrupt<br />

routine sharing the data.) Failure to tag a shared data element with volatile can<br />

generate intermittent system faults that are difficult to track.<br />

VxWorks 5.4 and earlier always used the –fvolatile compiler option to force all<br />

pointers to be treated as pointing to a volatile data item. Portable code should not<br />

rely on this mechanism in the future. The compiler can optimize much more<br />

effectively when the correct attributes of all data elements are known.<br />

The const attribute should be used to indicate to the compiler that an argument is<br />

strictly an input argument, and that its value is unchanged by this routine. This<br />

helps the compiler to perform error detection and allows it to better optimize the<br />

code.<br />

8<br />

Misuse of the register Attribute<br />

The misuse of the register (that is, FAST) attribute is quite common. In Wind<br />

River’s case, analysis of the code base revealed that a number of subroutines have<br />

been coded where the input arguments were all labeled with the FAST attribute, as<br />

well as a number of local routine values. The current compilers are able to do very<br />

good optimization of routines without requiring any use of the FAST attribute in<br />

the code base. Overuse of the attribute can actually prevent the compiler from<br />

performing effective optimization of the code. For the large majority of code now,<br />

the FAST attribute is simply unnecessary. It should only be used sparingly in<br />

situations where there is a large number of local variables, only a few of which are<br />

referenced often.<br />

Avoid vector Name<br />

A Motorola extension to the ANSI C specification makes the word vector a<br />

keyword. Runtime code should not use vector as a variable name. This change in<br />

167


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

the compilers supports the Altivec processor and the built-in DSP functions it<br />

provides. Your code should avoid the use of vector as a variable name.<br />

Statement Labels<br />

The ANSI specification requires labels to be associated with statements. It is not<br />

uncommon to place labels at the end of a code block without any associated<br />

statement at all. With strict ANSI checking this is an error. In the code below the<br />

default label is not connected to a statement. To correct this problem, either remove<br />

the label or add a null statement to give the label a proper point of connection.<br />

switch (xxx)<br />

{<br />

case X: statement;<br />

case Y: statement;<br />

default: /* WRONG – no statement here */<br />

}<br />

Summary of Compiler Macros<br />

For each supported C toolchain, the macros described in this section are defined<br />

when vxWorks.h is included in your compilation.<br />

_WRS_PACK_ALIGN(n)<br />

This macro is used to specify the packing and alignment attributes for a structure.<br />

Packing insures that no padding is inserted and that the minimum field alignment<br />

within the structure is one byte. The user can specify the assumed alignment for<br />

the structure as a whole with the argument x, in bytes. The value x is expected to<br />

be a power of two value (1,2,4,8,…). The size of the structure is then a multiple of<br />

this value. If the overall structure alignment is 1, the compiler assumes that this<br />

structure, and any pointer to this structure, can exist on any possible alignment.<br />

For an architecture that cannot handle misaligned data transfers, the compiler is<br />

forced to generate code to access each byte separately and then to assemble the<br />

data into larger word and longword units.<br />

The macro is placed after the closing brace of the structure field description and<br />

before any variable item declarations, or typedef name declarations.<br />

168


8<br />

Writing Portable C Code<br />

Always specify fields with explicit widths, such as UINT8, UINT16, INT32, and so<br />

on. Do not use bitfields in a packed structure.<br />

_WRS_ASM(“X”)<br />

This macro is used to insert assembly code within a C function declaration. The<br />

inserted code must not interact with C variables or try to alter the return value of<br />

the function. The code uses the MIT assembly-language mnemonics and syntax.<br />

It is assumed that the compiler does not optimize or reorder any specified in-line<br />

assembly code. The insertion of a null in-line assembly statement can be used to<br />

prevent the compiler from reordering C code before the statement with C code that<br />

follows the statement.<br />

8<br />

_WRS_DATA_ALIGN_BYTES(n)<br />

This macro is used in prefix notation to declare an initialized C data element with<br />

a special alignment. The argument n is the alignment in byte units (1, 2, 4, 8, 16, and<br />

so on). This is normally used only with initialized global data elements. Use this<br />

macro with caution: overuse of this macro can result in poor memory utilization.<br />

If large numbers of variables require special alignment, it may be best to declare<br />

them in separate sections directly in assembler. The linker loader could then fit<br />

them together in an optimal fashion.<br />

_WRS_GNU_VAR_MACROS<br />

The GNU compiler system created a means to pass a variable number of<br />

arguments to pre-processor macro functions, and there are a few special instances<br />

in the VxWorks code base that use the GNU-defined syntax. Since then, the ANSI<br />

standards committee has defined an ANSI standard that is different from this<br />

practice. Currently, the GNU compiler 2.96 does not yet support the ANSI<br />

standard, and the Diab compiler supports only the ANSI standard.<br />

Code that does use variadic macros should define them both for GNU and for the<br />

ANSI standard (Diab). Rather than select upon the toolchain or compiler name, a<br />

new macro feature name, _WRS_GNU_VAR_MACROS, has been created. The GNU<br />

toolchain defines this macro; the Diab toolchain does not.<br />

If you want to port your code to another toolchain, you must choose between<br />

supporting the GNU-style syntax or the ANSI standard syntax. For example, the<br />

following code fragment demonstrates the use of an #ifdef statement to make this<br />

choice between GNU and ANSI:<br />

169


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

#ifdef _WRS_GNU_VAR_MACROS /* GNU Syntax */<br />

#define MY_MACRO(x, y, args...) printf (x, y, args)<br />

#else /* ANSI Syntax */<br />

#define MY_MACRO(x, y, ...) printf (x, y, __VA_ARG__)<br />

#endif<br />

In the future, when the GNU toolchain does support the ANSI standard, the<br />

#ifdefs based on this macro can be removed from the code base.<br />

_WRS_ALIGNOF(item)<br />

This macro returns the alignment of the specified item, or item type, in byte units.<br />

Most structures have alignment values of 4, which is the normal alignment of a<br />

longword data value. Data items or types with greater alignment values return an<br />

appropriate alignment value, which is expected to be a power of two (1, 2, 4, 8, 16,<br />

and so on).<br />

_WRS_ALIGN_CHECK(ptr, type)<br />

This macro returns a boolean value, either TRUE or FALSE. A return of TRUE<br />

indicates that the pointer value is sufficiently aligned to be a valid pointer to the<br />

data item or type. The expected implementation is to examine the low-order bits<br />

of the pointer value to see whether it is a proper modulo of the alignment for the<br />

given type.<br />

_WRS_UNALIGNED_COPY(pSrc, pDst, size)<br />

This macro is a compiler-optimized version of the standard Wind River bcopy<br />

operation. It moves a data block from the source location to the destination<br />

location. This macro allows the compiler to optimize the copy operation based on<br />

the data types of the pointers and the size of the block. This macro is designed to<br />

be used in high-performance situations; the size of the block is expected to be<br />

small. Misuse of the macro for other situations should be avoided.<br />

170


8<br />

Writing Portable C Code<br />

8.2 Tool Implementation<br />

This section discusses how the current VxWorks runtime code is organized to<br />

facilitate the addition and maintenance of new compiler tools.<br />

8.2.1 New Tool Macros File<br />

The definition of the new tool-based macros must be placed into the compilation<br />

units. This has been achieved by modifying the target/h/vxWorks.h file to include<br />

a new toolMacros.h file. This file defines the new macros, and any other tool-based<br />

options, that apply globally to run-time compilations. All run-time compiled files<br />

must include vxWorks.h so that the new tool macro definitions are also included.<br />

8<br />

8.2.2 New Tool Directories<br />

Each toolchain provides the toolMacros.h file in a separate directory. Changes<br />

have been made in vxWorks.h to find the toolMacros.h file based on the<br />

preprocessor variable TOOL_FAMILY. For backward compatibility, if<br />

TOOL_FAMILY is not explicitly defined, its value is generated from the value of the<br />

build macro TOOL.<br />

This new toolchain-specific directory structure is intended to make it easy for all<br />

tool-related files to be located in a common directory separate from other tool<br />

system files. It also makes it unnecessary to modify any common files in the system<br />

just to add a new tool system. Add the new tool directory target/h/tool/newTool and<br />

then perform a system build; this triggers the system to reanalyze all toolchains<br />

and rebuild the toolchain database.<br />

8.2.3 <strong>BSP</strong> Makefile Changes<br />

All VxWorks 5.5 (Tornado 2.2) <strong>BSP</strong> makefiles require modification to replace the<br />

old make tool include file path with the new tool-based path. For this release, all<br />

changes are made to the platform release files.<br />

Comment out the following lines from each <strong>BSP</strong> makefile by inserting a # in front<br />

of them. The remaining include lines pull in all the needed make files.<br />

#include $(TGT_DIR)/h/make/make.$(CPU)$(TOOL)<br />

#include $(TGT_DIR)/h/make/defs.$(WIND_HOST_TYPE)<br />

#include $(TGT_DIR)/h/make/rules.$(WIND_HOST_TYPE)<br />

171


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

8.2.4 Macro Definitions for GNU and Diab<br />

The current implementation of the required macros for the GNU toolchain is as<br />

follows (this assumes GCC 2.96):<br />

#define _WRS_PACK_ALIGN(x) __attribute__((packed,aligned(x)))<br />

#define _WRS_ASM(x)<br />

__asm__ volatile (x)<br />

#define _WRS_DATA_ALIGN_BYTES(x) __attribute__((aligned(x)))<br />

#define _WRS_GNU_VAR_MACROS<br />

#define _WRS_ALIGNOF(x)<br />

__alignof__(x)<br />

#define _WRS_ALIGN_CHECK(ptr,type) \<br />

(((int)(ptr) & (WRS_ALIGNOF(type) – 1)) == 0 ? TRUE : FALSE)<br />

#define WRS_UNALIGNED_COPY(pSrc,pDst,size) \<br />

(__builtin_memcpy((pDst, (void *)(pSrc), size))<br />

The current implementation of the required macros for the Diab toolchain is as<br />

follows (this assumes Diab 5.0):<br />

#define _WRS_PACK_ALIGN(x) __attribute__((packed,aligned(x)))<br />

#define _WRS_ASM(x)<br />

__asm volatile (x)<br />

#define _WRS_DATA_ALIGN_BYTES(x) __attribute__((aligned(x)))<br />

#undef _WRS_GNU_VAR_MACROS<br />

#define _WRS_ALIGNOF(x)<br />

sizeof(x,1)<br />

#define _WRS_ALIGN_CHECK(ptr,type) \<br />

(((int)(ptr) & (WRS_ALIGNOF(type) – 1)) == 0 ? TRUE : FALSE)<br />

#define _WRS_UNALIGNED_COPY(pSrc,pDst,size) \<br />

(memcpy((pDst), (pSrc), size))<br />

172


9<br />

Documentation <strong>Guide</strong>lines<br />

9.1 Introduction<br />

Reference documentation for Wind River board support packages (<strong>BSP</strong>s) consists<br />

of UNIX-style reference entries (formerly known as man pages) for the module<br />

sysLib.c and the file target.nr. Documentation in HTML format is generated from<br />

these files using the Wind River tool refgen. During a <strong>BSP</strong> build, make runs refgen<br />

and places the HTML output in the Tornado/VxWorks docs directory. The<br />

resulting reference pages can be displayed online with an HTML browser.<br />

This chapter covers Wind River conventions for style and format, and the<br />

procedures for generating <strong>BSP</strong> documentation. The <strong>BSP</strong> templates supplied with<br />

the VxWorks <strong>BSP</strong> Developer’s Kit provide examples of the writing style, text<br />

format, module layout, and text commands discussed throughout this chapter.<br />

Modules formatted with the conventions discussed here will be compatible with<br />

all Wind River documentation macros and formatting scripts, should your <strong>BSP</strong> be<br />

turned over to Wind River for distribution.<br />

9.2 Written Style<br />

This section describes a few of the general requirements for written style in Wind<br />

River technical publications. The items below are only a portion of the standards<br />

described in Wind River’s style guide, but are chosen for inclusion here based on<br />

their frequent misuse.<br />

173


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Specific requirements for <strong>BSP</strong>s are in 9.4 Subsections, p.183.<br />

Sentences<br />

■<br />

■<br />

■<br />

■<br />

■<br />

Keep sentences brief and to the point, presenting information in a simple,<br />

straightforward manner.<br />

Always use complete sentences.<br />

Keep sentences in present tense. Do not use future or past tense unless they<br />

are necessary to convey the idea.<br />

Do not use abbreviated English—do not exclude articles (the, a, an) for brevity.<br />

Separate sentences by two spaces.<br />

Punctuation<br />

■<br />

■<br />

■<br />

Always use a colon after the phrase or sentence introducing an example,<br />

display, itemized list, or table.<br />

A comma should always precede the conjunction and, or, or nor when it<br />

separates the last of a series of three or more words or phrases. This comma<br />

is not optional. For example:<br />

apples, oranges, and bananas<br />

Avoid the use of quotation marks. If they are necessary, form quotations using<br />

the straight double-quote ( " ) only. Use single quotes only as described in<br />

Special Elements, p.180. Do not create quotations with the old troff convention<br />

of double back-quotes and apostrophes.<br />

Word Usage<br />

■<br />

■<br />

■<br />

■<br />

Do not use capital letters to convey emphasis; use italics. For information on<br />

how to apply font changes, see Table 9-3. In general, avoid applying italics for<br />

emphasis—the best way to convey emphasis is a well cast sentence.<br />

Do not use the word so to mean thus or therefore. However, the construction so<br />

that is acceptable.<br />

Do not use contractions (don’t, doesn’t, can’t, and so on).<br />

Do not exclude articles (the, a, an) for brevity.<br />

174


9<br />

Documentation <strong>Guide</strong>lines<br />

Spelling<br />

Table 9-1 defines the Wind River standard for terms that are spelled inconsistently,<br />

particularly in the computer industry. This table also includes a few words or<br />

abbreviations which are commonly misspelled, and words whose spelling is<br />

frequently misunderstood because it may depend on context.<br />

Table 9-1<br />

Spelling Conventions<br />

Use...<br />

and so forth, among others<br />

back end<br />

boot line<br />

boot ROM<br />

bps<br />

caching<br />

cacheable<br />

callback<br />

cannot<br />

CD-ROM<br />

coprocessor<br />

countdown<br />

cross-compiler<br />

cross-development<br />

cross-reference<br />

data type<br />

dialog<br />

e-mail<br />

Ethernet<br />

Excelan<br />

Not...<br />

etc.<br />

backend<br />

bootline, boot-line<br />

bootrom<br />

BPS, baud<br />

cacheing<br />

cachable<br />

call-back<br />

can not<br />

CDROM, cdrom<br />

co-processor<br />

count-down<br />

cross compiler<br />

cross development<br />

cross reference<br />

datatype<br />

dialogue<br />

email, E-mail, Email<br />

ethernet<br />

Excellan<br />

9<br />

175


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Table 9-1<br />

Spelling Conventions (Continued)<br />

Use...<br />

fax<br />

fd<br />

filename<br />

for example<br />

FTP<br />

HP-UX<br />

I/O<br />

ID<br />

Internet<br />

intertask<br />

inline<br />

ioctl<br />

Iostreams (no bold)<br />

log in (v.)<br />

login (n., adj.)<br />

lowercase<br />

MC680x0<br />

Not...<br />

FAX<br />

FD<br />

file name<br />

e.g.<br />

ftp<br />

HP/UX, HPUX<br />

i/o, IO, io<br />

id<br />

internet<br />

inter-task<br />

in-line<br />

IOCTL, IOctl, IOCtl<br />

IOStreams, iostreams, IoStreams<br />

login, log-in<br />

log in, log-in<br />

lower-case<br />

M68000, M68k<br />

MC68020... M68020, 68020...<br />

MS-DOS<br />

motherboard<br />

multiprocessor<br />

multitasking<br />

multi-user<br />

nonvolatile<br />

MSDOS, MS DOS<br />

mother-board, mother board<br />

multi-processor<br />

multi-tasking<br />

multiuser<br />

non-volatile<br />

176


9<br />

Documentation <strong>Guide</strong>lines<br />

Table 9-1<br />

Spelling Conventions (Continued)<br />

Use...<br />

nonzero<br />

on-board<br />

online<br />

PAL<br />

pop-up<br />

preemptive<br />

printout<br />

real-time, Real-time<br />

reentrant<br />

RSH<br />

run-time, Run-time<br />

SBus<br />

SCSI<br />

set up (v.)<br />

setup (n., adj.)<br />

shell script<br />

single-stepping<br />

standalone<br />

start up (v.)<br />

startup (n., adj.)<br />

stdio<br />

sub-class<br />

subdirectory<br />

SunOS<br />

Not...<br />

non-zero<br />

on board, onboard<br />

on-line<br />

pal<br />

popup<br />

pre-emptive<br />

print-out<br />

realtime, Real-Time<br />

re-entrant<br />

rsh<br />

runtime, Run-Time<br />

S-Bus, Sbus<br />

Scsi, scsi<br />

set-up<br />

set-up<br />

shellscript<br />

single stepping<br />

stand-alone<br />

startup, start-up<br />

start-up<br />

STDIO<br />

subclass<br />

sub-directory<br />

SUN OS<br />

9<br />

177


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Table 9-1<br />

Spelling Conventions (Continued)<br />

Use...<br />

super-class<br />

task ID<br />

Tcl<br />

TFTP<br />

that is<br />

timeout<br />

timestamp<br />

tty<br />

UNIX<br />

uppercase<br />

Users’ Group<br />

VxWorks<br />

workaround (n.)<br />

Not...<br />

superclass<br />

task id<br />

TCL, tcl<br />

tftp<br />

i.e.<br />

time-out<br />

time stamp, time-stamp<br />

TTY<br />

Unix<br />

upper-case, upper case<br />

User’s Group Users Group<br />

VxWORKS, VXWORKS<br />

work-around<br />

Acronyms<br />

Define acronyms at first usage, except for widely recognized acronyms (see<br />

Table 9-2). At first usage, give the full definition, followed by the acronym in<br />

parentheses, for example:<br />

Internet Control Message Protocol (ICMP)<br />

Do not use an apostrophe ( ’ ) to form the plural of an acronym. The plural of CPU<br />

is CPUs.<br />

Table 9-2<br />

Common Acronyms<br />

Acronym<br />

ASCII<br />

ANSI<br />

Definition<br />

American Standard Code for Information Interchange<br />

American National Standards Institute<br />

178


9<br />

Documentation <strong>Guide</strong>lines<br />

Table 9-2<br />

Common Acronyms<br />

Acronym<br />

CPU<br />

EOF<br />

fd<br />

FTP<br />

IP<br />

NFS<br />

PPP<br />

pty<br />

RAM<br />

ROM<br />

RSH<br />

TCP<br />

TFTP<br />

tty<br />

Definition<br />

Central Processing Unit<br />

End-Of-File<br />

file descriptor<br />

File Transfer Protocol<br />

Internel Protocol<br />

Network File System<br />

Point-to-Point Protocol<br />

pseudo terminal device<br />

Random Access Memory<br />

Read-Only Memory<br />

Remote Shell<br />

Transmission Control Protocol<br />

Trivial File Transfer Protocol<br />

terminal device<br />

9<br />

Board Names<br />

Names used for target VME boards should correspond to the names used by their<br />

suppliers; for example, MV135 is not an acceptable name for the MVME135.<br />

When multiple board models are covered by the same board support package, and<br />

the portion of their names that differs is separated by a slash ( / ) or a hyphen ( - ),<br />

these portions can be repeated, each separated by a comma and a space. See the<br />

examples below:<br />

Force SYS68K/CPU-21, -29, -32<br />

Heurikon HK68/V2F, V20, V2FA<br />

However:<br />

Motorola MVME147, MVME147S-1<br />

179


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

9.3 Format<br />

This section discusses general formatting requirements of Wind River reference<br />

documentation. Specific requirements relevant to <strong>BSP</strong>s are discussed in<br />

9.4 Subsections, p.183.<br />

Layout<br />

■<br />

Module Layout. To work with refgen, the documentation in source modules<br />

must be laid out in accordance with a few simple principles. These layout<br />

requirements are described in the Tornado User’s <strong>Guide</strong>: Coding Conventions.<br />

■<br />

General. Text should fill out the full line length (assume about 75<br />

characters). Do not start every sentence on a new line.<br />

Special Elements<br />

■<br />

Subroutines. Include parentheses with all subroutine names, even those<br />

generally construed as shell commands. Do not put a space between the<br />

parentheses or after the name (unlike the Wind River convention for code):<br />

CORRECT:<br />

taskSpawn()<br />

INCORRECT:<br />

taskSpawn( ), taskSpawn (), taskSpawn<br />

Note that there is one major exception to this rule: In the subroutine title, do<br />

not include the parentheses in the name of the subroutine being defined:<br />

CORRECT:<br />

/*************************************************<br />

*<br />

* xxxFunc - do such and such<br />

INCORRECT:<br />

/*************************************************<br />

*<br />

* xxxFunc() - do such and such<br />

180


9<br />

Documentation <strong>Guide</strong>lines<br />

■<br />

Avoid using a routine or module name as the first word in a sentence, but if<br />

you must, do not capitalize it.<br />

Parameters. When referring to parameters in text, surround the argument<br />

name with the angle brackets < and >. For example, if a routine getName( )<br />

had the following declaration:<br />

VOID getName<br />

(<br />

int tid, /* task ID */<br />

char * pTname /* task name */<br />

)<br />

You might say something like the following:<br />

This routine gets the name associated with the specified task ID and<br />

copies it to .<br />

9<br />

■<br />

Commands, Files, Tasks, Global Variables, Operators, C Keywords, Network<br />

Interfaces, and so on. Place names for these elements in single-quotes; for<br />

example:<br />

This routine maps an error number in ‘errno’ to an error message.<br />

■<br />

■<br />

Terminal Keys. Enter the names of terminal keys in all uppercase; for example,<br />

RETURN, ESC. Prefix the names of control characters with CTRL+; for example,<br />

CTRL+C.<br />

References to Publications. References to chapters of publications should take<br />

the form Publication Title: Chapter Name. For example, you might say:<br />

For more information, see the<br />

.I "VxWorks Programmer’s <strong>Guide</strong>: I/O System."<br />

■<br />

Do not include the chapter number. References to documentation volumes<br />

should be set off in italics. For general cases, use the .I macro. However, in<br />

SEE ALSO sections, use the .pG and .tG macros for the VxWorks Programmer’s<br />

<strong>Guide</strong> and Tornado User’s <strong>Guide</strong>, respectively. For more information, see Markup<br />

Commands, p.190.<br />

Section-Number Cross-References. Do not use the UNIX<br />

parentheses-plus-number scheme to cross-reference the documentation<br />

sections for libraries and routines:<br />

CORRECT:<br />

sysLib, vxTas()<br />

181


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

INCORRECT:<br />

sysLib(1), vxTas(2)<br />

Table 9-3<br />

Format of Special Elements<br />

Component Input Output (mangen + troff)<br />

library in title sysLib.c sysLib<br />

library in text sysLib sysLib<br />

subroutine in title sysMemTop sysMemTop( )<br />

subroutine in text sysMemTop() sysMemTop( )<br />

subroutine parameter ptid<br />

publication, not in SEE<br />

ALSO<br />

.I "Tornado User’s <strong>Guide</strong>" Tornado User’s <strong>Guide</strong><br />

VxWorks Programmer’s<br />

<strong>Guide</strong> in SEE ALSO<br />

Tornado User’s <strong>Guide</strong> in<br />

SEE ALSO<br />

.pG "Configuration"<br />

.tG "Cross-Development"<br />

VxWorks Programmer’s <strong>Guide</strong>:<br />

Configuration<br />

Tornado User’s <strong>Guide</strong>:<br />

Cross-Development<br />

emphasis .I must must<br />

Displays<br />

The macros and commands for creating the following displays are discussed more<br />

fully in 9.5.3 Text Formatting, p.190.<br />

■<br />

Code. Use the .CS and .CE macros for displays of code or terminal<br />

input/output. Indent such displays by four spaces from the left margin. 1 For<br />

example:<br />

* .CS<br />

* struct stat statStruct;<br />

* fd = open ("file", READ);<br />

* status = ioctl (fd, FIOFSTATGET, &statStruct);<br />

* .CE<br />

*<br />

1. For library entries, this means the display text starts at column 5; for subroutines, column 7<br />

(because for subroutines the effective line starts in column 3, because the initial star and<br />

space character are stripped off by refgen).<br />

182


9<br />

Documentation <strong>Guide</strong>lines<br />

■<br />

■<br />

■<br />

Board Diagrams. Use the .bS and .bE macros to display board diagrams under<br />

the BOARD LAYOUT heading in the target.nr module.<br />

Tables. Tables built with tbl mark-up are easy as long as you stick to basics,<br />

which will suffice in almost all cases. For information on the commands for<br />

building tables, see Tables, p.192. General stylistic considerations are as<br />

follows:<br />

– Set column headings in bold.<br />

– Separate column headings from the table body with a single rule.<br />

Lists. Mark list items with the standard man macro .IP. Do not use the .CS/.CE<br />

macros to create lists.<br />

9<br />

9.4 Subsections<br />

This section discusses special stylistic considerations for <strong>BSP</strong> documentation on a<br />

section-by-section basis. For more information and specific examples, refer to the<br />

<strong>BSP</strong> templates provided.<br />

In the examples below, mfr&board means the manufacturer’s name plus the full<br />

model name of the board, as described in Board Names, p.179.<br />

The target-information reference page (target.nr) has special requirements, and is<br />

thus described separately from standard library and subroutine reference pages.<br />

Library and Subroutine Reference Pages<br />

A template showing documentation for sysLib.c is provided in<br />

target/config/templateCPU/sysLib.c. Reference pages for libraries and<br />

subroutines always contain the following subsections in the order shown; other<br />

subsections can be included as needed:<br />

NAME<br />

the name of the library or subroutine<br />

SYNOPSIS<br />

for libraries, the summary of subroutines; for subroutines, the declaration<br />

(generated automatically by refgen).<br />

183


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

NAME Section<br />

DESCRIPTION<br />

an overall description of the library or subroutine<br />

INCLUDE FILES<br />

the included .h files (libraries only)<br />

RETURNS<br />

the values returned (subroutines only)<br />

SEE ALSO<br />

cross-references to documentation for other libraries and routines, or other<br />

user manuals<br />

Special considerations for these subsections are discussed below.<br />

■<br />

Libraries. Describe briefly what this collection of routines does. The hyphen<br />

must appear exactly as indicated (space-hyphen-space)—do not use<br />

backslashes or double hyphens. The general format is:<br />

nameLib.c - the such-and-such library<br />

For example:<br />

sysALib.s - mfr&board system-dependent assembly routines<br />

sysLib.c - mfr&board system-dependent library<br />

■<br />

Be sure to include the file-name extension (.c, .s); but note that the refgen<br />

process strips it off so that it does not appear in the final reference page entry.<br />

Subroutines. For the one-line heading/definition, use the imperative mood<br />

and convey action. The general format is:<br />

name - do such and such<br />

For example:<br />

DESCRIPTION Section<br />

sysMemTop - get the address of the top of memory<br />

Do not include the subroutine parentheses in the heading; the refgen process<br />

adds them in so that they appear in the final reference page entry.<br />

Start off the description section by saying: “This library...” or “This routine...”—do<br />

not repeat the module or subroutine name here; it has already been made<br />

clear. The remainder of the sentence should be a summary of what the library or<br />

routine does or provides (and in more depth than the NAME line).<br />

184


9<br />

Documentation <strong>Guide</strong>lines<br />

INCLUDE FILES Section<br />

Every library and driver entry should have a subheading INCLUDE FILES, which<br />

lists any relevant header files, for example:<br />

RETURNS Section<br />

INCLUDE FILES: sysLib.h<br />

The RETURNS section should be the last section before the SEE ALSO section.<br />

■<br />

Include a RETURNS section in all subroutines. If there is no return value (as in<br />

the case of a void) simply enter:<br />

■<br />

■<br />

■<br />

■<br />

■<br />

RETURNS: N/A<br />

Mention only true returns in the RETURNS section—not values copied to a<br />

buffer given as an argument.<br />

Always start a return-value statement with a capital and end it with a period;<br />

and again, do not use abbreviated English. For example:<br />

RETURNS: The address of the top of memory.<br />

Despite the general rule of style, we do not treat return values as complete<br />

sentences; the subject and verb are understood.<br />

Keep return statements in present tense. (Even if the conditions that cause an<br />

ERROR may be thought of as “past” once ERROR is returned.)<br />

In STATUS returns, ERROR must be followed by a qualifying statement.<br />

Always enter a comma after OK, because it must be clear that the qualifier<br />

belongs to the ERROR condition and not the OK. For example:<br />

RETURNS: OK, or ERROR if memory is insufficient.<br />

Do not preface lines of text with extra leading spaces—input lines whose first<br />

characters is a space cause a fill break. In the past, some authors applied this<br />

technique in RETURNS sections to force line breaks for separate elements of a<br />

return—we do not follow this convention. For example:<br />

CORRECT:<br />

* RETURNS: OK, or ERROR if the tick rate is invalid or the timer<br />

* cannot be set.<br />

9<br />

185


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

SEE ALSO Section<br />

INCORRECT:<br />

* RETURNS: OK, or ERROR<br />

* if the tick rate is invalid or<br />

* the timer cannot be set.<br />

The SEE ALSO section should be the last section of a reference-page entry.<br />

■<br />

■<br />

If the entry is a subroutine, refgen automatically includes the parent library in<br />

the SEE ALSO section.<br />

Do not cross-reference manual section numbers using the UNIX<br />

parentheses-plus-number scheme:<br />

CORRECT:<br />

SEE ALSO: sysLib, vxTas()<br />

INCORRECT:<br />

SEE ALSO: sysLib(1), vxTas(2)<br />

■<br />

In the SEE ALSO section, include cross-references to chapters of the VxWorks<br />

Programmer’s <strong>Guide</strong> or the Tornado User’s <strong>Guide</strong> by using the .pG macro or the<br />

.tG macro, respectively. The dot must be the first character on the effective line<br />

(for a subroutine section, refgen strips the star plus space); for example:<br />

* SEE ALSO: someLib, anotherLib,<br />

* .pG "Basic OS, Cross-Development,"<br />

* .tG "Setup and Startup"<br />

*/<br />

As this example illustrates, the cross-reference to another volume should come<br />

after cross-references to other libraries or subroutines. The .pG and .tG macros<br />

should only be used in SEE ALSO sections.<br />

Target Information Reference Page: target.nr<br />

A template for the target-information reference page is provided in<br />

target/config/templateCPU/target.nr. This reference entry always contains the<br />

subsections described below, and others as needed. Summary:<br />

NAME<br />

the name of the board<br />

186


9<br />

Documentation <strong>Guide</strong>lines<br />

INTRODUCTION<br />

summary of scope and assumptions<br />

FEATURES<br />

supported and unsupported features of the board<br />

HARDWARE DETAILS<br />

driver and hardware details for the board<br />

SPECIAL CONSIDERATIONS<br />

special features or restrictions<br />

BOARD LAYOUT<br />

the board layout in ASCII format<br />

SEE ALSO<br />

references to Wind River documentation<br />

BIBLIOGRAPHY<br />

references to additional documentation<br />

9<br />

NAME Section<br />

The information in the NAME section should all be on a single line and entered as<br />

a single argument to the .aX macro in the following format:<br />

.aX "mfr&board"<br />

mfr&board stands for the manufacturer’s name plus the manufacturer’s name for<br />

the board model, as described previously. For example:<br />

INTRODUCTION Section<br />

.aX "Motorola MVME147, MVME147S-1"<br />

This section includes getting started information, including subsections detailing<br />

ROM installation and jumper settings for VxWorks operation.<br />

FEATURES Section<br />

This section describes all the features of the board whether or not they are<br />

supported. Every feature of the board should be identified in either of the<br />

subsections, Supported Features or Unsupported Features. Each board configuration<br />

option should be considered a feature. A third subsection, Feature Interactions,<br />

describes how one feature or board configuration affects others.<br />

187


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

HARDWARE DETAILS Section<br />

This section discusses hardware elements and device drivers, such as serial,<br />

Ethernet, and SCSI. It also includes memory maps for each bus and lists of<br />

interrupt levels and/or vector numbers for each interrupting source.<br />

SPECIAL CONSIDERATIONS Section<br />

This section identifies the unique characteristics of the board. It includes all<br />

information needed by the user that does not fit in any other section.<br />

For customers who have the <strong>BSP</strong> Validation Test Suite, this section must also<br />

address known failures of VTS tests. Presumably the board doesn’t have a special<br />

feature or it implements it in a special manner. The <strong>BSP</strong> writer is responsible for<br />

documenting all exceptions noted during VTS testing of the <strong>BSP</strong>.<br />

BOARD LAYOUT Section<br />

Use the .bS/.bE macros to display board diagrams. See the template <strong>BSP</strong> for<br />

guidelines on diagramming jumper positions, or see target.nr, p.27.<br />

SEE ALSO Section<br />

This section always references the Setup and Startup chapter of the Tornado User’s<br />

<strong>Guide</strong>. Other Wind River manuals can be referenced as necessary.<br />

Use the .tG macro for Tornado User’s <strong>Guide</strong> references. Use the .pG macro for<br />

VxWorks Programmer’s <strong>Guide</strong> references. (See Markup Commands, p.190.) Use the .iB<br />

macro for other manuals. For example:<br />

BIBLIOGRAPHY Section<br />

.SH "SEE ALSO"<br />

.tG "Setup and Startup,"<br />

.pG "Configuration, Motorola MC680x0"<br />

This section references any additional technical manuals, data sheets, or<br />

supplements that the user should have at hand. Use the .iB macro for these<br />

references. (See Markup Commands, p.190.) For example:<br />

.SH "BIBLIOGRAPHY"<br />

.iB "Motorola MC68020 User’s Manual"<br />

.iB "Motorola MC68030 User’s Manual"<br />

188


9<br />

Documentation <strong>Guide</strong>lines<br />

9.5 Generating Reference Pages<br />

This section discusses the mechanics of generating <strong>BSP</strong> documentation: the files<br />

and tools used, the text formatting commands, and the makefile system used to<br />

process documentation from source code to printable reference pages.<br />

9.5.1 Files<br />

File-name extensions indicate the following types of files:<br />

.s assembly-language source files.<br />

.c C-language source files.<br />

.nr nroff/troff source file.<br />

.html generated HTML file.<br />

9<br />

Source Directory<br />

target/config/bspname<br />

This directory contains the C and assembly sources and documentation<br />

sources for a particular <strong>BSP</strong>; bspname is a directory name reflecting the maker<br />

and model of the board; for example, mv147 = Motorola MVME147. The files<br />

relevant to documentation are:<br />

Makefile<br />

Master makefile for building <strong>BSP</strong> and VxWorks modules. Three constants<br />

must be defined for documentation: TARGET_DIR, VENDOR, and<br />

BOARD. See 9.5.4 Processing, p.193 for more information.<br />

depend.bspname<br />

Dependency rules generated by Makefile.<br />

sysLib.c<br />

Library of board-dependent C routines.<br />

target.nr<br />

Source for the target-information reference page, containing general<br />

information about a board’s installation requirements or capabilities<br />

as they relate to VxWorks. This file is “manually” created nroff/troff<br />

source.<br />

189


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Documentation Directories<br />

docs/vxworks/bsp/bspname<br />

This directory contains the HTML reference-page files for <strong>BSP</strong>s. All files are<br />

generated from the source files in target/config/bspname by the make process,<br />

which runs refgen. The files are:<br />

bspname.html<br />

Target-information reference page generated from target.nr.<br />

sysLib.html<br />

Reference page for sysLib.c.<br />

libIndex.html<br />

Index of the <strong>BSP</strong>s library-level reference pages.<br />

rtnIndex.html<br />

Index of the <strong>BSP</strong>s subroutine reference pages.<br />

9.5.2 Tools<br />

host/host/bin/refgen<br />

This tool is a Tcl script that generates HTML files from specially formatted<br />

source code, which may be C language modules, assembly language modules,<br />

or target.nr files. The command-line syntax and options for refgen are<br />

summarized in the reference page shown in L. Refgen.<br />

9.5.3 Text Formatting<br />

Markup Commands<br />

This section describes the use of the UNIX nroff/troff man macros that form the<br />

basis of the formatting mark-up used in source files.<br />

Understanding the mark-up commands is necessary for constructing the target.nr<br />

file. However, in .c and .s files, mark-up should be restricted to .CS/.CE for<br />

showing examples, or .IP for building lists—mark-up should be used only<br />

sparingly in these modules, since most are added automatically.<br />

The list below shows the mark-up used in Wind River reference documentation.<br />

Mark-up commands inherited from the UNIX man macros are named with two<br />

190


9<br />

Documentation <strong>Guide</strong>lines<br />

uppercase letters. Those added by Wind River are named with a lowercase letter<br />

followed by an uppercase letter.<br />

Each command argument should be enclosed in quotation marks ("); for example:<br />

.SH "BOARD LAYOUT"<br />

.TH 12345<br />

Title Heading. This macro is used to fill in running header and footer<br />

fields. It is always the first macro called for a given manual entry. Its<br />

arguments are as follows:<br />

1 - module name (for target.nr, the target directory name)<br />

2 - section number of letter (“T” for target.nr documentation)<br />

3 - board manufacturer and model (middle part of running footer)<br />

4 - current date in the form “Rev: 01 Jan 97”<br />

5 - “VXWORKS REFERENCE MANUAL” (middle of running head)<br />

.SH heading<br />

Subheading (NAME, DESCRIPTION, and so on).<br />

9<br />

.CS<br />

.CE<br />

.bS<br />

.bE<br />

.IP x<br />

Code Start / Code End. This pair of macros is used to set off code displays—<br />

output appears in no-fill mode (exactly as typed) and is set in a<br />

fixed-width font.<br />

Board Start / Board End. This pair of macros is used to set off displays of<br />

board diagrams in target.nr. They are similar to .CS/.CE but output<br />

appears in a smaller font size. See target.nr, p.27 for guidelines on<br />

diagramming jumper positions using ASCII characters.<br />

Indented Paragraph. This macro is useful for creating itemized<br />

lists. Argument x is the item mark. Indentation ends when a .LP is<br />

encountered.<br />

.IP "FIODISKFORMAT"<br />

Formats the entire disk with appropriate hardware track and<br />

sector marks. No file system is initialized on the disk by<br />

this request.<br />

.IP "FIODISKINIT"<br />

Initializes a DOS file system on the disk volume.<br />

.LP<br />

Any other ioctl() function codes are passed to the block<br />

device driver for handling.<br />

191


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

.LP<br />

Example output:<br />

FIODISKFORMAT<br />

Formats the entire disk with appropriate hardware track and sector<br />

marks. No file system is initialized on the disk by this request.<br />

FIODISKINIT<br />

Initializes a DOS file system on the disk volume.<br />

Any other ioctl( ) function codes are passed to the block device driver for<br />

handling.<br />

Left Paragraph. This macro restores the left indent set by .IP. See the<br />

example above.<br />

.pG chapter<br />

Programmer’s <strong>Guide</strong> Chapter. This macro is used in a SEE ALSO section to<br />

specify a cross-reference to a chapter of the VxWorks Programmer’s<br />

<strong>Guide</strong>. See SEE ALSO Section, p.186.<br />

.tG chapter<br />

Tornado User’s <strong>Guide</strong> Chapter. This macro is used in a SEE ALSO section to<br />

specify a cross-reference to a chapter of the Tornado User’s <strong>Guide</strong>. See SEE<br />

ALSO Section, p.186.<br />

.iB text Bibliography. This macro is used in SEE ALSO and BIBLIOGRAPHY sections<br />

to reference documents other than the VxWorks Programmer’s <strong>Guide</strong> or the<br />

Tornado User’s <strong>Guide</strong>.<br />

.I text Italics. This macro is used to set text in italics.<br />

.aX text This macro causes no special formatting; wrs.an outputs its arguments<br />

verbatim. However, it is used by Wind River macro packages and scripts<br />

to collect data for tables of contents and indexes. Call directly in target.nr<br />

only. See NAME Section, p.184.<br />

Tables<br />

Building tables is easy as long as you stick to basics, which will suffice in almost all<br />

cases. General stylistic considerations are described in Displays, p.182.<br />

NOTE: Do not use the .CS/.CE macros to build tables. These macros are reserved<br />

for code examples.<br />

192


9<br />

Documentation <strong>Guide</strong>lines<br />

The following example demonstrates our general style:<br />

.TS<br />

expand;<br />

l l l .<br />

Column Head 1 | Column Head 2 | Column Head 3<br />

_<br />

Row 1 Col 1 | Row 1 Col 2 | Row 1 Col 3<br />

Row 2 Col 1 | Row 2 Col 2 | Row 2 Col 3<br />

.TE<br />

Alternatively, in the target.nr file only you can instead use tab characters as the<br />

column separator in place of “|”.<br />

9.5.4 Processing<br />

9<br />

The steps below describe how to generate <strong>BSP</strong> documentation using the makefiles<br />

based on the templates delivered with the <strong>BSP</strong> Developer’s Kit.<br />

1. In target/config/bspname, check for the existence of the three required constants<br />

in Makefile:<br />

TARGET_DIR<br />

target directory name (bspname); for example, “mv147”<br />

VENDOR<br />

vendor name; for example, “Motorola”<br />

BOARD<br />

board model name; for example, “MVME147, MVME147S-1”<br />

2. Generate the reference pages by running:<br />

make man<br />

This does the following:<br />

– Builds an appropriate depend.bspname.<br />

– Runs sysLib.c through the C preprocessor to collect any drivers included<br />

by #include directives.<br />

– Runs refgen -mg.<br />

– Distributes HTML reference pages to the appropriate WIND_BASE/docs<br />

directories.<br />

193


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

The flow chart in Figure 9-1 shows how the make process distributes <strong>BSP</strong><br />

reference pages in the docs/vxworks/bsp directory.<br />

Figure 9-1 Production Flow for <strong>BSP</strong> Documentation<br />

target/config/bspname<br />

target.nr<br />

sysLib.c<br />

make man<br />

(mg & mangen)<br />

docs/vxworks/bsp/bspname<br />

bspname.html<br />

sysLib.html<br />

libIndex.html<br />

rtnIndex.html<br />

194


10<br />

Product Packaging<br />

10.1 SETUP Developer’s Kit<br />

The current method of delivery for Wind River products uses the SETUP utility to<br />

create CD-ROM images. Products are encrypted and accessible only through<br />

installation keys. The SETUP utility is compatible with all supported host<br />

platforms.<br />

A SETUP CD-ROM image contains the appropriate unpacking routines for all host<br />

platforms. It also contains some text files: README.TXT, FIXED.TXT, and<br />

PROBLEMS.TXT.<br />

For more information, see the Tornado SETUP SDK Developer’s <strong>Guide</strong> (available<br />

from WindSurf).<br />

10.2 <strong>BSP</strong> Packaging<br />

Packaging involves both content and format of the delivered product. At Wind<br />

River, all <strong>BSP</strong>s are now formatted on CD-ROMs installable on any host. In the past,<br />

<strong>BSP</strong>s have been delivered on UNIX tar tapes or CD-ROMs containing a UNIX<br />

installation script and a Windows self-extracting utility.<br />

All VxWorks <strong>BSP</strong>s have similar directory structures and include several common<br />

files, which are described below. Strict adherence to the standards described in the<br />

195


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

following subsections is required to ensure smooth integration of the <strong>BSP</strong> into the<br />

VxWorks development system.<br />

<strong>BSP</strong> Contents<br />

Determining the files and directories that are delivered as part of a <strong>BSP</strong> product is<br />

one of the last and most important steps in creating a <strong>BSP</strong>. The <strong>BSP</strong> must include<br />

all the files needed to recompile the <strong>BSP</strong>. It must not contain any files that would<br />

cause another <strong>BSP</strong> to fail to compile on the user’s system.<br />

Default Configuration<br />

Before beginning the <strong>BSP</strong> packaging phase, you must establish and set the default<br />

configuration for the <strong>BSP</strong>. This means setting the configuration options in config.h<br />

and selecting the default deliverables using the RELEASE variable in the makefile.<br />

In some cases, the target board for which the <strong>BSP</strong> is written may be available in<br />

several different configurations. For example, it may be available with different<br />

memory modules, peripheral controllers, processor types, or revision levels. One<br />

<strong>BSP</strong> that supports all possible configurations is usually the desired solution.<br />

To this end, you are encouraged to configure the final <strong>BSP</strong> for the default case with<br />

the minimum configuration possible. This allows the ROM set and VxWorks image<br />

to run, as shipped, on most all variations of the target board. Thus, the default<br />

memory size should be the minimum available, and all optional peripheral<br />

controllers should be configured out of the <strong>BSP</strong>. If end users have more memory or<br />

an optional module, they can then configure in the appropriate support and<br />

rebuild the VxWorks image and VxWorks boot ROMs when necessary.<br />

Any <strong>BSP</strong> configuration mechanisms for tuning target board support should be<br />

accessible through parameters in config.h. These parameters are typically either<br />

macros or conditional compilation directives. Any uncommon or complex<br />

configuration mechanisms should be explained fully in config.h and in the<br />

SPECIAL CONSIDERATIONS section of target.nr.<br />

The standard delivered makefile targets for Wind River <strong>BSP</strong>s include bootrom,<br />

vxWorks, and vxWorks.st. The standard make variable RELEASE is defined to be<br />

these targets. If a different set of targets (say, bootrom_uncmp.hex instead of<br />

bootrom.hex) is to be delivered, RELEASE should be redefined in the makefile. For<br />

example:<br />

196


10<br />

Product Packaging<br />

...<br />

include $(TGT_DIR)/h/make/defs.$(WIND_HOST_TYPE)<br />

...<br />

RELEASE +=bootrom_uncmp.hex<br />

...<br />

include $(TGT_DIR)/h/make/rules.bsp<br />

...<br />

The purpose of delivering executable images to the customer is for demonstration<br />

and verification only. It is presumed that all customers will reconfigure and rebuild<br />

all executables in-house. This includes boot ROM images.<br />

Projects for the supported toolchains should also be delivered. The default name<br />

for these projects is bspName_gnu or bspName_diab. Third parties may use other<br />

naming schemes. These projects are built by default with the RELEASE macro.<br />

They can be built individually by using the make targets prj_gnu or prj_diab.<br />

10<br />

Included Files<br />

For details on the files included in a <strong>BSP</strong> product, see M. <strong>BSP</strong> Product Contents.<br />

<strong>BSP</strong> files fall into these categories:<br />

■<br />

Target-specific files: all files in the target/config/bspname and target reference<br />

page entries in the docs/vxworks/bsp/bspName directory.<br />

■<br />

■<br />

Files associated with the default projects generated from the <strong>BSP</strong>. This project<br />

can be created from the project facility or from the traditional command line<br />

using make release.<br />

Documentation files using HTML format. See the reference entry for the<br />

htmlBook command (Tornado User’s <strong>Guide</strong>: Utilities Reference).<br />

Excluded Files<br />

The following files should not be delivered with a <strong>BSP</strong> product:<br />

■<br />

VxWorks Files<br />

The product should not include any files that are provided to the user by any<br />

other Wind River product.<br />

target/config/all/....<br />

target/config/comps/...<br />

target/src/...<br />

target/h/...<br />

197


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

■<br />

The files in these directories are part of the VxWorks architecture/toolchain<br />

product and should not be altered by any third-party product.<br />

The <strong>BSP</strong> dependency file, target/config/bspname/depend.bspname, should not<br />

be delivered with the other <strong>BSP</strong> files. By not including this file, the system is<br />

forced to recreate it the first time a user issues any make command to compile<br />

anything.<br />

Driver Directories<br />

The product should not include any-third party files in the directories listed<br />

below. These directories are reserved for Wind River-original files only. Third<br />

parties should not add to, or modify, any file from these directories. If the <strong>BSP</strong><br />

includes a <strong>BSP</strong>-specific version of a Wind River driver, the driver should be<br />

distributed in the <strong>BSP</strong> directory, not the target/src/drv directory.<br />

target/h/drv/...<br />

target/src/drv/...<br />

■<br />

Modified Wind River object files<br />

The <strong>BSP</strong> writer should not deliver any object file that overwrites or replaces a<br />

Wind River-supplied object file. Unique or special object files shall be<br />

delivered in the <strong>BSP</strong> directory itself.<br />

■<br />

Copyright Protected Files<br />

Wind River reserves all rights to its network and SCSI drivers. No third party<br />

may distribute the source code to these drivers, or to any derivative driver<br />

without the express written consent of Wind River Systems. Source code for<br />

Wind River component releases is normally protected.<br />

target/src/drv/netif/any.c<br />

target/src/drv/scsi/any.c<br />

target/src/drv/end/any.c<br />

Source of the Files<br />

The template <strong>BSP</strong> included in the <strong>BSP</strong> Kit product is not the source for the generic<br />

driver or architecture-specific driver files. The sample <strong>BSP</strong> is supplied primarily as<br />

an aid to developers who are creating target-specific files and new drivers.<br />

Developers typically copy common files from a reference <strong>BSP</strong> (one <strong>BSP</strong> is bundled<br />

with each VxWorks object license).<br />

198


10<br />

Product Packaging<br />

Vendor-Supplied Shared Files<br />

Some files can appear to be target-specific when in fact they are shared by multiple<br />

<strong>BSP</strong>s. These shared files include those described above as “generic” and<br />

“architecture-specific,” as well as files included on the Device Driver Object<br />

product.<br />

The following directories are distributed with the Tornado architecture product<br />

and the Tornado driver component product:<br />

target/config/all<br />

target/src/config<br />

target/src/drv/antyhing<br />

target/h/drv/anything<br />

target/h/make<br />

target/h/tool/anything<br />

Under no circumstances may these directories and files be altered and shipped by<br />

third-party developers. Although <strong>BSP</strong> developers are encouraged to create generic<br />

device drivers, they must not place the source code in the target/src/drv and<br />

target/h/drv directories; all existing Wind River drivers must not be modified. If an<br />

end user were to install a Wind River <strong>BSP</strong> or a new VxWorks version after<br />

installing a third-party <strong>BSP</strong> with altered shared files, the third-party changes<br />

would be overwritten by the Wind River files.<br />

Typically, <strong>BSP</strong>s can be written so that all target-specific files reside in<br />

target/config/bspname, and target reference pages in docs/vxworks/bsp/bspName.<br />

In the few cases where this is not possible, the <strong>BSP</strong> must include altered versions<br />

of the shared files. However, the shared files themselves must not be altered;<br />

instead, a copy of the needed file is modified and placed in an appropriate location<br />

(for example, target/config/bspname). Then the <strong>BSP</strong> make files are updated to point<br />

to the developer’s version; see the makefile mechanisms described in the Tornado<br />

User’s <strong>Guide</strong>, 2.2.<br />

The <strong>BSP</strong> developer can use the CONFIG_ALL makefile variable to direct the <strong>BSP</strong><br />

make files to search for modified versions of the target/config/all files. First, the<br />

developer should make copies of the Wind River versions of these files and place<br />

them in the <strong>BSP</strong> bspname directory, modifying them as necessary. (Note that this<br />

mechanism only works for traditional command-line building and does not have<br />

any effect on project configuration or building.)<br />

By customizing the VxWorks build, the <strong>BSP</strong> developer can create target-specific<br />

versions of shared files without conflicting with other <strong>BSP</strong>s.<br />

Beginning with Tornado 2.0, each architecture CD-ROM contains a “Driver<br />

Objects/Headers” product. This product contains all the compiled Ethernet and<br />

10<br />

199


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

SCSI drivers for that architecture, and their headers. Also included are all the<br />

unprotected Wind River drivers in source form. It is expected that customers will<br />

be able to download updated driver products from the Web.<br />

10.2.1 <strong>BSP</strong> Media<br />

Beginning with Tornado 1.0.1, all Wind River products have been packaged onto<br />

CD-ROM media using a new combined UNIX/Windows SETUP utility. Both<br />

UNIX and Windows users begin the installation process with the SETUP<br />

command. All users are then presented with a consistent graphical user interface<br />

that guides them through the product and license manager installations.<br />

For more information, see the Tornado SETUP SDK Developer’s <strong>Guide</strong> (available<br />

from WindSurf).<br />

10.3 Component Packaging<br />

Component packaging is a problem area. Wind River delivers the parts of its<br />

components in their traditional locations:<br />

– Source code modules are usually found in the target/src or target/config<br />

directories.<br />

– Headers are found in target/h; object modules are delivered in<br />

target/lib/objARCH.<br />

– Component description files are in target/config/comps/vxWorks.<br />

– Component configlettes (source fragments) are in target/config/comps/src.<br />

Third parties are not limited to this arrangement, and the location of component<br />

elements can be fully described in the component description file. It is<br />

recommended that third parties place their component source and object elements<br />

in a directory, such as target/config/vendor_name. The location of the component<br />

description file (CDF) depends on where in the system the components should be<br />

integrated.<br />

To integrate the new component into the full system, the CDF should be located in<br />

target/config/comps/vxWorks. If it is a <strong>BSP</strong>-specific component, the file should be<br />

located in the <strong>BSP</strong> directory. If it is specific to a single project, it should be located<br />

200


10<br />

Product Packaging<br />

in the project directory (target/proj/project_name). Be sure to follow the proper<br />

naming conventions. All third-party CDF names must begin with a sequence<br />

number between 50 and 99 (See 6.3.2 CDF Precedence and Paths, p.126).<br />

Third-party components should not overwrite a Wind River-supplied file. They<br />

may override the description of a Wind River component within their own<br />

component description file. It is not necessary to overwrite a file to change a<br />

component’s behavior, because of file precedence.<br />

10.4 Project Packaging<br />

Projects are normally packaged together as a group of files in a single directory.<br />

Projects can be built using the project creation wizard or from the command line<br />

using make release.<br />

Here is a typical file listing of a standard Wind River <strong>BSP</strong> project:<br />

10<br />

bsp_gnu<br />

bsp_gnu/bsp_gnu.wpj<br />

bsp_gnu/usrAppInit.c<br />

bsp_gnu/prjParams.h<br />

bsp_gnu/linkSyms.c<br />

bsp_gnu/prjConfig.c<br />

bsp_gnu/Makefile<br />

bsp_gnu/default<br />

bsp_gnu/default/vxWorks<br />

bsp_gnu/default_rom/vxWorks_rom<br />

bsp_gnu/default_romCompressed/vxWorks_romCompressed<br />

bsp_gnu/default_romResident/vxWorks_romResident<br />

(intermediate .o files have been omitted)<br />

Any special components and CDFs that a project requires should be built into the<br />

project. If a project is transferred from one installation to another, the component<br />

description files at the new installation are used when the project is rebuilt.<br />

Third parties should package their projects for delivery to customers in a similar<br />

manner. You can use the target/proj directory provided your project directory<br />

names do not conflict with those of any Wind River-provided projects.<br />

201


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

202


A<br />

Upgrading a <strong>BSP</strong> for<br />

Tornado 2.0<br />

This appendix describes how to port a <strong>BSP</strong> from Tornado 1.0.1/VxWorks 5.3.1 to<br />

Tornado 2.0/VxWorks 5.4.<br />

<strong>BSP</strong>s written for VxWorks 5.2, or earlier releases, are designated as version 1.0<br />

<strong>BSP</strong>s. <strong>BSP</strong>s written for Tornado 1.0.1, or earlier, are designated as version 1.1 <strong>BSP</strong>s.<br />

<strong>BSP</strong>s written to the standard outlined in this document, specifically for Tornado<br />

2.0, are designated as version 1.2 <strong>BSP</strong>s.<br />

All version 1.1 <strong>BSP</strong>s that have been modified to use END drivers and the SENS<br />

network stack are compatible with Tornado 2.0. Third-party <strong>BSP</strong>s using<br />

specialized make sequences and modified versions of kernel files may or may not<br />

translate well to projects. They will work correctly if the traditional command line<br />

is used to build the project.<br />

A.1 Porting Issues<br />

Porting an existing Tornado 1.0.1 <strong>BSP</strong> to Tornado 2.0 involves three main steps:<br />

■<br />

■<br />

Update the <strong>BSP</strong> for the SENS network stack. If an END-style driver is available<br />

for the <strong>BSP</strong>, then it should become the default network driver. Any custom<br />

network drivers that are not END or BSD 4.4 compatible must be upgraded for<br />

SENS. See C. Upgrading a <strong>BSP</strong> for the VxWorks Network Stack.<br />

Create a default project and the HTML documentation for the <strong>BSP</strong>. This is done<br />

using the command make release man.<br />

203


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

■<br />

Create a <strong>BSP</strong> product. This applies only to customers who intend to distribute<br />

their <strong>BSP</strong> to other Wind River customers. See A.4 Product Contents, p.205 for<br />

information on how to package a <strong>BSP</strong> product for delivery to customers.<br />

A.2 Code Interface Changes<br />

None of the standard APIs used in <strong>BSP</strong>s have been changed since Tornado 1.0.1.<br />

The Tornado Release Notes, 2.0, mentions changes to the API for pciConfigLib and<br />

access mechanism 0; however, these modifications should affect very few<br />

customers, if any at all.<br />

The version numbers of Wind River <strong>BSP</strong>s have been updated to version 1.2 as a<br />

result of changes to product packaging. Wind River uses a <strong>BSP</strong> identification<br />

scheme of the form X.X/Y, where X.X is the <strong>BSP</strong> version identification, and Y is the<br />

revision ID. The revision ID is incremented by one each time a <strong>BSP</strong> is updated or<br />

re-released. The first revision number for any new <strong>BSP</strong> is zero (0), not one (1). The<br />

config.h file includes the macro <strong>BSP</strong>_REV, which is a string indicating the revision<br />

number of the <strong>BSP</strong>, for example:<br />

#define <strong>BSP</strong>_VER_1_2 1<br />

#define <strong>BSP</strong>_VER_1_1 1<br />

#define <strong>BSP</strong>_VERSION "1.2" /* A Tornado 2.0 <strong>BSP</strong> */<br />

#define <strong>BSP</strong>_REV "/0" /* First Tornado 2.0 revision */<br />

The config.h file also declares the <strong>BSP</strong> version number in both string and macro<br />

form. The <strong>BSP</strong>_VERSION macro is a string, for example “1.2”. The macro<br />

<strong>BSP</strong>_VER_1_2 is defined to be the integer 1 and can be used in both #if and #ifdef<br />

expressions. Since version 1.2 <strong>BSP</strong>s are otherwise compatible with version 1.1<br />

<strong>BSP</strong>s, the macro <strong>BSP</strong>_VER_1_1 can also be defined.<br />

At the end of config.h, add directives that #include the project parameters header<br />

file when building from the project facility.<br />

#if defined(PRJ_BUILD)<br />

# include "prjParams.h"<br />

#endif<br />

204


A<br />

Upgrading a <strong>BSP</strong> for Tornado 2.0<br />

A.3 Project Issues<br />

The project facility is the major difference between Tornado 1.0.1 and Tornado 2.0.<br />

For command-line operations, there is no difference between a Tornado 1.0.1 and<br />

a Tornado 2.0 <strong>BSP</strong>. In Tornado 2.0, project builds are completely new, and they do<br />

not involve files in target/config/all. The old usrConfig.c file has been pulled apart<br />

into initialization groups and component configlettes, which are compiled and<br />

linked together by the project build mechanism. Building with the project facility<br />

differs greatly from building from the command line.<br />

Building from the command line uses the <strong>BSP</strong> Makefile as well as the config.h and<br />

configAll.h header files to control most of the configuration of the object being<br />

built. When building from the project facility, the configuration is determined by<br />

the project header files instead. Project building does not involve the <strong>BSP</strong> makefile.<br />

If there is an item in config.h or configAll.h that is described to the project facility<br />

through a CDF file, that item is controlled solely by the project information;<br />

changes to config.h and configAll.h do not affect it, nor do they affect an existing<br />

project.<br />

Note, if there is something in config.h or configAll.h that the project tool is not<br />

aware of, then the config.h and configAll.h selections will prevail during project<br />

builds.<br />

There are two methods for generating a default project from a <strong>BSP</strong><br />

■<br />

Invoke the project facility wizard. To open the wizard, select the File>New<br />

Project command from the menubar, or, if the Create Project or Open Workspace<br />

window is open, select the New tab.<br />

■<br />

Use the command line, as follows:<br />

A<br />

make release<br />

A.4 Product Contents<br />

The most obvious change for version 1.2 <strong>BSP</strong>s is the product contents list, which is<br />

provided in M. <strong>BSP</strong> Product Contents.<br />

In Tornado 1.0.1, each <strong>BSP</strong> product carried a large number of driver files that were<br />

also delivered as part of the base Tornado product. This redundancy caused<br />

problems for customers, who were uncertain what version of a file was being used.<br />

205


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

In Tornado 2.0, neither the <strong>BSP</strong> nor the base product includes any generic Wind<br />

River driver elements. Generic driver elements are a separate product on the<br />

CD-ROM, where they are usually listed in the contents as “Driver<br />

objects/headers”. This product contains all the object modules for network and<br />

SCSI drivers. It also contains all the source for other drivers, as well as the header<br />

files.<br />

Also new for Tornado 2.0 is the <strong>BSP</strong> project. Each <strong>BSP</strong> should include a default<br />

project that represents the default configuration of the <strong>BSP</strong>. End-users should be<br />

encouraged to base the new projects on a <strong>BSP</strong>’s default project; they should not be<br />

developed directly from a <strong>BSP</strong>.<br />

Documentation deliverables have also changed. The new documentation standard<br />

is based on HTML pages that can be browsed. This replaces UNIX-style man<br />

pages. For more information, see L. Refgen.<br />

A.4.1 Product Restrictions<br />

■<br />

Do not provide any files or modules that overwrite anything provided by<br />

Wind River in any product:<br />

target/config/anything<br />

target/lib/obj$(CPU)$(TOOL)vx/anything<br />

target/config/all/anything<br />

target/src/drv/any.c<br />

target/h/drv/any.c<br />

■<br />

Do not include any <strong>BSP</strong>-specific file or module in a restricted Wind River<br />

directory. (that is, third parties must deliver files in target/config/xxxx<br />

directories only):<br />

target/config/all/*<br />

target/src/*<br />

target/h/*<br />

target/lib/*<br />

■<br />

Do not include the <strong>BSP</strong> dependency file used with command-line building. By<br />

not including this file, the make system is forced to rebuild the information the<br />

first time the user gives a make command:<br />

target/config/target/depend.target<br />

206


A<br />

Upgrading a <strong>BSP</strong> for Tornado 2.0<br />

■<br />

Do not include old-style man pages:<br />

target/man/*.*<br />

target/man/manX/*.*<br />

A.4.2 Product Requirements<br />

■<br />

Include the <strong>BSP</strong>-specific files that are always part of the <strong>BSP</strong> product (a typical<br />

<strong>BSP</strong> is shown):<br />

target/config/bspname/Makefile<br />

target/config/bspname/README<br />

target/config/bspname/bootrom.hex<br />

target/config/bspname/config.h<br />

target/config/bspname/configNet.h<br />

target/config/bspname/romInit.s<br />

target/config/bspname/sysALib.s<br />

target/config/bspname/sysLib.c<br />

target/config/bspname/sysScsi.c<br />

target/config/bspname/sysSerial.c<br />

target/config/bspname/target.nr<br />

target/config/bspname/vxWorks<br />

target/config/bspname/vxWorks.st<br />

target/config/bspname/vxWorks.sym<br />

A<br />

■<br />

Include project files generated by the project facility wizard:<br />

target/proj/bspname_vx/Makefile<br />

target/proj/bspname_vx/prjComps.h<br />

target/proj/bspname_vx/prjObjs.lst<br />

target/proj/bspname_vx/usrAppInit.c<br />

target/proj/bspname_vx/bspname_vx.wpj<br />

target/proj/bspname_vx/linkSyms.c<br />

target/proj/bspname_vx/prjConfig.c<br />

target/proj/bspname_vx/prjParams.h<br />

■<br />

Include the default build files generated by the project facility wizard:<br />

target/proj/bspname_vx/default/*.*<br />

207


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

■<br />

Include the <strong>BSP</strong> help files created by make man:<br />

docs/vxworks/bsp/bspname/*.*<br />

A.5 Summary<br />

You can model your porting activities on the following steps, which were taken at<br />

Wind River Systems, to update 1.1 <strong>BSP</strong>s to version 1.2:<br />

1. All Wind River <strong>BSP</strong>s were updated to use END-style drivers or modified BSD<br />

4.4 drivers compatible with the SENS 1.1 product. This occurred when the<br />

SENS product for Tornado 1.0.1 was delivered.<br />

2. Some <strong>BSP</strong>s and drivers received normal maintenance patches. These had<br />

nothing to do with the implementation of projects or components.<br />

3. The macros <strong>BSP</strong>_VERSION, <strong>BSP</strong>_VER_1_2, and <strong>BSP</strong>_REV were added to<br />

config.h. These macros must be inserted prior to the statement #include<br />

"configAll.h", as it appears in the following file excerpt:<br />

...<br />

/* New <strong>BSP</strong> version/revision id */<br />

#define <strong>BSP</strong>_VER_1_2 1<br />

#define <strong>BSP</strong>_VER_1_1 1 /* compatible with 1.2 */<br />

#define <strong>BSP</strong>_VERSION "1.2"<br />

#define <strong>BSP</strong>_REV "/0" /* increment with each revision */<br />

#include "configAll.h"<br />

...<br />

4. The prjParams.h file was included conditionally at the end of the config.h file,<br />

as follows:<br />

#if defined(PRJ_BUILD)<br />

# include "prjParams.h"<br />

#endif<br />

5. The README file was modified to reflect the new release of the <strong>BSP</strong>. A new<br />

entry was added to the top of the list to identify the new version and revision<br />

of the <strong>BSP</strong>, for example:<br />

1.2/0 - First release for Tornado 2.0.<br />

208


A<br />

Upgrading a <strong>BSP</strong> for Tornado 2.0<br />

6. The default project files were generated:<br />

make release<br />

7. The default help files were generated:<br />

make man<br />

8. The new product was created. All driver elements were removed from the file<br />

lists for the <strong>BSP</strong>. The new project-based files were added to the file list. New<br />

HTML documentation files were also added, replacing old-style man pages<br />

held in the directories target/man/manX.<br />

A<br />

209


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

210


B<br />

Upgrading a <strong>BSP</strong> for<br />

Tornado 2.2<br />

This chapter discusses the migration of a <strong>BSP</strong> to VxWorks 5.5. It includes<br />

information on both architecture-independent and architecture-dependent issues.<br />

B.1 Architecture-Independent Changes to <strong>BSP</strong>s<br />

<strong>BSP</strong> Makefile Changes and the bspCnvtT2_2 Tool<br />

The <strong>BSP</strong> makefile has been simplified by minimizing the number of include<br />

statements needed. In particular, prior to Tornado 2.2, a makefile needed several<br />

includes, as shown in Example B-1.<br />

Example B-1 Makefile includes Prior to Tornado 2.2<br />

...<br />

include $(TGT_DIR)/h/make/defs.bsp<br />

include $(TGT_DIR)/h/make/make.$(CPU)$(TOOL)<br />

include $(TGT_DIR)/h/make/defs.$(WIND_HOST_TYPE)<br />

...<br />

include $(TGT_DIR)/h/make/rules.bsp<br />

include $(TGT_DIR)/h/make/rules.$(WIND_HOST_TYPE)<br />

...<br />

In Tornado 2.2, only two of these include statements are necessary:<br />

211


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

...<br />

include $(TGT_DIR)/h/make/defs.bsp<br />

...<br />

include $(TGT_DIR)/h/make/rules.bsp<br />

...<br />

The defs.bsp and rules.bsp files now include any other files necessary to build<br />

your <strong>BSP</strong>. To modify your <strong>BSP</strong>, simply comment out the unnecessary includes in<br />

your makefile.<br />

In addition, a makefile conversion tool, bspCnvtT2_2, has been provided in the<br />

installDir/host/$(WIND_HOST_TYPE)/bin directory. You can invoke<br />

bspCnvtT2_2 with the following syntax:<br />

% bspCnvtT2_2 bspName1 bspName2 ...<br />

bspCnvtT2_2 converts your makefile by performing the following actions:<br />

■<br />

■<br />

■<br />

Saving your old makefile to a file named Makefile.old in your <strong>BSP</strong> directory.<br />

Commenting out the unnecessary includes.<br />

Warning you about the use of any hex build flags. (See Hex Utilities and objcopy,<br />

p.212.)<br />

Hex Utilities and objcopy<br />

The use of Wind River-provided hex and binary utilities, such as aoutToBinDec or<br />

coffHexArm, has been deprecated in favor of the GNU utility objcopy. See the<br />

GNU Toolkit User’s <strong>Guide</strong> chapter on binary utilities for details. It is recommended<br />

that you modify your <strong>BSP</strong> build settings as necessary to use objcopy.<br />

New Default Value of WDB_COMM_TYPE<br />

The WDB_COMM_TYPE default value has been changed from<br />

WDB_COMM_NETWORK to WDB_COMM_END. If you plan to use a different<br />

communication mode, define it explicitly in config.h. For example, if by default<br />

your <strong>BSP</strong> sets up WDB communication on a serial line, you should include the<br />

following line in config.h:<br />

...<br />

/* make sure this appears after inclusion of configAll.h */<br />

#define WDB_COMM_TYPE WDB_COMM_SERIAL<br />

...<br />

212


B<br />

Upgrading a <strong>BSP</strong> for Tornado 2.2<br />

Changes in the Shared Memory Subsystem<br />

A <strong>BSP</strong> for VxWorks 5.5 requires several modest changes to config.h and possibly<br />

to sysLib.c in order to support the shared memory network and the optional<br />

component VxMP. In past releases of VxWorks, you could ensure that the shared<br />

memory components were included simply by verifying the inclusion of the<br />

shared memory backplane network. But in VxWorks 5.5, VxMP can be configured<br />

without support for the shared memory network.<br />

A new component with the inclusion macro INCLUDE_SM_COMMON has been<br />

added to VxWorks 5.5. Use this macro to test for shared memory support. The<br />

majority of <strong>BSP</strong>s that support shared memory use conditional compilation<br />

statements such as the following:<br />

#ifdef INCLUDE_SM_NET<br />

/* shared memory-specific code */<br />

#endif<br />

For VxWorks 5.5, these statements must be updated to test for<br />

INCLUDE_SM_COMMON:<br />

B<br />

#ifdef INCLUDE_SM_COMMON<br />

/* shared memory-specific code */<br />

#endif<br />

When you modify sysLib.c, follow the simple rule of replacing all instances of<br />

INCLUDE_SM_NET with INCLUDE_SM_COMMON.<br />

With a few exceptions, you can use the same rule in changing config.h. A test for<br />

INCLUDE_SM_NET is still valid in network-related statements, but is not valid as<br />

a test for the common shared memory parameters:<br />

SM_ANCHOR_ADRS SM_ANCHOR_OFFSET SM_CPUS_MAX<br />

SM_INT_ARG1 SM_INT_ARG2 SM_INT_ARG3<br />

SM_INT_TYPE SM_MASTER SM_MAX_WAIT<br />

SM_MEM_ADRS SM_MEM_SIZE SM_OBJ_MEM_SIZE<br />

SM_OFF_BOARD SM_TAS_TYPE<br />

These shared memory parameters do not require conditional compilation and can<br />

be left defined at all times. (Note that some are defined by default in configAll.h<br />

and must be undefined before being redefined in config.h.)<br />

The definition of INCLUDE_SM_NET in config.h may also bring in components<br />

that have changed in VxWorks 5.5, such as INCLUDE_NET_SHOW and<br />

INCLUDE_BSD. These components are no longer needed; the smNetShow( )<br />

routine is now in a separate component, called INCLUDE_SM_NET_SHOW, and<br />

proper BSD or other network configuration is contained in other files.<br />

213


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Changes in Other Run-time Facilities<br />

Several optional products for Tornado 2.2/VxWorks 5.5 have undergone changes<br />

that necessitate <strong>BSP</strong> revisions:<br />

■<br />

■<br />

■<br />

True Flash File System (TrueFFS). For details, see the VxWorks Programmer’s<br />

<strong>Guide</strong> chapter on the Flash Memory Device Interface. Also consult the library<br />

entries for tffsConfig and tffsDrv in the VxWorks API Reference.<br />

USB. For details, see the USB Developer’s Kit Programmer’s <strong>Guide</strong>, 1.1.2, and the<br />

USB Developer’s Kit Release Notes, 1.1.2.<br />

DosFs 2.0. This updated version of the DOS file system support for VxWorks<br />

necessitates changes to your <strong>BSP</strong>. Because dosFsNLib version 2.0 has been<br />

available since shortly after the Tornado 2.0 release, many Tornado 2.0.x and<br />

later <strong>BSP</strong>s may already support it, and do not require modification.<br />

B.2 Architecture-Dependent <strong>BSP</strong> Issues<br />

The following sections provide the specific steps required to upgrade your <strong>BSP</strong> to<br />

Tornado 2.2/VxWorks 5.5 as well as architecture-specific information related to<br />

upgrading a <strong>BSP</strong>. For additional architecture-specific information, refer to the<br />

appropriate VxWorks Architecture Supplement manual for your target<br />

architecture (available on WindSurf).<br />

NOTE: Architecture information provided in this section is accurate at the time of<br />

publication. For current architecture information, see the Tornado Migration<br />

<strong>Guide</strong>, 2.2 (available on the Wind River Support Web site).<br />

B.2.1 Migration Changes Common to All Architectures<br />

NOTE: Some material in this section overlaps with the information in<br />

B.1 Architecture-Independent Changes to <strong>BSP</strong>s, p.211.<br />

The following changes are required for all <strong>BSP</strong>s, regardless of architecture:<br />

214


B<br />

Upgrading a <strong>BSP</strong> for Tornado 2.2<br />

■<br />

■<br />

Makefile update. This step is required for all users. Use the bspCnvtT2_2 script<br />

to update the <strong>BSP</strong> makefile. This script comments out unnecessary include<br />

lines and any existing HEX_FLAGS value.<br />

TFFS support. This step is required for <strong>BSP</strong>s with TFFS support. Remove the<br />

inclusion of sysTffs.c from the syslib.c file.<br />

B.2.2 68K/CPU32<br />

All Wind River-supplied <strong>BSP</strong>s for the 68K/CPU32 architecture released with the<br />

Tornado 2.2 product have been upgraded for use with VxWorks 5.5. Custom<br />

VxWorks 5.4-based <strong>BSP</strong>s require only the modifications described in<br />

B.2.1 Migration Changes Common to All Architectures, p.214 to upgrade to VxWorks<br />

5.5. No architecture-specific modifications are required.<br />

For more information on using VxWorks with 68K/CPU32 targets, see the<br />

VxWorks for 68K/CPU32 Architecture Supplement.<br />

B<br />

B.2.3 ARM<br />

NOTE: This section describes <strong>BSP</strong> migration from Tornado 2.1\VxWorks 5.4 to<br />

Tornado 2.2\VxWorks 5.5. For information on migrating a <strong>BSP</strong> from Tornado 2.0.x<br />

to Tornado 2.1, see the Tornado for ARM Release Notes and Architecture Supplement<br />

manual available on WindSurf.<br />

In addition to the steps described in B.2.1 Migration Changes Common to All<br />

Architectures, p.214, the following ARM-specific migration changes are required:<br />

■<br />

For assembly files only. The new macros GTEXT, GDATA, FUNC, and<br />

FUNC_LABEL have been added to assist in porting assembly files. The leading<br />

underscores in global assembly label names should be removed. Using these<br />

macros allows source compatibility between Tornado 2.1.x and Tornado 2.2.<br />

■<br />

Diab support. Due to differences in assembler syntax between the GNU and<br />

Diab toolchains, you need to change any GNU assembly macros to Diab<br />

syntax. For more information on Diab assembly syntax, see the Diab C/C++<br />

Compiler for ARM User’s <strong>Guide</strong>.<br />

For more information on using VxWorks with ARM targets, see the VxWorks for<br />

ARM Architecture Supplement.<br />

215


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

B.2.4 ColdFire<br />

In addition to the steps described in B.2.1 Migration Changes Common to All<br />

Architectures, p.214, the following ColdFire-specific issues should be considered<br />

when migrating your custom <strong>BSP</strong>:<br />

■<br />

Diab support. This release of VxWorks for ColdFire includes the same basic<br />

layout and functionality included with the previous Tornado 2.1/VxWorks 5.4<br />

release. However, the GNU toolchain is no longer supported.<br />

For more information on using VxWorks with ColdFire targets, see the VxWorks for<br />

ColdFire Architecture Supplement.<br />

B.2.5 MIPS<br />

NOTE: This section describes <strong>BSP</strong> migration from Tornado 2.1\VxWorks 5.4 to<br />

Tornado 2.2\VxWorks 5.5. For information on migrating a <strong>BSP</strong> from Tornado 2.0.x<br />

to Tornado 2.1, see the Tornado for MIPS Release Notes and Architecture Supplement<br />

manual available on WindSurf.<br />

In addition to the steps described in B.2.1 Migration Changes Common to All<br />

Architectures, p.214, the following MIPS-specific issues should be considered when<br />

migrating your custom <strong>BSP</strong> to Tornado 2.2/VxWorks 5.5:<br />

■<br />

CPU variants. MIPS CPUs are now organized by CPU variant. This allows the<br />

VxWorks kernel to take advantage of the specific architecture characteristics of<br />

one variant without negatively impacting another. As a result, all MIPS <strong>BSP</strong>s<br />

must now include a CPU_VARIANT line in the Makefile after the<br />

MACH_EXTRA line. For example, CPUs which fall into the category of Vr54xx<br />

variants, use the following line:<br />

CPU_VARIANT<br />

=_vr54xx<br />

■<br />

■<br />

See the VxWorks for MIPS Architecture Supplement for a list of MIPS CPUs and<br />

their respective CPU_VARIANT values.<br />

MIPS64 Libraries. The MIPS64 libraries (MIPS64gnu, MIPS64diab,<br />

MIPS64gnule, and MIPS64diable) now support 64-bit MIPS devices with ISA<br />

Level III and above. In previous versions of VxWorks, these libraries only<br />

supported MIPS devices with ISA Level IV and above. For more information<br />

on compiler options for MIPS libraries, refer to the Architecture Supplement.<br />

Alchemy Semiconductor <strong>BSP</strong>s. The Alchemy Semiconductor <strong>BSP</strong>, pb1000, has<br />

been altered to provide additional support to the pb1500 <strong>BSP</strong>. As a result, some<br />

216


B<br />

Upgrading a <strong>BSP</strong> for Tornado 2.2<br />

changes have been made to the API of the common support for these two <strong>BSP</strong>s.<br />

All macro, driver, and file names previously using au1000 have been changed<br />

to simply au. For example, the cache library cacheAu1000Lib is now known as<br />

cacheAuLib. For more details on these changes, refer to the <strong>BSP</strong> and its<br />

supporting drivers.<br />

For more information on using VxWorks with MIPS targets, see the VxWorks for<br />

MIPS Architecture Supplement.<br />

B.2.6 Pentium<br />

In addition to the steps described in B.2.1 Migration Changes Common to All<br />

Architectures, p.214, the following Pentium-specific issues should be considered<br />

when migrating your custom <strong>BSP</strong> to Tornado 2.2/VxWorks 5.5:<br />

■<br />

■<br />

■<br />

■<br />

■<br />

■<br />

■<br />

The new CPU types PENTIUM2, PENTIUM3, and PENTIUM4 have been added<br />

and CPU_VARIANT has been removed. Thus, CPU_VARIANT should be<br />

replaced with a new CPU type that is appropriate for your processor.<br />

Three new code selectors, sysCsSuper, sysCsExc, and sysCsInt, have been<br />

added for this release, and sysCodeSelector has been removed. In existing<br />

<strong>BSP</strong>s, sysCodeSelector should be replaced with sysCsSuper.<br />

The ROM_IDTR, ROM_GDTR, ROM_GDT, ROM_INIT2 offset macros have<br />

been removed due to improvements in the GNU assembler (GAS). These<br />

macros are no longer used by romInit.s.<br />

For assembly files only: the new macros GTEXT, GDATA, FUNC, and<br />

FUNC_LABEL have been added to assist in porting assembly files. The leading<br />

underscores in global assembly label names should be removed. Using these<br />

macros allows source compatibility between Tornado 2.0.2 and Tornado 2.2.<br />

For assembly files only: replace .align with .balign.<br />

The PC host utility mkboot now works with known VxWorks names, but may<br />

not work with user-provided names unless they are of type binary (*.bin). For<br />

all other images, there are two options:<br />

■<br />

■<br />

Rename your image to bootrom.dat before running mkboot.<br />

Modify mkboot.dat to support your names. Follow the examples given in<br />

the mkboot.bat file.<br />

Power management is enabled by default. To disable it, modify config.h:<br />

B<br />

#undef VX_POWER_MANAGEMENT<br />

217


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

■<br />

The default console is now set to COM1. In prior versions of VxWorks, x86<br />

targets set the default console to the VGA console. To use the VGA console,<br />

change config.h:<br />

■<br />

■<br />

■<br />

#define INCLUDE_PC_CONSOLE<br />

The configuration parameters for the IDE driver, ideDrv, have been removed<br />

in favor of the ATA driver, ataDrv, that is already used as the default<br />

configuration in Tornado 2.0.<br />

The CPUID structure (sysCpuId) has been updated to support Pentium III and<br />

Pentium 4 processors. sysCpuId.version, sysCpuId.vendor, and<br />

sysCpuId.feature are replaced respectively with sysCpuId.signature,<br />

sysCpuId.vendorId, and sysCpuId.featuresEdx.<br />

INT_VEC_GET( )/XXX_INT_VEC have been replaced with<br />

INT_NUM_GET( )/INT_NUM_XXX, respectively. Although older macros are<br />

available in this release for backward compatibility, they will be removed in<br />

the next release.<br />

■<br />

The routine sysCpuProbe( ) now understands Pentium III and Pentium 4<br />

processors.<br />

■<br />

The routine sysIntEoiGet( ) has been updated.<br />

■<br />

The local and IO APIC/xAPIC drivers, loApicIntr.c, ioApicIntr.c, and<br />

loApicTimer.c, now support the xAPIC in Pentium 4. The show routines for<br />

these drivers have been separated and contained in loApicIntrShow.c and<br />

ioApicIntrShow.c, respectively.<br />

For more information on using VxWorks with Pentium targets, see the VxWorks for<br />

Pentium Architecture Supplement.<br />

B.2.7 PowerPC<br />

In addition to the steps described in B.2.1 Migration Changes Common to All<br />

Architectures, p.214, the following PowerPC-specific changes are required to<br />

migrate your custom <strong>BSP</strong> to Tornado 2.2/VxWorks 5.5:<br />

■<br />

Use of the vxImmrGet( ) routine is deprecated. Existing <strong>BSP</strong>s implement this<br />

routine differently; some return the entire IMMR register, while others mask<br />

off the PARTNUM bits. <strong>BSP</strong>s’ existing behavior is unchanged.<br />

218


B<br />

Upgrading a <strong>BSP</strong> for Tornado 2.2<br />

■<br />

The preferred replacements for this routine are vxImmrIsbGet( ) and<br />

vxImmrDevGet( ), which are implemented in vxALib.s and should not be<br />

overridden by the <strong>BSP</strong>. Standard Wind River drivers use the new interface.<br />

Some early MPC74xx/AltiVec support included a routine, typically<br />

vmxExcLoad( ), to initialize the AltiVec exception vectors. For example:<br />

{<br />

bcopy ((char*)(LOCAL_MEM_LOCAL_ADRS + 0x0100),<br />

(char*)(LOCAL_MEM_LOCAL_ADRS + _EXC_VMX_UNAVAIL),<br />

SIZEOF_EXCEPTION);<br />

bcopy ((char*)(LOCAL_MEM_LOCAL_ADRS + 0x0100),<br />

(char*)(LOCAL_MEM_LOCAL_ADRS + _EXC_VMX_ASSIST),<br />

SIZEOF_EXCEPTION);<br />

}<br />

Such code must be removed. AltiVec exception vectors are initialized by<br />

altivecInit( ).<br />

The following change is optional for PowerPC <strong>BSP</strong>s:<br />

■<br />

Assembly files can be converted to use the Wind River standard macros<br />

defined in installDir/target/h/arch/ppc/toolsPpc.h:<br />

B<br />

FUNC_EXPORT<br />

FUNC_IMPORT<br />

_WRS_TEXT_SEG_START<br />

FUNC_BEGIN<br />

FUNC_LABEL<br />

FUNC_END<br />

Converting assembly files in this way is not generally required. However,<br />

conversion (especially to _WRS_TEXT_SEG_START) occasionally fixes a silent<br />

bug.<br />

For more information on using VxWorks with PowerPC targets, see the VxWorks<br />

for PowerPC Architecture Supplement.<br />

B.2.8 XScale/StrongARM<br />

NOTE: This section describes <strong>BSP</strong> migration from Tornado 2.1\VxWorks 5.4 to<br />

Tornado 2.2\VxWorks 5.5. For information on migrating a <strong>BSP</strong> from Tornado 2.0.x<br />

to Tornado 2.1, see the Tornado for StrongARM/XScale Release Notes and Architecture<br />

Supplement manual available on WindSurf.<br />

219


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

In addition to the steps described in B.2.1 Migration Changes Common to All<br />

Architectures, p.214, the following XScale/StrongARM-specific changes are<br />

required to migrate your custom <strong>BSP</strong> to Tornado 2.2/VxWorks 5.5:<br />

■<br />

For assembly files only: the new macros GTEXT, GDATA, FUNC, and<br />

FUNC_LABEL have been added to assist in porting assembly files. The leading<br />

underscores in global assembly label names should be removed. Using these<br />

macros allows source compatibility between Tornado 2.1.x and Tornado 2.2.<br />

■<br />

Diab support. Due to differences in assembler syntax between the GNU and<br />

Diab toolchains, you need to change any GNU assembly macros to Diab<br />

syntax. For more information on Diab assembly syntax, see the Diab C/C++<br />

Compiler for ARM User’s <strong>Guide</strong>.<br />

For more information on using VxWorks with XScale/StrongARM targets, see the<br />

VxWorks for Intel XScale/StrongARM Architecture Supplement.<br />

B.2.9 SuperH<br />

In addition to the steps described in B.2.1 Migration Changes Common to All<br />

Architectures, p.214, the following SuperH-specific changes are required to migrate<br />

your custom <strong>BSP</strong> to Tornado 2.2/VxWorks 5.5:<br />

■<br />

■<br />

■<br />

Power management setup. This step is required for <strong>BSP</strong>s where processor<br />

power management is enabled. In the sysHwInit( ) routine in sysLib.c.<br />

initialize the vxPowerModeRegs structure depending on the SuperH<br />

processor used.<br />

Diab support. This step is only required if the <strong>BSP</strong> will be built with the Diab<br />

toolchain. Assembler files should be updated to use the .short directive instead<br />

of the .word directive.<br />

Use of NULL. In previous releases, NULL was defined as integer zero. This<br />

definition has been changed to match the C standard to a void pointer. To<br />

avoid compiler warnings, make sure NULL is only used for pointer<br />

assignments.<br />

For more information on using VxWorks with SuperH targets, see the VxWorks for<br />

Hitachi SuperH Architecture Supplement.<br />

220


C<br />

Upgrading a <strong>BSP</strong> for the<br />

VxWorks Network Stack<br />

Adding your driver to the target VxWorks system is much like adding any other<br />

application. The first step is to compile and include the driver code in the VxWorks<br />

image. For a description of the general procedures, see the Tornado User’s <strong>Guide</strong>:<br />

Projects, which tells you how to compile source code to produce target-suitable<br />

object code.<br />

Including most software modules in the VxWorks image is usually just a matter of<br />

setting a few #define statements. Adding a network interface driver does not<br />

require much more. However, because VxWorks allows you to create more than<br />

one network device, you must also set up a table that groups the #define<br />

statements into device-specific groups. This table is defined in<br />

target/src/config/<strong>BSP</strong>/configNet.h, where <strong>BSP</strong> is the name of your board support<br />

package, such as mv162 and pc486.<br />

For example, if you wanted VxWorks to create two network devices, one that<br />

supported buffer loaning and one that did not, you would first edit configNet.h to<br />

include the following statements:<br />

/* Parameters for loading the driver supporting buffer loaning. */<br />

#define LOAD_FUNC_0 ln7990EndLoad<br />

#define LOAD_STRING_0 "0xfffffe0:0xffffffe2:0:1:1"<br />

#define <strong>BSP</strong>_0 NULL<br />

/* Parameters for loading the driver NOT supporting buffer loaning. */<br />

#define LOAD_FUNC_1 LOAD_FUNC_0<br />

#define LOAD_STRING_1 "0xffffee0:0xfffffee2:4:1:1"<br />

#define <strong>BSP</strong>_1 NULL<br />

221


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

To set appropriate values for these constants, consider the following:<br />

END_LOAD_FUNC<br />

Specify the name of your driver’s endLoad( ) entry point. For example, if your<br />

driver’s endLoad( ) entry point is ln7990EndLoad( ), you would edit config.h<br />

to include the line:<br />

#define END_LOAD_FUNC ln7990EndLoad<br />

END_LOAD_STRING<br />

Specify the initialization string passed into muxDevLoad( ) as the initString<br />

parameter.<br />

You must also edit the definition of endTbl (a table in configNet.h that specifies<br />

the ENDs included in the image) to include the following:<br />

END_TBL_ENTRY endTbl<br />

{<br />

{ 0, LOAD_FUNC_0, LOAD_STRING_0, <strong>BSP</strong>_0, FALSE},<br />

{ 1, LOAD_FUNC_1, LOAD_STRING_1, <strong>BSP</strong>_1, FALSE},<br />

{ 0, END_TBL_END, 0, NULL},<br />

};<br />

The first number in each table entry specifies the unit number for the device. The<br />

first entry in the example above specifies a unit number of 0. Thus, the device it<br />

loads is deviceName0. The FALSE at the end of each entry indicates that the entry<br />

has not been processed. After the system successfully loads a driver, it changes this<br />

value to TRUE in the run-time version of this table. To prevent the system from<br />

automatically loading your driver, set this value to TRUE.<br />

Finally, you must edit your <strong>BSP</strong>’s config.h file to define INCLUDE_END. This tells<br />

the build process to include the END/MUX interface. A this point, you are ready<br />

to rebuild VxWorks to include your new drivers. When you boot this rebuilt image,<br />

it calls muxDevLoad( ) for each device specified in the table in the order listed. 1<br />

1. For a description of the parameters to muxDevLoad( ), see the appropriate reference entry.<br />

222


D<br />

VxWorks Boot Sequence<br />

Table D-1 documents the sequence of initialization for a ROMmed VxWorks or<br />

boot ROM image. This sequence only applies to images built from the traditional<br />

command line.<br />

NOTE: You can expect, in a future release, that this old initialization sequence will<br />

be obsoleted in favor of project and component initialization groups.<br />

Images built from the project facility follow a different but similar initialization<br />

sequence based on initGroups described in the component description files. See<br />

E.3 Project Initialization Order, p.238 for the project component initialization order.<br />

Table D-1<br />

VxWorks Boot Sequence<br />

Functions Activity File<br />

1. romInit( ) (a) disable interrupts romInit.s<br />

(b)<br />

(c)<br />

save boot type (cold/warm)<br />

enable DRAM and DRAM refresh<br />

(hardware independent)<br />

(d) branch to romStart( )<br />

(position independent code)<br />

2. romStart( ) (a) copy text (and data) segment from ROM to<br />

RAM<br />

bootInit.c<br />

(b)<br />

(c)<br />

clear memory (if necessary)<br />

decompress (if necessary)<br />

223


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Table D-1<br />

VxWorks Boot Sequence (Continued)<br />

Functions Activity File<br />

(d)<br />

if (i960 CPU)<br />

invoke sysInitAlt(bootType)<br />

else<br />

invoke usrInit(bootType)<br />

3. sysInitAlt( )<br />

(i960 only)<br />

(a) invalidate caches, if any sysALib.s<br />

(b)<br />

(c)<br />

(d)<br />

(e)<br />

(f)<br />

initialize system interrupt tables with default<br />

stubs<br />

initialize system fault tables with default stubs<br />

initialize all processor registers to known<br />

default values<br />

enable tracing<br />

clear all pending interrupts<br />

(g) usrInit(bootType) usrConfig.c<br />

4. usrInit( ) (a) Verify correct data segment position. Infinite<br />

loop if not aligned correctly<br />

(b)<br />

(c)<br />

(d)<br />

(e)<br />

if (SPARC CPU)<br />

initialize register window management<br />

if (SYS_HW_INIT_0)<br />

execute SYS_HW_INIT_0 macro<br />

if (CACHE_SUPPORT)<br />

cacheLibInit( )<br />

if (MIPS CPU)<br />

sysGpInit( ), to initialize the global pointer<br />

usrConfig.c<br />

sysALib.s<br />

(f) zero bss (uninitialized data) usrConfig.c<br />

(g)<br />

save bootType in sysStartType<br />

(h) intVecBaseSet( ), to set vector base table lib/*.a<br />

(i)<br />

excVecInit( ), to initialize all system and<br />

default interrupt vectors<br />

lib/*.a<br />

224


D<br />

VxWorks Boot Sequence<br />

Table D-1<br />

VxWorks Boot Sequence (Continued)<br />

Functions Activity File<br />

(j)<br />

sysHwInit( ), to initialize board dependent<br />

hardware<br />

sysLib.c<br />

(k) usrKernelInit( ), to configure the wind kernel usrKernel.c<br />

(l)<br />

if (instruction cache)<br />

enable the instruction cache<br />

if (data cache)<br />

enable the data cache<br />

(m) kernelInit( ) lib/*.a<br />

5. kernelInit( ) Initialize and start the kernel. lib/*.a<br />

(a) intLockLevelSet( ) lib/*.a<br />

(b)<br />

(c)<br />

if (interrupt stack)<br />

create interrupt stack from beginning of memory<br />

pool<br />

create root stack and TCB from end of memory<br />

pool<br />

D<br />

(d) taskInit(tRootTask) lib/*.a<br />

(e) taskActivate(usrRoot) lib/*.a<br />

(f) usrRoot( ) usrConfig.c<br />

6. usrRoot( ) Initialize I/O system, install drivers, create devices,<br />

and set up network as configured in configAll.h and<br />

config.h.<br />

usrConfig.c<br />

(a)<br />

memInit( ) to initialize memory pool<br />

if (show routines)<br />

memShowInit( )<br />

if (virtual memory)<br />

usrMmuInit( )<br />

lib/*.a<br />

lib/*.a<br />

usrMmuInit.c<br />

(b) sysClkConnect( ) sysLib.c<br />

(c) sysClkRateSet( ) sysLib.c<br />

(d) sysClkEnable( ) sysLib.c<br />

(e) selectInit( )<br />

225


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Table D-1<br />

VxWorks Boot Sequence (Continued)<br />

Functions Activity File<br />

(f) iosInit( ) lib/*.a<br />

(g)<br />

(h)<br />

(i)<br />

if (INCLUDE_TTY_DEV)<br />

and (NUM_TTY)<br />

ttyDrv( )<br />

establish console port, standard input, standard<br />

output, standard error<br />

if (target symbol table)<br />

hashLibInit( ) and symLibInit( )<br />

if (LSTLIB)<br />

lstLibInit( )<br />

ttyDrv.c<br />

lib/*.a<br />

(j) initialize exception handling excInit( )<br />

if (logging)<br />

logInit( )<br />

if (signals)<br />

sigInit( )<br />

lib/*.a<br />

lib/*.a<br />

lib/*.a<br />

(k)<br />

(l)<br />

(m)<br />

(n)<br />

(o)<br />

(p)<br />

(q)<br />

if (native debugging)<br />

dbgInit( )<br />

if (pipes)<br />

pipeDrv( )<br />

if (standard I/O)<br />

stdioInit( )<br />

if (POSIX_SIGNALS)<br />

sigqueueInit( )<br />

if (POSIX semaphores)<br />

semPxLibInit( )<br />

if (show routines)<br />

semPxShowInit( )<br />

if (POSIX_THREADS)<br />

pthreadLibInit( )<br />

if (POSIX message queues)<br />

mqPxLibInit( )<br />

if (show routines)<br />

mqPxShowInit( )<br />

lib/*.a<br />

lib/*.a<br />

lib/*.a<br />

lib/*.a<br />

lib/*.a<br />

226


D<br />

VxWorks Boot Sequence<br />

Table D-1<br />

VxWorks Boot Sequence (Continued)<br />

Functions Activity File<br />

(r)<br />

(s)<br />

(t)<br />

(u)<br />

(v)<br />

(w)<br />

if (POSIX asynchronous I/O)<br />

aioPxLibInit( )<br />

if (show routines)<br />

aioPxShowInit( )<br />

if (CBIO)<br />

cbioLibInit( )<br />

if (DOS file system)<br />

dosFsInit( )<br />

if (raw file system)<br />

rawFsInit( )<br />

if (rt11 file system)<br />

rt11FsInit( )<br />

if (RAM disk)<br />

ramDrv( )<br />

lib/*.a<br />

lib/*.a<br />

lib/*.a<br />

lib/*.a<br />

lib/*.a<br />

(x)<br />

if (USB)<br />

usbInit( )<br />

D<br />

(y)<br />

(z)<br />

if (SCSI-2 support)<br />

scsi2IfInit( )<br />

else if (SCSI-1 support)<br />

scsi1IfInit( )<br />

sysScsiInit( )<br />

usrScsiConfig( )<br />

if (floppy disk support)<br />

fdDrv( )<br />

sysLib.c<br />

usrScsi.c<br />

sysScsi.c<br />

(aa) if (IDE disk support)<br />

ideDrv( )<br />

(ab) if (ATA driver support)<br />

ataDrv( )<br />

(ac)<br />

if (parallel printer support)<br />

lptDrv( )<br />

(ad) if (PCMCIA support)<br />

pcmciaInit( )<br />

227


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Table D-1<br />

VxWorks Boot Sequence (Continued)<br />

Functions Activity File<br />

(ae)<br />

(af)<br />

if (flash file system support)<br />

tffsDrv( )<br />

if (formatted I/O support)<br />

fioLibInit( )<br />

(ag) if (floating point support)<br />

floatInit( )<br />

(ah) if (software floating-point)<br />

mathSoftInit( )<br />

if (hardware floating-point)<br />

mathHardInit( )<br />

if (hardware floating-point and show routines)<br />

fppShowInit( )<br />

lib/*.a<br />

lib/*.a<br />

lib/*.a<br />

lib/*.a<br />

(ai)<br />

(aj)<br />

if (DSP)<br />

usrDspInit( )<br />

if (AltiVec)<br />

usrAltivecInit( )<br />

(ak) if (spy)<br />

spyStop( )<br />

lib/*.a<br />

(al)<br />

if (timex)<br />

timexInit( )<br />

lib/*.a<br />

(am) if (environment variables)<br />

envLibInit( )<br />

(an) if (loader)<br />

moduleLibInit( )<br />

(ao) if (a.out format)<br />

loadAoutInit( )<br />

else if (ecoff format)<br />

loadEcoffInit( )<br />

else if (coff format)<br />

loadCoffInit( )<br />

else if (ELF format)<br />

loadElfInit( )<br />

lib/*.a<br />

lib/*.a<br />

lib/*.a<br />

lib/*.a<br />

lib/*.a<br />

lib/*.a<br />

228


D<br />

VxWorks Boot Sequence<br />

Table D-1<br />

VxWorks Boot Sequence (Continued)<br />

Functions Activity File<br />

(ap) if (SYM_TBL_SYNC)<br />

symSyncLibInit( )<br />

(aq) if (network initialization)<br />

usrBootLineInit( )<br />

usrNetInit( )<br />

usrNetwork.c<br />

usrNetwork.c<br />

(ar)<br />

(as)<br />

(at)<br />

if (shared memory objects)<br />

usrSmObjInit( )<br />

if (VxFusion)<br />

usrVxFusionInit( )<br />

if (text protect and VxVMI)<br />

vmTextProtect( )<br />

usrSmObj.c<br />

lib/*.a<br />

(au) if (vector table protect and VxVMI)<br />

intVecTableWriteProtect( )<br />

(av) if (select)<br />

selTaskDeleteHookAdd( )<br />

(aw) if (symbol table)<br />

symTblCreate( )<br />

netLoadSymTbl( )<br />

(ax) if (C++)<br />

cplusCtorsLink( )<br />

cplusLibInit( )<br />

(ay) if (COM)<br />

comLibInit( )<br />

(az) if (DCOM)<br />

dcomLibInit( )<br />

(ba) if (http)<br />

httpd( )<br />

(bb) if (WindView)<br />

windviewConfig( )<br />

(bc) wdbConfig( ):<br />

confirm and initialize target agent<br />

lib/*.a<br />

lib/*.a<br />

lib/*.a<br />

usrLoadSym.c<br />

lib/*.a<br />

lib/*.a<br />

lib/*.a<br />

D<br />

229


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Table D-1<br />

VxWorks Boot Sequence (Continued)<br />

Functions Activity File<br />

(bd) if (shell)<br />

shellInit( )<br />

lib/*.a<br />

(be) if (WindML)<br />

usrWindMlInit( )<br />

(bf)<br />

if (Java)<br />

javaConfig( )<br />

lib/*.a<br />

(bg) if (HTML)<br />

usrHtmlInit( )<br />

(bh) if (USER_APPL)<br />

execute USER_APP_INIT macro<br />

lib/*.a<br />

sysLib.o<br />

230


E<br />

Component Language<br />

E.1 Component Description Language (CDL)<br />

This appendix provides a technical summary of the Component Description<br />

Language (CDL) used to describe a component to the project configuration tool.<br />

CDL uses a component description file (CDF) to describe one or more components.<br />

By convention, a CDF has the file extension .cdf. This appendix provides the<br />

syntax for each of the five CDL objects types; for additional information, see<br />

6.2.2 CDL Object Types, p.115.<br />

Properties essentially define their objects, and, more broadly, the associated<br />

component. In this appendix, if a property does not specify that it has a default<br />

value, none exists.<br />

The appendix also includes the default folder hierarchy for Tornado 2.x, as well as<br />

the default initialization group ordering. The folder hierarchy determines where a<br />

component appears in the project facility’s hierarchy of components. Sequencing<br />

by initialization group determines the order in which a component is initialized<br />

during system startup.<br />

231


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

E.1.1 Component Properties<br />

Component component { // required for all components<br />

NAME name // readable name (e.g., "foo manager").<br />

// should be in all lower case.<br />

SYNOPSIS desc // one-line description<br />

MODULES m1 m2 .. // object modules making up the service.<br />

// used to generate dependency<br />

// information.<br />

// it is important to keep this list<br />

// small,since the tool’s dependency<br />

// engine assumes that the component is<br />

// included if *any* of the modules are<br />

// dragged in by dependency. It may make<br />

// sense to split a large number of<br />

// modules into several distinct<br />

// components.<br />

CONFIGLETTES 1 s2 .. // source files in the component that are<br />

// #included in the master configuration<br />

// file.<br />

// file paths are assumed to be relative<br />

// to $(WIND_BASE)/target/config/comps/src<br />

<strong>BSP</strong>_STUBS s1 s2 .. // source file stubs that should be copied<br />

// into the <strong>BSP</strong> and customized for the<br />

// component to work.<br />

// file paths are assumed to be relative<br />

// to $(WIND_BASE)/target/config/comps/src<br />

// (<strong>BSP</strong>_STUBS are supported for Tornado 2.2<br />

// only; they are not supported in earlier<br />

// Tornado 2.x releases)<br />

HDR_FILES h1 h1 .. // header files that need to be included<br />

// to use this component. Typically<br />

// contains prototypes for the<br />

// initialization routine.<br />

CFG_PARAMS p1 p2 .. // configuration parameters, typically<br />

// macros defined in config[All].h, that<br />

// can change the way a component works.<br />

// see Parameters, below, for more info.<br />

INIT_RTN init(..) // one-line initialization routine.<br />

// if it needs to be more than one line,<br />

// put the code in a CONFIGLETTE.<br />

LINK_SYMS s1 s2 .. // reference these symbols in order to drag<br />

// in the component from the archive.<br />

// this tells the code generator how to<br />

// drag in components that don’t need to<br />

// be initialized.<br />

232


E<br />

Component Language<br />

REQUIRES r1 r2 .. // other components required. Note:<br />

// dependencies are automatically calculated<br />

// based on a components MODULES and<br />

// LINK_SYMS. For example, because nfsLib.o<br />

// calls rpcLib.o, the tool is able to<br />

// figure out that INCLUDE_NFS requires<br />

// INCLUDE_RPC. One only needs to list<br />

// requirements that cannot be detected from<br />

// MODULE dependencies. Typically only needed<br />

// for components that don’t have associated<br />

// MODULES (e.g., ones with just<br />

// configlettes).<br />

EXCLUDES e1 e1 .. // other components that cannot<br />

// coexist with this component<br />

HELP h1 h2 .. // reference pages associated with the<br />

// component.<br />

// The default is the MODULES and INIT_RTN<br />

// of the component. For example, if the<br />

// component has MODULE fooLib.o, then the<br />

// manual page for fooLib is automatically<br />

// associated with the component (if the<br />

// manual page exists). Similary for the<br />

// components INIT_RTN. If there are any<br />

// other relevant manual pages, they can<br />

// be specified here.<br />

MACRO_NEST expr // This is for Wind River internal use only.<br />

// It is used to tell the bsp2prj script<br />

// how to create a project corresponding<br />

// to a given <strong>BSP</strong>.<br />

// The "bsp2prj" script assumes that if<br />

// a <strong>BSP</strong> has macro INCLUDE_FOO defined,<br />

// the corresponding component INCLUDE_FOO<br />

// should be included in the project.<br />

// That is not always the case. For example,<br />

// The INCLUDE_AOUT component should only<br />

// be included if both INCLUDE_AOUT *and*<br />

// INCLUDE_LOADER are defined.<br />

// So for the INCLUDE_AOUT component, we set<br />

// MACRO_NEST = INCLUDE_LOADER.<br />

// SImilarly all WDB subcomponents have<br />

// MACRO_NEST = INCLUDE_WDB.<br />

E<br />

ARCHIVE a1 // archive in which to find the MODULES.<br />

// default is lib$(CPU)$(TOOL)vx.a.<br />

// file path is assumed to be relative<br />

// to $(WIND_BASE)/target/lib.<br />

// any archive listed here is<br />

// automatically added to the VxWorks<br />

// link-line when the component is<br />

// included.<br />

// Note: the tool only analyzes archives<br />

// associated with included components.<br />

233


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

// This creates a chicken-and-egg problem,<br />

// because the tool analyzes components<br />

// before they are actually added.<br />

// So if you add a component with an ARCHIVE,<br />

// analysis will be done without the ARCHIVE.<br />

// As a work-around, if a separate archive is<br />

// used, create a dummy component that<br />

// lets the tool know that a new archive<br />

// should be read. Such a component<br />

// should be called INSTALL_something.<br />

// It should contain only NAME, SYNOPSIS,<br />

// and ARCHIVE attributes. Only after the<br />

// user adds it can he or she add other<br />

// components from the archive.<br />

INCLUDE_WHEN c1 c2 .. // automatically include this component<br />

// when some other components are included.<br />

// All listed components must be included to<br />

// activate the INCLUDE_WHEN (AND<br />

// relationship). This allows, for example,<br />

// msgQShow to be included whenever msgQ and<br />

// show are included. Similarly, WDB fpp<br />

// support can be included when WDB and fpp<br />

// are included.<br />

INIT_BEFORE c1 // if component c1 is present, our init<br />

// routine must be called before c1.<br />

// Only needed for component releases.<br />

_CHILDREN fname // Component is a child of folder or<br />

// selection fname.<br />

_INIT_ORDER gname // Component is a member of init group gname<br />

// and is added to the end of the<br />

// initialization sequence by default (see<br />

// INIT_BEFORE).<br />

}<br />

E.1.2 Parameter Properties<br />

Parameter parameter {<br />

NAME name // readable name (e.g., "max open files")<br />

SYNOPSIS desc // one-line description.<br />

STORAGE storage // MACRO, REGISTRY, ... Default is MACRO.<br />

TYPE type // type of parameter:<br />

// int, uint, bool, string, exists.<br />

// Default is untyped.<br />

// more types will be added later.<br />

DEFAULT value // default value of the parameter.<br />

234


E<br />

Component Language<br />

}<br />

// default is none - in which case the user<br />

// must define a value to use the component.<br />

// for parameters of type "exists," the<br />

// value is TRUE if the macro should be<br />

// defined, or FALSE if undefined.<br />

E.1.3 Folder Properties<br />

The project facility component hierarchy uses folders to group components<br />

logically. Instead of presenting all components in a flat list, as in configAll.h, the<br />

project facility presents them hierarchically. For example, top-level folders might<br />

organize components under headings such as network, drivers, OS, and<br />

application.<br />

Folder folder {<br />

NAME name // readable name (e.g., "foo libraries").<br />

SYNOPSIS desc // one-line description<br />

CHILDREN i1 i2 .. // containers and components<br />

// that belong to this container.<br />

}<br />

DEFAULTS i1 i2 .. // default CHILDREN.<br />

// if the folder represents a complex<br />

// subsystem (such as the WDB agent),<br />

// this is used to suggest to the user<br />

// which components in the folder are<br />

// considered "default." That way the user<br />

// can add the whole subsystem at once,<br />

// and a reasonable set of subcomponents<br />

// will be chosen.<br />

E<br />

E.1.4 Selection Properties<br />

Selection selection {<br />

NAME name // readable name (for example , "foo<br />

// communication path")<br />

SYNOPSIS desc // one-line description<br />

COUNT min-max // range of allowed subcomponents.<br />

// 1-1 means exactly one.<br />

// 1- means one or more.<br />

CHILDREN i1 i2 .. // components from which to select<br />

DEFAULTS i1 i2 .. // default CHILDREN.<br />

235


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

}<br />

// this is not used for anything except to<br />

// to suggest to the user which components<br />

// in the selection we consider "default."<br />

E.1.5 InitGroup Properties<br />

InitGroup group {<br />

INIT_RTN rtn(..) // initialization routine definition<br />

INIT_ORDER i1 i2 .. // ordered list of init groups and<br />

// components that belong to this init group<br />

}<br />

INIT_AFTER i2 i2 .. // Only needed for component releases.<br />

E.2 Folder Hierarchy<br />

The following hierarchy is the default folder directory for Tornado 2.x and should<br />

be referred to only in the context of Tornado 2.x development.<br />

NOTE: Do not presume that future releases will preserve the names or nature of<br />

any folders included in the Tornado 2.x folder hierarchy, except FOLDER_ROOT.<br />

FOLDER_ROOT<br />

{// all components<br />

FOLDER_APPLICATION // user application component(s)<br />

FOLDER_TOOLS // Development Tools<br />

{<br />

FOLDER_WDB // WDB agent components<br />

{<br />

FOLDER_WDB_OPTIONS // optional WDB agent services<br />

}<br />

FOLDER_SHELL // Target shell components<br />

FOLDER_LOADER // OMF loader components<br />

FOLDER_SYMTBL // symbol table components<br />

{<br />

FOLDER_SYM_TBL_INIT // Symbol table initialization<br />

}<br />

FOLDER_SHOW_ROUTINES // Kernel show routine components<br />

236


E<br />

Component Language<br />

FOLDER_WINDVIEW // WindView components<br />

}<br />

FOLDER_NETWORK // Network components<br />

{<br />

FOLDER_CORE_COMPONENTS // basic network initialization options<br />

{<br />

FOLDER_BOOTLINE_SETUP // network init from bootline<br />

}<br />

FOLDER_NET_DEV // Support for network device types<br />

{<br />

FOLDER_SMNET_COMPONENTS // Shared memory component<br />

FOLDER_BSD_NET_DRV // BSD Ethernet drivers<br />

}<br />

FOLDER_NET_PROTOCOLS // networking protocols<br />

{<br />

FOLDER_NET_FS // Network file systems<br />

{<br />

FOLDER_NET_REM_IO // Network remote I/O components<br />

}<br />

FOLDER_NET_APP // Network applications<br />

{<br />

FOLDER_MIB2 // MIB2 application<br />

FOLDER_STREAMS // Streams application<br />

}<br />

FOLDER_NET_API // Networking APIs<br />

FOLDER_NET_ROUTE // Network routing protocols<br />

FOLDER_NET_DEBUG // Network show routines<br />

FOLDER_TCP_IP // Core TCP/IP components<br />

{<br />

FOLDER_TCPIP_CONFIG // TCP/IP configuration components<br />

}<br />

}<br />

}<br />

FOLDER_CPLUS // C++ class libraries<br />

{<br />

FOLDER_CPLUS_STDLIB // C++ Standard Library<br />

FOLDER_CPLUS_WFC // Wind Foundation Classes<br />

}<br />

FOLDER_OS // Operating system components<br />

{<br />

FOLDER_IO_SYSTEM // IO system components<br />

FOLDER_KERNEL // kernel components<br />

E<br />

237


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

FOLDER_ANSI // ANSI libraries<br />

FOLDER_POSIX // POSIX components<br />

FOLDER_UTILITIES // Utility components<br />

}<br />

FOLDER_OBSOLETE // Obsolete components<br />

FOLDER_HARDWARE // Hardware components<br />

{<br />

FOLDER_MEMORY // Memory components<br />

{<br />

FOLDER_MMU // MMU options<br />

}<br />

FOLDER_BUSES // Bus components<br />

{<br />

FOLDER_SCSI // SCSI components<br />

}<br />

FOLDER_PERIPHERALS // Peripheral components<br />

{<br />

FOLDER_HD // Hard Disk components<br />

FOLDER_CLOCK // System and Aux Clock component<br />

FOLDER_SERIAL // SIO driver support<br />

FOLDER_FPP // Floating Point libraries<br />

}<br />

FOLDER_<strong>BSP</strong>_CONFIG // <strong>BSP</strong> configuration components<br />

}<br />

FOLDER_GRAPHICS // Graphic components<br />

{<br />

FOLDER_UGL // Optional product<br />

FOLDER_HTML // Optional product<br />

}<br />

}<br />

E.3 Project Initialization Order<br />

Images built from a project are initialized according to initialization groups or init<br />

groups. Through the CDF, a component can declare that it belongs to a named<br />

238


E<br />

Component Language<br />

initialization group. It can also declare that it should be initialized before or after<br />

other components within that group.<br />

The two primary initGroups for project compilation are usrInit and usrRoot. Each<br />

initialization group translates to a C function declaration where the body of the<br />

function is the initialization code from each of the constituent components.<br />

In the initialization sequences that follow, names appearing all in uppercase are<br />

component names. Names appearing in all lowercase are routine names. Each<br />

initialization group has a routine with the same name as the initialization group.<br />

Indentation is used in this chart to represent the hierarchy of the standard<br />

components as defined by Tornado 2.x. When the prjConfig.c file is generated,<br />

each included component is replaced by its initialization code fragment, as defined<br />

in the CDF for that component. Excluded components do not contribute code<br />

fragments to their initialization group.<br />

NOTE: The project facility build process does not apply to boot ROMs. Boot ROMs<br />

for Tornado 2.x can only be built from the traditional command line.<br />

E.3.1 romInit.s<br />

Only used for ROMmed VxWorks images, this assembly code initializes the<br />

processor and memory. This code always ends by calling romStart( ).<br />

E<br />

E.3.2 romStart.c<br />

Only used for ROMmed VxWorks images, this code relocates text and data from<br />

within the ROM itself into RAM. It terminates by calling the routine located at<br />

RAM_DST_ADRS. This is normally the address of usrEntry( ).<br />

E.3.3 usrEntry.c<br />

Only used for ROMmed VxWorks images, this routine does some<br />

architecture-specific initialization and terminates by calling usrInit( ) in<br />

prjConfig.c.<br />

239


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

E.3.4 sysALib.s<br />

For downloaded images only, execution begins with sysInit( ), instead of<br />

romInit( ), romStart( ), and usrEntry( ). This routine should repeat all the<br />

processor and hardware initialization done by romInit( ), except for main memory.<br />

This routine terminates by calling usrInit( ) in prjConfig.c.<br />

E.3.5 prjConfig.c<br />

NOTE: Do not presume that future releases will preserve the names or nature of<br />

any initGroups included in Tornado 2.x, except usrInit and usrRoot.<br />

usrInit<br />

{// pre-multitasking init group<br />

INCLUDE_SYS_START<br />

INCLUDE_CACHE_SUPPORT<br />

INCLUDE_EXC_HANDLING<br />

INCLUDE_SYSHW_INIT<br />

INCLUDE_CACHE_ENABLE<br />

INCLUDE_WINDVIEW_CLASS<br />

INCLUDE_KERNEL // DO NOT REMOVE.<br />

} // end of usrInit<br />

The required element INCLUDE_KERNEL must always be the last component<br />

initialized in usrInit( ). It starts multitasking by creating the root task and<br />

scheduling it to execute the routine usrRoot( ).<br />

usrRoot<br />

{// post-multitasking init group<br />

usrKernelCoreInit<br />

{// kernel core features init group<br />

INCLUDE_SEM_BINARY<br />

INCLUDE_SEM_MUTEX<br />

INCLUDE_SEM_COUNTING<br />

INCLUDE_MSG_Q<br />

INCLUDE_WATCHDOGS<br />

INCLUDE_TASK_HOOKS<br />

} // end of usrKernelCoreInit<br />

INCLUDE_MEM_MGR_BASIC<br />

INCLUDE_MEM_MGR_FULL<br />

240


E<br />

Component Language<br />

INCLUDE_MMU_BASIC<br />

INCLUDE_MMU_FULL<br />

INCLUDE_SYSCLK_INIT // makes indirect call to sysHwInit2.<br />

usrIosCoreInit<br />

{// I/O system core init group<br />

INCLUDE_HW_FP<br />

INCLUDE_SW_FP<br />

INCLUDE_BOOT_LINE_INIT<br />

INCLUDE_TTY_DEV<br />

INCLUDE_TYCODRV_5_2<br />

INCLUDE_SIO<br />

INCLUDE_PC_CONSOLE<br />

} // end of usrIosCoreInit<br />

usrKernelExtraInit<br />

{// kernel extra features init group<br />

INCLUDE_HASH<br />

INCLUDE_SYM_TBL<br />

INCLUDE_ENV_VARS<br />

INCLUDE_SIGNALS<br />

INCLUDE_POSIX_AIO<br />

INCLUDE_POSIX_AIO_SYSDRV<br />

INCLUDE_POSIX_MQ<br />

INCLUDE_POSIX_MEM<br />

INCLUDE_POSIX_SIGNALS<br />

INCLUDE_SM_OBJ<br />

INCLUDE_PROTECT_TEXT<br />

INCLUDE_PROTECT_VEC_TABLE<br />

usrIosExtraInit<br />

{// I/O system extras init group<br />

INCLUDE_EXC_TASK<br />

INCLUDE_LOGGING<br />

INCLUDE_PIPES<br />

INCLUDE_STDIO<br />

INCLUDE_DOSFS<br />

INCLUDE_RAWFS<br />

INCLUDE_RT11FS<br />

INCLUDE_RAMDRV<br />

INCLUDE_SCSI<br />

INCLUDE_FD<br />

INCLUDE_IDE<br />

INCLUDE_ATA<br />

E<br />

241


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

INCLUDE_LPT<br />

INCLUDE_PCMCIA<br />

INCLUDE_TFFS<br />

INCLUDE_FORMATTED_IO<br />

INCLUDE_FLOATING_POINT<br />

} // end of usrIosExtraInit<br />

} // end of usrKernelExtraInit<br />

usrNetworkInit<br />

{// network system init group<br />

INCLUDE_NET_SETUP<br />

usrNetProtoInit<br />

{// Network Protocol initializations<br />

INCLUDE_BSD_SOCKET<br />

INCLUDE_ZBUF_SOCK<br />

BSD43_COMPATIBLE<br />

INCLUDE_ROUTE_SOCK<br />

INCLUDE_HOST_TBL<br />

INCLUDE_IP<br />

INCLUDE_IP_FILTER<br />

INCLUDE_UDP<br />

INCLUDE_UDP_SHOW<br />

INCLUDE_TCP<br />

INCLUDE_TCP_SHOW<br />

INCLUDE_ICMP<br />

INCLUDE_ICMP_SHOW<br />

INCLUDE_IGMP<br />

INCLUDE_IGMP_SHOW<br />

INCLUDE_SM_NET_SHOW<br />

INCLUDE_MCAST_ROUTING<br />

INCLUDE_OSPF<br />

INCLUDE_NET_LIB<br />

INCLUDE_TCP_DEBUG<br />

INCLUDE_ARP_API<br />

INCLUDE_NET_SHOW<br />

}// end of usrNetProtoInit<br />

INCLUDE_MUX<br />

INCLUDE_END<br />

INCLUDE_PPP<br />

INCLUDE_PPP_CRYPT<br />

INCLUDE_SLIP<br />

242


E<br />

Component Language<br />

INCLUDE_NETWORK<br />

usrNetworkBoot<br />

{// configure the network boot device, if specified<br />

INCLUDE_NET_INIT<br />

usrNetworkAddrInit<br />

{// get a network address<br />

INCLUDE_DHCPC_LEASE_GET<br />

INCLUDE_DHCPC_LEASE_CLEAN<br />

}// end of usrNetworkAddrInit<br />

INCLUDE_PPP_BOOT<br />

INCLUDE_SLIP_BOOT<br />

INCLUDE_NETMASK_GET<br />

INCLUDE_NETDEV_NAMEGET<br />

INCLUDE_SM_NET_ADDRGET<br />

usrNetworkDevStart<br />

{// attach and configure the network device(s)<br />

INCLUDE_SM_NET<br />

INCLUDE_END_BOOT<br />

INCLUDE_BSD_BOOT<br />

INCLUDE_LOOPBACK<br />

}// end of usrNetworkDevStart<br />

INCLUDE_SECOND_SMNET<br />

}// end of usrNetworkBoot<br />

usrNetworkAddrCheck<br />

{// verify IP address<br />

INCLUDE_DHCPC<br />

INCLUDE_DHCPC_LEASE_TEST<br />

}// end of usrNetworkAddrCheck<br />

usrNetRemoteInit<br />

{// network remote I/O access<br />

INCLUDE_NET_HOST_SETUP<br />

INCLUDE_NET_REM_IO<br />

INCLUDE_NFS<br />

INCLUDE_NFS_MOUNT_ALL<br />

}// end of usrNetRemoteInit<br />

usrNetAppInit<br />

{// start network applications<br />

INCLUDE_RPC<br />

INCLUDE_RLOGIN<br />

E<br />

243


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

INCLUDE_TELNET<br />

INCLUDE_SECURITY<br />

INCLUDE_TFTP_SERVER<br />

INCLUDE_FTP_SERVER<br />

INCLUDE_FTPD_SECURITY<br />

INCLUDE_NFS_SERVER<br />

INCLUDE_DHCPC_SHOW<br />

INCLUDE_DHCPR<br />

INCLUDE_DHCPS<br />

INCLUDE_SNTPC<br />

INCLUDE_SNTPS<br />

INCLUDE_PING<br />

INCLUDE_RIP<br />

INCLUDE_DNS_RESOLVER<br />

INCLUDE_SNMPD<br />

INCLUDE_MIB2_ALL<br />

INCLUDE_STREAMS<br />

INCLUDE_STREAMS_ALL<br />

INCLUDE_STREAMS_AUTOPUSH<br />

INCLUDE_STREAMS_DEBUG<br />

INCLUDE_STREAMS_DLPI<br />

INCLUDE_STREAMS_SOCKET<br />

INCLUDE_STREAMS_STRACE<br />

INCLUDE_STREAMS_STRERR<br />

INCLUDE_STREAMS_TLI<br />

}// end of usrNetAppInit<br />

} // end of usrNetworkInit<br />

INCLUDE_SELECT<br />

usrToolsInit<br />

{// user tools init group<br />

INCLUDE_SPY<br />

INCLUDE_TIMEX<br />

INCLUDE_MODULE_MANAGER<br />

INCLUDE_LOADER<br />

INCLUDE_NET_SYM_TBL<br />

INCLUDE_STANDALONE_SYM_TBL<br />

INCLUDE_STAT_SYM_TBL<br />

INCLUDE_TRIGGERING<br />

usrWdbInit<br />

{// WDB init group<br />

INCLUDE_WDB<br />

244


E<br />

Component Language<br />

INCLUDE_WDB_MEM<br />

INCLUDE_WDB_SYS<br />

INCLUDE_WDB_TASK<br />

INCLUDE_WDB_EVENTS<br />

INCLUDE_WDB_EVENTPOINTS<br />

INCLUDE_WDB_DIRECT_CALL<br />

INCLUDE_WDB_CTXT<br />

INCLUDE_WDB_REG<br />

INCLUDE_WDB_GOPHER<br />

INCLUDE_WDB_EXIT_NOTIFY<br />

INCLUDE_WDB_EXC_NOTIFY<br />

INCLUDE_WDB_FUNC_CAL<br />

INCLUDE_WDB_VIO_LIB<br />

INCLUDE_WDB_VIO<br />

INCLUDE_WDB_BP<br />

INCLUDE_WDB_TASK_BP<br />

INCLUDE_WDB_START_NOTIFY<br />

INCLUDE_WDB_USER_EVENT<br />

INCLUDE_WDB_HW_FP<br />

INCLUDE_WDB_TASK_HW_FP<br />

INCLUDE_WDB_SYS_HW_FP<br />

INCLUDE_WDB_BANNER<br />

INCLUDE_SYM_TBL_SYNC<br />

} // end of usrWdbInit<br />

usrShellInit<br />

{// target shell init group<br />

INCLUDE_DEBUG // brkpts and stack tracer on target<br />

INCLUDE_SHELL_BANNER // display the Wind River banner on startup<br />

INCLUDE_STARTUP_SCRIPT<br />

INCLUDE_SHELL<br />

}// end of usrShellInit<br />

usrWindviewInit<br />

{// WindView init group<br />

INCLUDE_WINDVIEW<br />

INCLUDE_SYS_TIMESTAMP<br />

INCLUDE_USER_TIMESTAMP<br />

INCLUDE_SEQ_TIMESTAMP<br />

INCLUDE_RBUFF<br />

INCLUDE_WV_BUFF_USER<br />

INCLUDE_WDB_TSFS<br />

INCLUDE_WVUPLOAD_SOCK<br />

E<br />

245


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

INCLUDE_WVUPLOAD_TSFSSOCK<br />

INCLUDE_WVUPLOAD_FILE<br />

} // end of usrWindviewInit<br />

usrShowInit<br />

{// show routines init group<br />

INCLUDE_TASK_SHOW<br />

INCLUDE_CLASS_SHOW<br />

INCLUDE_MEM_SHOW<br />

INCLUDE_TASK_HOOKS_SHOW<br />

INCLUDE_SEM_SHOW<br />

INCLUDE_MSG_Q_SHOW<br />

INCLUDE_WATCHDOGS_SHOW<br />

INCLUDE_SYM_TBL_SHOW<br />

INCLUDE_MMU_FULL_SHOW<br />

INCLUDE_POSIX_MQ_SHOW<br />

INCLUDE_POSIX_SEM_SHOW<br />

INCLUDE_HW_FP_SHOW<br />

INCLUDE_ATA_SHOW<br />

INCLUDE_TRIGGER_SHOW<br />

INCLUDE_RBUFF_SHOW<br />

INCLUDE_STDIO_SHOW<br />

} // end of usrShowInit<br />

}// end of usrToolsInit<br />

INCLUDE_CPLUS<br />

INCLUDE_CPLUS_DEMANGLER<br />

INCLUDE_HTTP<br />

INCLUDE_USER_APPL // start user application<br />

} // end of usrRoot<br />

246


F<br />

Generic Drivers<br />

F.1 Introduction<br />

This appendix provides guidelines for writing generic drivers for the handful of<br />

devices that are common to most <strong>BSP</strong>s. Although <strong>BSP</strong>s can differ considerably in<br />

detail, there are some needs that are common to almost all. For example, most <strong>BSP</strong>s<br />

require a serial device driver or a timer driver. Ideally, the drivers for these devices<br />

would be generic enough to port to a new <strong>BSP</strong> with a simple recompilation. This<br />

reuse of code reduces your maintenance overhead and lets you focus your testing<br />

efforts, which results in better tested code. For example, using generic drivers let<br />

Wind River save 500 lines of C source code in three similar <strong>BSP</strong>s. 1<br />

To help you use generic drivers across multiple similar <strong>BSP</strong>s, the <strong>BSP</strong> kit includes<br />

source for generic drivers in the target/src/drv directory. At compile time, sysLib.c<br />

(a file duplicated in every <strong>BSP</strong>) can include generic drivers from the target/src/drv<br />

directory as needed. As you develop drivers for your <strong>BSP</strong>s, you should strive to<br />

create drivers that are generic enough to service multiple <strong>BSP</strong>s. You can add such<br />

drivers to those in the target/src/drv directory.<br />

However, when dealing with atypical hardware or legacy code, it might not be<br />

practical to use a generic driver. Some hardware designs are just too different to<br />

work with a generic driver. In the case of legacy code, it might be possible to use a<br />

generic driver. Unfortunately, reworking the <strong>BSP</strong> to use a generic driver might not<br />

be worth the effort, especially if you are just upgrading the <strong>BSP</strong> to a new release of<br />

VxWorks. In either case, you must create or maintain a <strong>BSP</strong>-specific driver. Such a<br />

1. VxWorks network and SCSI device drivers (distributed in object form) are not discussed<br />

here, but are covered in other appendices in this manual.<br />

247


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

driver would not reside in the target/src/drv directory but in a <strong>BSP</strong>-specific<br />

directory (from which the <strong>BSP</strong>’s sysLib.c can include the driver when needed).<br />

F.2 Serial Drivers<br />

Generic serial drivers reside in the directory target/src/drv/serial. Included in this<br />

directory is templateSerial.c and its corresponding header file, templateSerial.h.<br />

These files contain very detailed information on the design and construction of a<br />

typical serial driver. When writing a serial driver, base the driver on this template,<br />

then modify the <strong>BSP</strong>’s sysLib.c or sysSerial.c files to include the driver as needed.<br />

NOTE: Serial drivers are provided for backward compatibility with VxWorks 5.2<br />

and earlier. All Tornado-era <strong>BSP</strong>s should instead use the SIO drivers.<br />

To manage information about a serial device, sysLib.c uses a device descriptor.<br />

This device descriptor also encapsulates board-specific information. For example,<br />

it typically includes the frequency of the clock and the addresses of the registers,<br />

although the details are dictated by the device in question. In sysLib.c, the serial<br />

device descriptor is declared outside the function definitions as:<br />

TY_CO_DEV tyCoDv [NUM_TTY]; /* structure for serial ports */<br />

This array is initialized at run-time in sysHwInit( ). The TY_CO_DEV structure is<br />

defined in the device header file (for example, target/h/drv/serial/z8530.h). The<br />

following members of the TY_CO_DEV structure are common to all serial drivers:<br />

tyDev<br />

Required by tyLib, the VxWorks tty driver support library.<br />

created<br />

A flag that must be initialized to FALSE in sysHwInit( ).<br />

numChannels<br />

Used for parameter checking.<br />

The following macros must be defined for all <strong>BSP</strong>s:<br />

NUM_TTY<br />

Defines the number of serial channels supported. In configAll.h, the default<br />

defined as 2. To override the default, first undefine then define NUM_TTY in<br />

config.h. If there are no serial channels, define NUM_TTY as NONE.<br />

248


F<br />

Generic Drivers<br />

CONSOLE_TTY<br />

This macro defines the channel number of the console. In configAll.h, the<br />

default defined as 0. To override the default, first undefine then define<br />

CONSOLE_TTY in config.h.<br />

F.3 Multi-Mode Serial (SIO) Drivers<br />

The generic multi-mode serial drivers reside in the directory target/src/drv/sio.<br />

These drivers are called SIO drivers to distinguish them from the older serial<br />

drivers that only have a single interrupt mode of operation.<br />

SIO drivers provide an interface for setting hardware options, such as the number<br />

of stop bits, data bits, parity, and so on. In addition, these drivers provide an<br />

interface for polled communication that can provide external mode debugging<br />

(such as ROM-monitor style debugging) over a serial line. Currently only<br />

asynchronous-mode SIO drivers are supported.<br />

Every SIO device is controlled by an SIO_CHAN structure. This structure contains<br />

a single member, a pointer to an SIO_DRV_FUNCS structure. These structures are<br />

defined in target/h/sioLib.h as:<br />

typedef struct sio_chan /* a serial channel */<br />

{<br />

SIO_DRV_FUNCS * pDrvFuncs;<br />

/* device data */<br />

} SIO_CHAN;<br />

F<br />

typedef struct sio_drv_funcs SIO_DRV_FUNCS;<br />

struct sio_drv_funcs /* driver functions */<br />

{<br />

int (*ioctl)<br />

(<br />

SIO_CHAN * pSioChan,<br />

int<br />

cmd,<br />

void *<br />

arg<br />

);<br />

int (*txStartup)<br />

(<br />

SIO_CHAN *<br />

);<br />

pSioChan<br />

int (*callbackInstall)<br />

(<br />

249


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

int (*pollInput)<br />

int (*pollOutput)<br />

};<br />

SIO_CHAN *<br />

int<br />

STATUS<br />

void *<br />

);<br />

(<br />

SIO_CHAN *<br />

char *<br />

(<br />

SIO_CHAN *<br />

char outChar<br />

);<br />

pSioChan,<br />

callbackType,<br />

(*callback)(),<br />

callbackArg<br />

pSioChan,<br />

inChar);<br />

pSioChan,<br />

The members of the SIO_DRV_FUNCS structure function as follows:<br />

ioctl<br />

Points to the standard I/O control interface function for the driver. This<br />

function provides the primary control interface for any driver. To access the<br />

I/O control services for a standard SIO device, use the following symbolic<br />

constants:<br />

SIO_BAUD_SET<br />

SIO_BAUD_GET<br />

SIO_HW_OPTS_SET<br />

SIO_HW_OPTS_GET<br />

SIO_MODE_SET<br />

SIO_MODE_GET<br />

SIO_AVAIL_MODES_GET<br />

SIO_OPEN<br />

SIO_HUP<br />

Set a new baud rate.<br />

Get the current baud rate.<br />

Set new hardware settings.<br />

Get current hardware settings.<br />

Set a new operating mode.<br />

Get the current mode.<br />

Get available modes.<br />

Open a channel.<br />

Close a channel.<br />

txStartup<br />

Provides a pointer to the function that the system calls when new data is<br />

available for transmission. Typically, this routine is called only from the<br />

ttyDrv.o module. This module provides a higher level of functionality that<br />

makes a raw serial channel behave with line control and canonical character<br />

processing).<br />

callbackInstall<br />

Provides the driver with pointers to callback functions that the driver can call<br />

asynchronously to handle character puts and gets. The driver is responsible for<br />

saving the callback routines and arguments that it receives from the<br />

callbackInstall( ) function.The available callbacks are<br />

SIO_CALLBACK_GET_TX_CHAR and SIO_CALLBACK_PUT_RCV_CHAR.<br />

250


F<br />

Generic Drivers<br />

Define SIO_CALLBACK_GET_TX_CHAR to point to a function that fetches a<br />

new character for output. The driver calls this callback routine with the<br />

supplied argument and an additional argument that is the address to receive<br />

the new output character if any. The called function returns OK to indicate that<br />

a character was delivered, or ERROR to indicate that no more characters are<br />

available.<br />

Define SIO_CALLBACK_PUT_RCV_CHAR to point to a function the driver can<br />

use to send characters upward. For each incoming character, the callback<br />

routine is called with the supplied argument, and the new character as a<br />

second argument. Drivers normally do not care about the return value from<br />

this call. There is usually nothing that the driver could do but to drop a<br />

character if the higher level is not able to receive it.<br />

pollInput and pollOutput<br />

Provide an interface to polled mode operations of the driver. Do not call these<br />

functions unless the device has already been placed into polled mode<br />

operation by an SIO_MODE_SET operation.<br />

See target/src/drv/sio/templateSio.c for more information on the internal<br />

workings of a typical SIO device driver.<br />

F.4 Timer<br />

F<br />

The generic timer drivers reside in the directory target/src/drv/timer. Included in<br />

this directory is templateTimer.c. When writing a timer driver, base the driver on<br />

this template, then modify the <strong>BSP</strong>’s sysLib.c file to include the driver as needed.If<br />

a <strong>BSP</strong> has access to only a single timer, that <strong>BSP</strong> must support the system clock and<br />

not the auxiliary clock. This means that sysAuxClkConnect( ) must return<br />

ERROR.<br />

The following macros are used for parameter checking in VxWorks timer drivers,<br />

and must be defined in each <strong>BSP</strong>’s bspname.h file:<br />

SYS_CLK_RATE_MIN<br />

Defines the minimum rate at which the system clock can run. Unless hardware<br />

constraints dictate otherwise, SYS_CLK_RATE_MIN must be less than or equal<br />

to 60 Hz.<br />

251


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

SYS_CLK_RATE_MAX<br />

Defines the maximum rate at which the system clock can run. Unless hardware<br />

constraints dictate otherwise, SYS_CLK_RATE_MAX must be greater than or<br />

equal to 60 Hz.<br />

AUX_CLK_RATE_MIN<br />

Defines the minimum rate at which the auxiliary clock can run. To support<br />

spy( ), AUX_CLK_RATE_MIN must be less than or equal to 100 Hz.<br />

AUX_CLK_RATE_MAX<br />

Defines the maximum rate at which the auxiliary clock can run. To support<br />

spy( ), AUX_CLK_RATE_MAX must be greater than or equal to 100 Hz.<br />

F.5 Non-Volatile Memory<br />

The generic NVRAM and flash drivers reside in the directory target/src/drv/mem.<br />

Included in this directory is templateNvRam.c. This file provides the template<br />

driver to be used as the basis of non-volatile memory drivers, including flash.<br />

However, do not use this template for the optional True Flash File System (TFFS)<br />

product. For TFFS, refer to documentation accompanying special MTD drivers for<br />

flash devices.<br />

All <strong>BSP</strong>s are required to have some type of non-volatile memory interface, even if<br />

non-volatile memory is not available. The two required routines are<br />

sysNvRamGet( ) and sysNvRamSet( ). These routines both require an offset<br />

parameter. Internally, these routines use the offset parameter as follows:<br />

offset += NV_BOOT_OFFSET; /* boot line begins at = 0 */<br />

if ((offset < 0) || (strLen < 0) || ((offset + strLen) ><br />

NV_RAM_SIZE))<br />

return (ERROR);<br />

Thus, the offset parameter is biased so that an offset of 0 points to the first byte of<br />

the VxWorks boot line. This is always true even if the boot line is not at the<br />

beginning of the non-volatile memory area.<br />

All <strong>BSP</strong>s must define the following macros:<br />

252


F<br />

Generic Drivers<br />

NV_RAM_SIZE<br />

Defines the total bytes of NVRAM available. Define NV_RAM_SIZE in<br />

config.h,orbspname.h. For boards without NVRAM, define NV_RAM_SIZE as<br />

NONE.<br />

BOOT_LINE_SIZE<br />

Defines the number of bytes of NVRAM that are reserved for the VxWorks<br />

boot line. The default value is 255 and is defined in configAll.h.<br />

BOOT_LINE_SIZE must be less than or equal to NV_RAM_SIZE. To override the<br />

default value of BOOT_LINE_SIZE, first undefine then define the macro in<br />

config.h or bspname.h.<br />

NV_BOOT_OFFSET<br />

Defines the byte offset to the beginning of the VxWorks boot line in NVRAM.<br />

The default value is 0 and is defined in configAll.h. This is distinct from<br />

BOOT_LINE_OFFSET, the offset of the boot line stored in RAM.<br />

The routines sysNvRamSet( ) and sysNvRamGet( ) have an offset parameter.<br />

If NV_BOOT_OFFSET is greater than zero, you can access the bytes before the<br />

boot line by specifying a negative offset. To override the default value of<br />

NV_BOOT_OFFSET, first undefine then define the macro.<br />

For boards without NVRAM, include the file mem/nullNvRam.c for stubbed<br />

out versions of the routines that return ERROR.<br />

F<br />

F.6 VMEbus<br />

The generic VMEbus drivers reside in the directory target/src/drv/vme. Included<br />

in this directory is the templateVme.c. Use the driver in this file as the template for<br />

VME drivers. Included in this template file is detailed information on VME driver<br />

construction.<br />

For boards without a VMEbus interface, use the nullVme.c driver. If the<br />

application does not use network support, you can skip the VME driver altogether.<br />

Although, in this case, you might need to provide a sysBusTas( ) function that<br />

always returns FALSE.<br />

Wind River does not currently offer the kind of plug-and-play support published<br />

in the VME-64 specification and its extensions.<br />

253


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

F.7 DMA<br />

VxWorks does not currently impose a DMA driver model. DMA support is<br />

optional, and the architecture of such support is left to the implementation.<br />

F.8 Interrupt Controllers<br />

The generic interrupt controller device drivers reside in the directory<br />

target/src/drv/intrCtl. See the template driver templateIntrCtl.c for detailed<br />

information on interrupt controller driver design and construction.<br />

Some CPU architectures use external interrupt controllers to receive and prioritize<br />

external device interrupts. Wind River has prepared a draft document to define a<br />

standard interrupt controller device interface. To see this document, check<br />

WindSurf online, under Wind River Technical Notes.<br />

F.9 Multi-Function<br />

Historically, there has been a directory target/src/drv/multi for drivers used with<br />

ASIC chips that incorporate more than one area of functionality. Wind River no<br />

long supports this driver model.<br />

Drivers for ASIC chips and multi-function daughter boards should be divided into<br />

individual drivers for each functional area. Some of these drivers might need to<br />

depend on features in another driver. If this is necessary, it should be well<br />

documented in the dependent driver source code.<br />

With separate drivers for different functional areas, users can scale out support for<br />

functional areas that are not used by their application.<br />

254


F<br />

Generic Drivers<br />

F.10 PCI Bus<br />

The libraries pciConfigLib.c, pciConfigShow.c, pciIntLib.c, and pciAutoCfg.c<br />

provide support for the PCI Bus Specification 2.1. These libraries support basic and<br />

automatic configuration. For technical information on how to use these libraries’<br />

routines, refer to Wind River Technical Note #49 and related reference entries.<br />

F<br />

255


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

256


G<br />

Upgrading 4.3 BSD<br />

Network Drivers<br />

G.1 Introduction<br />

This appendix describes two upgrade paths for 4.3 BSD network drivers. One path<br />

simply ports the 4.3 BSD network driver to the BSD 4.4 model. The other path<br />

upgrades the 4.3 BSD network driver to an END driver (described in<br />

H. Implementing a MUX-Based Network Interface Driver).<br />

Porting a network driver to the 4.4 BSD model should require only minimal<br />

changes to the code. In fact, porting some drivers has taken less than a day’s work.<br />

However, an older driver that does not already use a transmission startup routine<br />

can take longer to port.<br />

Porting a network driver to an END requires more extensive changes. However, it<br />

is worth the effort if the driver must handle the following:<br />

■<br />

■<br />

■<br />

■<br />

multicasting<br />

polled-mode Ethernet (necessary for WDB debugging of the kernel over a<br />

network, a mode that is several orders of magnitude faster than the serial link)<br />

zero-copy transmission<br />

support for network protocols other than IP<br />

NOTE: This chapter assumes that you are already familiar with BSD network<br />

device drivers. You should also have already read H. Implementing a MUX-Based<br />

Network Interface Driver.<br />

257


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

G.1.1 Structure of a 4.3 BSD Network Driver<br />

The network drivers currently shipped with VxWorks are based on those available<br />

in BSD UNIX version 4.3. These drivers define only one global (user-callable)<br />

routine, the driver’s attach( ) routine. Typically, the name of this routine contains<br />

the word, attach, prefixed with two letters from the device name. For example, the<br />

AMD Lance driver’s attach routine is called lnattach( ). The xxattach( ) routine<br />

hooks in five function pointers that are mapped into an ifnet structure. These<br />

functions, listed in Table G-1, are all called from various places in the IP protocol<br />

stack, which has intimate knowledge of the driver.<br />

Table G-1<br />

Network Interface Procedure Handles<br />

Function Function Pointer Driver-Specific Routine<br />

initialization if_init xxInit( )<br />

output if_output xxOutput( )<br />

control if_ioctl xxIoctl( )<br />

reset if_reset xxReset( )<br />

watchdog if_watchdog (optional) xxWatchdog( )<br />

Packet reception begins when the driver’s interrupt routine is invoked. The<br />

interrupt routine does the least work necessary to get the packet off the local<br />

hardware, schedules an input handler to run by calling netJobAdd( ), and then<br />

returns. The tNetTask calls the function that was added to its work queue. In the<br />

case of packet reception, this the driver’s xxReceive( ) function.<br />

The xxReceive( ) function eventually sends the packet up to a protocol by calling<br />

do_protocol_with_type( ). This routine is a switch statement that figures out<br />

which protocol to hand the packet off to. This calling sequence is shown in<br />

Figure G-1.<br />

Figure G-2 shows the call graph for packet transmission. After a protocol has<br />

picked an interface on which to send a packet, it calls the xxOutput( ) routine for<br />

that interface. The output routine calls the generic ether_output( ) function,<br />

passing it a pointer to addressing information (usually an arpcom structure) as<br />

well as the data to be sent. After the data is properly packed, it is placed on the<br />

output queue (using the IF_ENQUEUE macro), and the driver’s start routine is<br />

called. The xxTxStartup( ) routine dequeues as many packets as it can and<br />

transmits them on the physical medium.<br />

258


G<br />

Upgrading 4.3 BSD Network Drivers<br />

Figure G-1<br />

Packet Reception Call Graph<br />

etherInputHook( )<br />

[1]<br />

xxReceive( )<br />

[2]<br />

do_protocol_with_type( )<br />

xxHandleRecvInt( )<br />

xxInt( )<br />

[1] The xxReceive( ) first shows the packet to etherInputHook( ).<br />

[2] If etherInputHook( ) does not take delivery of the packet, xxReceive( ) hands<br />

the packet to do_protocol_with_type( ).<br />

Figure G-2<br />

Packet Transmission Call Graph<br />

xxOutput( )<br />

ether_output( )<br />

xxTxStartup( )<br />

G<br />

[1] [2]<br />

etherOutputHook( )<br />

transmit on medium<br />

[1] The xxTxStartup( ) first shows the packet to etherOutputHook( ).<br />

[2] If etherOutputHook( ) does not take delivery of the packet, xxTxStartup( )<br />

transmits the packet on the medium.<br />

G.1.2 Etherhook Routines Provide Access to Raw Packets<br />

You can use the etherInputHook( ) and etherOutputHook( ) routines to bypass the<br />

TCP/IP stack and thus get access to raw packets. On packet reception, if an<br />

etherInputHook( ) function is installed, it receives the packet just after the driver<br />

has completed reception but before the packet goes to the protocol. If<br />

259


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

etherInputHook( ) decides to prevent others from seeing the packet,<br />

etherInputHook( ) returns a non-zero value and the driver considers the packet to<br />

be delivered. If the etherInputHook( ) returns 0, the driver hands the packet to the<br />

TCP/IP stack.<br />

On packet transmission, an installed etherOutputHook( ) receives a packet just<br />

before it would have been transmitted. If etherOutputHook( ) decides to prevent<br />

the packet from passing on, etherOutputHook( ) returns a non-zero value and the<br />

driver considers the packet to be transmitted. If the etherOutputHook( ) returns 0,<br />

the driver transmits the packet.<br />

It is only possible to install one etherInputHook( ) and one etherOutputHook( )<br />

function per driver. This limits the number of alternate protocols to one, unless<br />

these ether*Hook( ) routines then act as a multiplexor for more protocols.<br />

For more information on etherhooks, see the Tornado User’s <strong>Guide</strong>, 1.0.1:<br />

G.4 Network Interface Hook Routines.<br />

NOTE: Future versions of VxWorks will not support etherhooks.<br />

G.2 Upgrading to 4.4 BSD<br />

To upgrade a driver from 4.3 BSD to 4.4 BSD you must change how the driver uses<br />

ether_attach( ). This routine is almost always called from the driver’s own<br />

xxattach( ) routine and is responsible for placing the driver’s entry points, listed in<br />

Table G-1, into the ifnet structure that the TCP/IP protocol to track drivers.<br />

Consider the call to ether_attach( ) shown below:<br />

ether_attach(<br />

(IFNET *) & pDrvCtrl->idr,<br />

unit,<br />

"xx",<br />

(FUNCPTR) NULL,<br />

(FUNCPTR) xxIoctl,<br />

(FUNCPTR) xxOutput,<br />

(FUNCPTR) xxReset<br />

);<br />

As arguments, this routine expects an Interface Data Record (IDR), a unit number,<br />

and a quoted string that is the name of the device, in this case, “xx”. The next four<br />

arguments are the function pointers to relevant driver routines.<br />

260


G<br />

Upgrading 4.3 BSD Network Drivers<br />

The first function pointer references this driver’s init( ) routine, which this driver<br />

does not need or have. The second function pointer references the driver’s ioctl( )<br />

interface, which allows the upper layer to manipulate the device state. The third<br />

function pointer references the routine that outputs packets on the physical<br />

medium. The last function pointer references a routine that can reset the device if<br />

the TCP/IP stack decides that this needs to be done.<br />

In 4.4 BSD, there is a generic output routine called ether_output( ) that all Ethernet<br />

device drivers can use. Thus, to convert the above ether_attach( ) call to a 4.4-style<br />

call, you would call ether_attach( ) as follows:<br />

ether_attach(<br />

(IFNET *) & pDrvCtrl->idr,<br />

unit,<br />

"xx",<br />

(FUNCPTR) NULL,<br />

(FUNCPTR) xxIoctl,<br />

(FUNCPTR) ether_output, /* generic ether_output */<br />

(FUNCPTR) xxReset<br />

);<br />

pDrvCtrl->idr.ac_if.if_start = (FUNCPTR)xxTxStartup;<br />

This time, there is an extra line following the call to ether_attach( ). This line of<br />

code adds a transmit startup routine to the Interface Data Record. The transmit<br />

startup routine is called by the TCP/IP stack after the generic ether_output( )<br />

routine is called. This extra line of code assumes that the driver already has a<br />

transmit startup routine. If a driver lacks a separate transmit startup routine, you<br />

must write one. See the template in G.2.4 Creating a Transmit Startup Routine.<br />

G<br />

G.2.1 Removing the xxOutput( ) Routine<br />

If a 4.3 BSD driver has an xxOutput( ) routine, it should look something like the<br />

following:<br />

static int xxOutput<br />

(<br />

IDR * pIDR,<br />

MBUF * pMbuf,<br />

SOCK * pDestAddr<br />

)<br />

{<br />

return (ether_output ((IFNET *)pIDR,pMbuf, pDestAddr,<br />

(FUNCPTR) xxTxStartup, pIDR));<br />

}<br />

Internally, this routine calls the ether_output( ) routine, which expects a pointer to<br />

the startup routine as one of its arguments. However, in the 4.4 BSD model, all that<br />

261


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

work that is now handled in the TCP/IP stack. Thus, in a 4.4 BSD driver, this code<br />

is unnecessary and should be removed.<br />

G.2.2 Changing the Transmit Startup Routine<br />

Under 4.3 BSD, the function prototype for a transmit startup routine is as follows:<br />

static void xxTxStartup (int unit);<br />

Under 4.4 BSD, the prototype has changed to the following:<br />

static void xxTxStartup (struct ifnet * pDrvCtrl);<br />

The 4.4 BSD version expects a pointer to a driver control structure. This change<br />

eases the burden on the startup routine. Instead of having to find its own driver<br />

control structure, it receives a pointer to a driver control structure as input.<br />

If the driver uses netJobAdd( ) to schedule the transmit startup routine for<br />

task-level execution, edit the netJobAdd( ) call to pass in a DRV_CTRL structure<br />

pointer instead of a unit number.<br />

G.2.3 Changes in Receiving Packets<br />

Under 4.3 BSD, the driver calls do_protocol_with_type( ). For example:<br />

do_protocol_with_type (etherType, pMbuf, &pDrvCtrl->idr, len);<br />

This call expects an etherType (which the driver had to discover previously), a<br />

pointer to an mbuf containing the packet data, the Interface Data Record, and the<br />

length of the data.<br />

Under 4.4 BSD, replace the call above with a call to do_protocol( ). For example:<br />

do_protocol (pEh, pMbuf, &pDrvCtrl->idr, len);<br />

The first parameter expects a pointer to the very beginning of the packet (including<br />

the link level header). All the other parameters remain the same. The driver no<br />

longer needs to figure out the etherType for the protocol.<br />

262


G<br />

Upgrading 4.3 BSD Network Drivers<br />

G.2.4 Creating a Transmit Startup Routine<br />

Some 4.3 BSD drivers did not have a transmit startup routine. For such a driver,<br />

you must create one. The template is as follows:<br />

void templateStartup<br />

(<br />

DRV_CTRL *pDrvCtrl<br />

)<br />

{<br />

MBUF * pMbuf;<br />

int length;<br />

TFD * pTfd;<br />

/*<br />

* Loop until there are no more packets ready to send or we<br />

* have insufficient resources left to send another one.<br />

*/<br />

while (pDrvCtrl->idr.ac_if.if_snd.ifq_head)<br />

{<br />

/* Deque a packet from the send queue. */<br />

IF_DEQUEUE (&pDrvCtrl->idr.ac_if.if_snd, pMbuf);<br />

/*<br />

* Device specific code to get transmit resources, such as a<br />

* transmit descriptor, goes here.<br />

*<br />

*/<br />

if (Insufficient Resources)<br />

{<br />

m_freem (pMbuf);/* Make sure to free the packet. */<br />

return;<br />

}<br />

G<br />

/*<br />

* pData below is really the place in your descriptor,<br />

* transmit descriptor, or equivalent, where the data is<br />

* to be placed.<br />

*/<br />

copy_from_mbufs (pData, pMbuf, length);<br />

if ((etherOutputHookRtn != NULL) &&<br />

(* etherOutputHookRtn)<br />

(&pDrvCtrl->idr, (ETH_HDR *)pTfd->enetHdr, length))<br />

continue;<br />

/*<br />

* Do hardware manipulation to set appropriate bits<br />

* and other stuff to get the packet to actually go.<br />

*/<br />

263


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

/*<br />

* Update the counter that determines the number of<br />

* packets that have been output.<br />

*/<br />

pDrvCtrl->idr.ac_if.if_opackets++;<br />

} /* End of while loop. */<br />

} /* End of transmit routine. */<br />

G.3 Porting a Network Interface Driver to the END Model<br />

The MUX-based model for network drivers contains standardized entry points<br />

that are not present in the BSD model. Table G-2 shows some of the analogies<br />

between functions found in BSD 4.3 drivers and those necessary for ENDs.<br />

Fortunately, you should be able to reuse much of the code from the BSD 4.3<br />

network driver.<br />

Table G-2<br />

Required Driver Entry Points and their Derivations<br />

END Entry Points<br />

BSD 4.3 Style Entry Points<br />

endLoad( ) xxattach( )<br />

endUnload( )<br />

N/A<br />

N/A xxReceive( )<br />

endSend( ) xxOutput( )<br />

endIoctl( ) xxIoctl( )<br />

endMCastAddrAdd( )<br />

endMCastAddrDel( )<br />

endMCastAddrGet( )<br />

endPollSend( )<br />

endPollReceive( )<br />

N/A<br />

N/A<br />

N/A<br />

N/A<br />

N/A<br />

264


G<br />

Upgrading 4.3 BSD Network Drivers<br />

! CAUTION: When converting a BSD 4.3 network driver code to an END, you must<br />

replace all calls into the protocol with appropriate calls to the MUX. Also, you must<br />

remove all code that implements or uses the etherInputHook( ) and<br />

etherOutputHook( ) routines.<br />

Rewrite xxattach( ) to Use an endLoad( ) Interface<br />

Rewrite the interface of your xxattach( ) to match the endLoad( ) entry point<br />

described in Loading the Device: endLoad( ), p.290.<br />

Much of the code that handles the specifics of hardware initialization should be the<br />

same. However, when allocating the memory for packet reception buffers that are<br />

passed up to the protocol, you should use the MUX buffer management utilities.<br />

See H.3.1 Setting Up and Using a Memory Pool for Receive and Transmit Buffers, as well<br />

as the reference entry for muxBufInit( ).<br />

Remove any code your xxattach( ) included to support the implementation of the<br />

etherInputHook( ) and etherOutputHook( ) routines.<br />

xxReceive( ) Still Handles Task-Level Packet Reception<br />

Because the MUX does not directly call the driver’s packet reception code, there is<br />

no endReceive( ) entry point. However, your driver still needs to handle packet<br />

reception at the task level. Unfortunately, most of the code in this driver routine<br />

requires extensive revision. Instead of calling the protocol directly, this routine<br />

uses a MUX-supplied function to pass a packet up to the protocol (see<br />

H.3 <strong>Guide</strong>lines for Handling Packet Reception in Your Driver). Also, your receive<br />

routine should use the MUX-managed memory pool as its receive buffer area.<br />

G<br />

Rewrite xxOutput( ) to Use an endSend( ) Interface<br />

Rewrite the interface of your xxOutput( ) to match the endSend( ) routine<br />

described in Sending Data Out on the Device: endSend( ), p.293.<br />

Much of the code that dealt directly with putting the packet on the hardware<br />

should need little if any revision. However, you should change your code to use<br />

mblk chains allocated out of an endBufLib-managed memory pool. For more<br />

information, see the reference entry for netBufLib.<br />

265


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

xxIoctl( ) is the Basis of endIoctl( )<br />

Rewrite the interface of your xxIoctl( ) to match the endIoctl( ) routine described<br />

in Providing an Opaque Control Interface to Your Driver: endIoctl( ), p.292. If your<br />

driver used xxIoctl( ) to implement multicasting, you must separate those<br />

operations into the separate endMCastAddrAdd( ), endMCastAddrDel( ), and<br />

endMCastAddrGet( ) routines.<br />

266


H<br />

Implementing a MUX-Based<br />

Network Interface Driver<br />

H.1 Introduction<br />

A network interface driver written especially for use with the network stack is<br />

known as an Enhanced Network Driver (END). This chapter describes how to<br />

write an END as well as how to write a protocol that knows how to use an END.<br />

This chapter assumes that you are a software developer familiar with general<br />

networking principles—including protocol layering. Familiarity with 4.4 BSD<br />

networking internals is also helpful. This chapter is not a tutorial on writing<br />

network interface drivers. Instead, you should use this chapter as a guide to the<br />

specifics of writing a network interface driver that runs under VxWorks.<br />

If this is the first time you have written a network interface driver, consider taking<br />

an existing driver and modifying it to meet your needs. For more information on<br />

TCP/IP, Wind River recommends the following Addison Wesley publications:<br />

■<br />

■<br />

TCP/IP Illustrated, Volume 1, The Protocols, by W. Richard Stevens<br />

TCP/IP Illustrated, Volume 2, The Implementation,<br />

by Gary R. Wright and W. Richard Stevens<br />

NOTE: If you are using IPv6, you should also consult the WindNet IPv6<br />

Programmer’s <strong>Guide</strong>, 1.0 or a future version of the VxWorks Network Programmer’s<br />

<strong>Guide</strong> (that is, a version released after WindNet IPv6 1.0).<br />

NOTE: The src/drv/end directory contains templateEnd.c as well as ln7990End.c,<br />

a sample END driver for use with the Lance chip.<br />

267


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

The MUX Is an Interface Joining the Data Link and Protocol Layers<br />

One feature of the network stack is an API between the data link and network<br />

protocol layers. This API multiplexes access to the networking hardware for<br />

multiple network protocols. This interface is known as the MUX. Figure H-1 shows<br />

the MUX in relationship to protocol and data link layers.<br />

Figure H-1<br />

The MUX Is the Interface Between the Data Link and Protocol Layers<br />

Protocol Layer:<br />

IP + ICMP<br />

Streams<br />

(custom<br />

protocol)<br />

MUX<br />

Data Link Layer:<br />

Ethernet<br />

Backplane<br />

CSLIP<br />

(other)<br />

At the protocol layer, VxWorks typically uses IP, although you can port and use<br />

other protocols. At the data link layer, VxWorks typically uses Ethernet, although<br />

VxWorks does support other physical media for data transmission. For example,<br />

VxWorks supports the use of serial lines for long-distance connections. In more<br />

closely coupled environments, VxWorks Internet protocols can also use the shared<br />

memory on a common backplane as the physical medium. However, whatever the<br />

medium, the network interface drivers all use the MUX to communicate with the<br />

protocol layer.<br />

NOTE: The data link layer is an abstraction. A network interface driver is code that<br />

implements the functionality described by that abstraction. Likewise, the protocol<br />

layer is an abstraction. The code that implements the functionality of the protocol<br />

layer could be called a protocol interface driver. However, this document refers to<br />

such code simply as “the protocol.”<br />

The MUX Decouples Network Interface Drivers and Protocols<br />

Under the BSD 4.3 model, VxWorks network drivers and protocols are tightly<br />

coupled. Both the protocol and the network driver depend on an intimate<br />

knowledge of each other’s data structures. Under the MUX-based model, network<br />

drivers and protocols have no knowledge of each other’s internals. Network<br />

interface drivers and protocols interact only indirectly—through the MUX.<br />

268


H<br />

Implementing a MUX-Based Network Interface Driver<br />

For example, after receiving a packet, the network interface driver does not<br />

directly access any structure within the protocol. Instead, when the driver is ready<br />

to pass data up to the protocol, the driver calls a MUX-supplied function. This<br />

function then handles the details of passing the data up to the protocol.<br />

The purpose of the MUX is to decouple the protocol and network driver, thus<br />

making the network driver and protocol nearly independent of each another. This<br />

independence makes it much easier to add a new drivers or protocols. For<br />

example, if you add a new END, all existing MUX-based protocols can use the new<br />

driver. Likewise, if you add a new MUX-based protocol, any existing END can use<br />

the MUX to access the new protocol.<br />

An Overview of the MUX, Protocol, and Driver API<br />

Figure H-2 shows a protocol, the MUX, and a network interface driver. The<br />

protocol implements the following entry points:<br />

■<br />

stackShutdownRtn( )<br />

■<br />

stackError( )<br />

■<br />

stackRcvRtn( )<br />

■<br />

stackTxRestartRtn( )<br />

The MUX calls these entry points when it needs to interact with a protocol. To port<br />

a protocol to use the MUX, you must implement at least all the entry points listed<br />

above.<br />

The MUX implements the entry points muxBind( ), muxUnbind( ),<br />

muxDevLoad( ), and so on. Both the protocol and the driver call the MUX entry<br />

points as needed. Because the MUX is already implemented for you, it requires no<br />

additional coding work on your part.<br />

The network interface driver implements the entry points endLoad( ),<br />

endUnload( ), endSend( ), and so on. The MUX uses these entry points to interact<br />

with the network interface driver. When writing or porting a network interface<br />

driver to use the MUX, you must implement all the entry points listed in<br />

Table H-1.<br />

H<br />

269


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Figure H-2<br />

The MUX Interface<br />

muxBind( )<br />

stackShutdownRtn( ) muxUnbind( )<br />

muxDevLoad( )<br />

muxDevUnload( )<br />

endLoad( )<br />

endUnload( )<br />

stackRcvRtn( )<br />

stackError( )<br />

muxReceive( )<br />

muxError( )<br />

muxSend( )<br />

endSend( )<br />

stackTxRestartRtn( ) muxTxRestartRtn( ) endTxRestartRtn( )<br />

muxMCastAddrDel( )<br />

muxMCastAddrGet( )<br />

endMCastAddrDel( )<br />

endMCastAddrGet( )<br />

muxPollSend( )<br />

muxMCastAddrAdd( )<br />

endPollSend( )<br />

endMCastAddrAdd( )<br />

muxPollReceive( )<br />

endPollReceive( )<br />

muxIoctl( ) endIoctl( )<br />

endStart( )<br />

endStop( )<br />

Protocol MUX END<br />

The arrows indicate calls to an entry point. For example, the top-most arrow tells you that the protocol<br />

calls muxBind( ), a routine implemented in the MUX. If the MUX-based API specifies both ends of the<br />

call, the figure specifies a routine name at each end of an arrow. For example, muxSend( ) calls<br />

endSend( ). Note that, although the protocol started the send by calling muxSend( ), the figure does<br />

not name the protocol routine that called muxSend( ). That routine is outside the standardized API.<br />

H.2 How VxWorks Launches and Uses Your Driver<br />

The primary focus of this chapter is on the MUX utilities and the standard END<br />

entry points. However, when designing or debugging your driver’s entry points,<br />

270


H<br />

Implementing a MUX-Based Network Interface Driver<br />

you need to know the context in which the entry point executes. Thus, you need to<br />

know the following:<br />

■<br />

■<br />

■<br />

The task that makes the calls that actually load and start your driver.<br />

The task that typically registers the interrupt handler for your driver.<br />

The task that uses your driver to do most of the processing on a packet.<br />

H.2.1 Launching Your Driver<br />

At system startup, VxWorks spawns the task tUsrRoot to handle the following:<br />

■<br />

■<br />

■<br />

■<br />

Initializing the network task’s job queue.<br />

Spawning tNetTask to process items on the network task’s job queue.<br />

Calling muxDevLoad( ) to load your network driver.<br />

Calling muxDevStart( ) to start your driver.<br />

Loading Your Driver into the MUX<br />

To load your network driver, tUsrRoot calls muxDevLoad( ). As input to the call,<br />

tUsrRoot specifies your driver’s endLoad( ) entry point. Internally, the<br />

muxDevLoad( ) call executes the specified endLoad( ) entry point. This<br />

endLoad( ) entry point is analogous to the xxattach( ) entry point, the only public<br />

entry point into the 4.3 BSD style drivers.<br />

The endLoad( ) routine handles any device-specific initialization and returns an<br />

END_OBJ structure. Your endLoad( ) must populate most of this structure (see,<br />

Providing Network Device Abstraction: END_OBJ, p.283). This includes providing a<br />

pointer to a NET_FUNCS structure populated with function pointers to your<br />

driver’s entry points for handling sends, receives, and so on.<br />

After control returns from endLoad( ) to muxDevLoad( ), the MUX completes the<br />

END_OBJ structure (by giving it a pointer to a function your driver can use to pass<br />

packets up to the MUX). The MUX then adds the returned END_OBJ to a linked list<br />

of END_OBJ structures. This list maintains the state of all the currently active<br />

network devices on the system. After control returns from muxDevLoad( ), your<br />

driver is loaded and ready to use.<br />

H<br />

Registering Your Driver’s Interrupt Routine<br />

To register your driver’s interrupt handler, you must call sysIntConnect( ). The<br />

most typical place to make this call is in your driver’s endStart( ) entry point.<br />

271


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

When muxDevLoad( ) loads your driver, it calls muxDevStart( ), which then calls<br />

your driver’s endStart( ) entry point.<br />

H.2.2 Your ISR Puts Work on the Network Job Queue<br />

Upon arrival of an interrupt on the network device, VxWorks invokes your<br />

driver’s previously registered interrupt service routine. Your interrupt service<br />

routine should do the minimum amount of work necessary to get the packet off the<br />

local hardware. To minimize interrupt lock-out time, your interrupt service routine<br />

should handle only those tasks that require minimal execution time, such as error<br />

or status change. Your interrupt service routine should queue all time-consuming<br />

work for processing at the task level.<br />

To queue packet-reception work for processing at the task level, your interrupt<br />

service routine must call netJobAdd( ). As input, this routine accepts a function<br />

pointer and up to five additional arguments (parameters to the function referenced<br />

by the function pointer).<br />

STATUS netJobAdd<br />

(<br />

FUNCPTR routine, /* routine to add to netTask work queue */<br />

int param1, /* first arg to added routine */<br />

int param2, /* second arg to added routine */<br />

int param3, /* third arg to added routine */<br />

int param4, /* fourth arg to added routine */<br />

int param5 /* fifth arg to added routine */<br />

)<br />

In your call to netJobAdd( ), you should specify your driver’s entry point for<br />

processing packets at the task level. The netJobAdd( ) routine then puts the<br />

function call (and arguments) on tNetTask’s work queue. VxWorks uses tNetTask<br />

to handle task-level network processing.<br />

NOTE: You can use netJobAdd( ) to queue up work other than processing for<br />

received packets.<br />

! CAUTION: Use netJobAdd( ) sparingly. The netJobRing is a finite resource that is<br />

also used by the network stack. If it overflows, this implies a general network stack<br />

corruption.<br />

272


H<br />

Implementing a MUX-Based Network Interface Driver<br />

H.2.3 Executing Calls Waiting in the Network Job Queue<br />

The tNetTask task sleeps on an incoming work queue. In response to an incoming<br />

packet, your interrupt service routine calls netJobAdd( ). As parameters to<br />

netJobAdd( ), your interrupt service routine specifies your driver’s entry point for<br />

handling task-level packet reception. The netJobAdd( ) call adds this entry point<br />

to tNetTask’s work queue. The netJobAdd( ) call also automatically gives the<br />

appropriate semaphore for awakening tNetTask.<br />

Upon awakening, tNetTask dequeues function calls and associated arguments<br />

from its work queue. It then executes these functions in its context. The tNetTask<br />

task runs as long as there is work on its queue. When the queue is empty and all<br />

packets have been successfully handed off to the MUX, tNetTask goes back to<br />

sleep on the queue.<br />

H.2.4 Adding Your Network Interface Driver to VxWorks<br />

Adding your driver to the target VxWorks system is much like adding any other<br />

application. The first step is to compile and include the driver code in the VxWorks<br />

image. For a description of the general procedures, see the Tornado User’s <strong>Guide</strong>.It<br />

tells you how to compile source code to produce target-suitable object code.<br />

Including most software modules in the VxWorks image is usually just a matter of<br />

setting a few #define statements. Adding a network interface driver does not<br />

require much more. However, because VxWorks allows you to create more than<br />

one network device, you must also set up a table that groups the #define<br />

statements into device-specific groups. This table is defined in<br />

target/src/config/<strong>BSP</strong>/configNet.h where <strong>BSP</strong> is the name of your Board Support<br />

Package, such as mv162, pc486, and the like.<br />

For example, if you wanted VxWorks to create two network devices, one that<br />

supported buffer loaning and one that did not, you would first edit configNet.h to<br />

include the following statements:<br />

H<br />

/* Parameters for loading the driver supporting buffer loaning. */<br />

#define LOAD_FUNC_0 ln7990EndLoad<br />

#define LOAD_STRING_0 "0xfffffe0:0xffffffe2:0:1:1"<br />

#define <strong>BSP</strong>_0 NULL<br />

/* Parameters for loading the driver NOT supporting buffer loaning. */<br />

#define LOAD_FUNC_1 LOAD_FUNC_0<br />

#define LOAD_STRING_1 "0xffffee0:0xfffffee2:4:1:1"<br />

#define <strong>BSP</strong>_1 NULL<br />

273


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

To set appropriate values for these constants, consider the following:<br />

END_LOAD_FUNC<br />

Specifies the name of your driver’s endLoad( ) entry point. For example, if<br />

your driver’s endLoad( ) entry point were ln7990EndLoad( ), you would edit<br />

config.h to include the line:<br />

#define END_LOAD_FUNC ln7990EndLoad<br />

END_LOAD_STRING<br />

Specifies the initialization string passed into muxDevLoad( ) as the initString<br />

parameter.<br />

You must also edit the definition of the endTbl (a table in configNet.h that specifies<br />

the ENDs included in the image) to include the following:<br />

END_TBL_ENTRY endTbl<br />

{<br />

{ 0, LOAD_FUNC_0, LOAD_STRING_0, <strong>BSP</strong>_0, FALSE},<br />

{ 1, LOAD_FUNC_1, LOAD_STRING_1, <strong>BSP</strong>_1, FALSE},<br />

{ 0, END_TBL_END, 0, NULL},<br />

};<br />

The number at the beginning of each line specifies the unit number for the device.<br />

The first line specifies a unit number of 0. Thus, the device it loads is deviceName0.<br />

The FALSE at the end of each entry indicates that the entry has not been processed.<br />

After the system has successfully loaded a driver, it changes this value to TRUE in<br />

the run-time version of this table. If you want to prevent the system from<br />

automatically loading your driver, set this value to TRUE.<br />

Finally, you must edit your <strong>BSP</strong>’s config.h file to define INCLUDE_END. 1 This tells<br />

the build process to include the END/MUX interface. A this point, you are ready<br />

to rebuild VxWorks to include your new drivers. When you boot this rebuilt image,<br />

it calls muxDevLoad( ) for each device specified in the table in the order listed. 2<br />

NOTE: If you do not rebuild your boot ROMs, they cannot contain your new END.<br />

This means you must boot from a non-END driver already resident in the boot<br />

ROMs. To do this, you must define END_OVERRIDE in your <strong>BSP</strong>’s config.h. After<br />

the system actually boots, it can use the new END device that you included in the<br />

VxWorks image.<br />

1. By default, the config.h file for an END <strong>BSP</strong> undefines INCLUDE_END.<br />

2. For a description of the parameters to muxDevLoad( ), see the appropriate reference entry.<br />

274


H<br />

Implementing a MUX-Based Network Interface Driver<br />

H.3 <strong>Guide</strong>lines for Handling Packet Reception in Your Driver<br />

The list of END entry points (see Table H-1) makes no mention of an endReceive( )<br />

entry point. That is because an END does not require one. Of course, your driver<br />

must include code that handles packet reception, but the MUX never calls this code<br />

directly. Thus, the specifics of the code for packet reception are left to you.<br />

However, even if the MUX API does not require an endReceive( ) entry point, you<br />

need to consider the VxWorks system when designing your driver’s packet<br />

reception code. For example, your network interface driver must include an entry<br />

point that acts as your device’s interrupt service routine. In addition, your driver<br />

also needs a different entry point for completing packet reception at the task level.<br />

Internally, your task-level packet-reception entry point should do whatever is<br />

necessary to prepare the packet for handing off to the MUX, such as assuring data<br />

coherency. Likewise, this entry point might use a level of indirection in order to<br />

check for and avoid race conditions before it attempts to do any processing on the<br />

received data. 3 When all is ready, your driver should pass the packet up to the<br />

MUX. To do this, it calls the function referenced in the receiveRtn member of the<br />

END_OBJ structure (see Providing Network Device Abstraction: END_OBJ, p.283).<br />

Although your driver’s endLoad( ) entry point allocated this END_OBJ structure<br />

and set the values of most of its members, it did not and could not set the value of<br />

the receiveRtn member. The MUX does this for you upon completion of the<br />

muxDevLoad( ) call that loaded your driver. However, there is a very brief interval<br />

between the time the driver becomes active and the completion of muxDevLoad( ).<br />

During that time, receiveRtn might not be set. Thus, it is a good practice always to<br />

check receiveRtn for NULL before you try to execute the function referenced there.<br />

H<br />

Removing Etherhook Code in Ported Drivers<br />

The BSD 4.3 model for a VxWorks network interface drivers support a set of input<br />

and output hooks that you can use to intercept packets as they pass between the<br />

driver and protocol. These input and output hooks are referred to as the etherhooks.<br />

When porting a driver to the END model, you must remove the code (if any) that<br />

implements etherhooks. ENDs have no need of etherhooks. That functionality is<br />

built into the MUX. For more information, see the discussion of etherhooks in the<br />

Tornado User’s <strong>Guide</strong>, 1.0.1.<br />

3. See the sample driver in target/src/drv/end/ln7990End.c.<br />

275


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

H.3.1 Setting Up and Using a Memory Pool for Receive and Transmit Buffers<br />

Included with the network stack is netBufLib, a library that you can use to set up<br />

and manage a memory pool specialized to the buffering needs of networking<br />

applications such as ENDs and network protocols. To support buffer loaning and<br />

other features, netBufLib routines deal with data in terms of mBlks, clBlks, and<br />

clusters. As a consequence, a memory pool established using netPoolInit( ) is<br />

organized around a pool of mBlk structures, a pool of clBlk structures, and one or<br />

more pools of clusters.<br />

The netBufLib routines use the mBlk and clBlk structures to track information<br />

necessary to manage the data in the clusters. The clusters contain the data<br />

described by the mBlk and clBlk structures. The mBlk structure is the primary<br />

vehicle through which you access or pass the data that resides in a memory pool<br />

established by netPoolInit( ). Because an mBlk merely references the data, this lets<br />

network layers communicate data without actually having to copy the data.<br />

Another mBlk feature is chaining. This lets you pass an arbitrarily large amount of<br />

data by passing the mBlk at the head of an mBlk chain. See Figure H-3.<br />

In addition, because the mBlk structure references data through a clBlk structure,<br />

this makes it easy for multiple mBlks to share the same cluster. This ability is<br />

useful if you want to duplicate an mBlk without having to copy the referenced<br />

data. For example, mBlk 1 in Figure H-4 is a duplicate of mBlk A. Both are joined<br />

to the same clBlk. Thus, both share the same cluster.<br />

Please note that using a clBlk structure instead of a pointer to provide a level of<br />

indirection is not an extravagance. The clBlk structure tracks how many mBlks<br />

share its underlying cluster. This is critical when it comes time to free an<br />

mBlk/clBlk/cluster construct. If you use netMblkClFree( ) to free the construct,<br />

the mBlk is freed back to the pool and the reference count in the clBlk is<br />

decremented. If the reference count drops to zero, the clBlk and cluster are also<br />

freed back to the memory pool.<br />

Setting Up a Memory Pool<br />

Each END unit requires its own memory pool. How you configure a memory pool<br />

differs slightly depending on whether you intend the memory pool to be used by<br />

a network protocol, such as IPv4, or an END.<br />

As was mentioned above, all memory pools are organized around pools of mBlk<br />

structures, clBlk structures, and clusters. However, because a network protocol<br />

typically requires clusters of several different sizes, its memory pool must contain<br />

several cluster pools (one cluster pool for each cluster size). In addition, each<br />

276


H<br />

Implementing a MUX-Based Network Interface Driver<br />

Figure H-3<br />

Presentation of Two Packets to the TCP Layer<br />

mBlk mBlk mBlk null<br />

clBlk clBlk clBlk<br />

Cluster<br />

64 bytes<br />

Cluster<br />

512<br />

bytes<br />

Cluster<br />

2048<br />

bytes<br />

Packet 1<br />

mBlk mBlk null<br />

clBlk<br />

Cluster<br />

64 bytes<br />

clBlk<br />

Cluster<br />

2028<br />

bytes<br />

Packet 2<br />

Figure H-4<br />

Two mBlks Can Share the Same Cluster<br />

H<br />

mBlk 1<br />

mBlk 2<br />

null<br />

mBlk A<br />

mBlk Bb<br />

null<br />

clBlk<br />

clBlk<br />

Cluster<br />

64 bytes<br />

Cluster<br />

2028<br />

bytes<br />

277


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

cluster size must be a power of two. Common cluster sizes for this style of memory<br />

pool are 64, 128, 256, 512, 1024 and 2048 bytes. See Figure H-5.<br />

Figure H-5<br />

A Protocol Memory Pool<br />

Memory Pool for a Protocol Stack<br />

Pool of mBlks<br />

mBlk mBlk mBlk<br />

mBlk mBlk mBlk<br />

mBlk mBlk mBlk<br />

mBlk mBlk ...<br />

Pool of Clusters<br />

64 64 64<br />

64 64 64<br />

64 64 64<br />

64 64 ...<br />

Pool of clBlks<br />

clBlk clBlk clBlk<br />

clBlk clBlk clBlk<br />

clBlk clBlk clBlk<br />

clBlk clBlk ...<br />

Pool of Clusters<br />

128 128 128<br />

128 128 128<br />

128 128 128<br />

128 128 ...<br />

Pool of Clusters<br />

...<br />

By contrast, a memory pool intended for an END typically contains only one<br />

cluster pool (in addition to the mBlk pools and clBlk pools), and the cluster size is<br />

not limited to a power of two. Thus, you are free to choose whatever cluster size is<br />

most convenient, which is typically something close to the MTU of the network.<br />

For example, in the Lance Ethernet END, the cluster size is 1520 bytes, which is the<br />

Ethernet MTU plus some slack. See Figure H-6.<br />

NOTE: It is recommended that there be at least a 3:1 ratio of mBlks to clusters.<br />

Figure H-6<br />

An END Memory Pool<br />

Memory Pool for an END<br />

Pool of mBlks<br />

mBlk mBlk mBlk<br />

mBlk mBlk mBlk<br />

mBlk mBlk mBlk<br />

mBlk mBlk ...<br />

Pool of clBlks<br />

clBlk clBlk clBlk<br />

clBlk clBlk clBlk<br />

clBlk clBlk clBlk<br />

clBlk clBlk ...<br />

Pool of Clusters<br />

1520 1520 1520<br />

1520 1520 1520<br />

1520 1520 1520<br />

1520 1520 ...<br />

278


H<br />

Implementing a MUX-Based Network Interface Driver<br />

To establish a memory pool, call netPoolInit( ). For an END, make the<br />

netPoolInit( ) call during the driver’s initialization phase. From out of this pool,<br />

your driver should reserve the mBlk/clBlk/cluster constructs it needs to receive<br />

a packet. For more information, see the reference entry for netBufLib.<br />

Receiving Data into Clusters<br />

During the initialization phase of your END, call netClusterGet( ) to reserve some<br />

reasonable number of clusters to receive incoming packets (store references to<br />

these reserved clusters in a buffer ring or some other structure appropriate to your<br />

needs). When a packet arrives, your END should receive it directly into one of<br />

these clusters.<br />

When your END is ready to pass a received packet up to the MUX, it does so using<br />

an mBlk/clBlk/cluster construct. To create this construct:<br />

1. Call netClBlkGet( ) to reserve a clBlk structure.<br />

2. Call netClBlkJoin( ) to join the clBlk to the cluster containing the packet.<br />

3. Call netMblkGet( ) to reserve a mBlk structure.<br />

4. Call netMblkClJoin( ) to join the mBlk structure to the clBlk/cluster<br />

construct.<br />

Now that the packet is contained within an mBlk/clBlk/cluster construct, the<br />

END can use various netBufLib routines to adjust or inspect the data in the<br />

mBlk/clBlk/cluster construct. For example, to read the packet data in the<br />

construct, your END can call netMblkToBufCopy( ). In addition, your END can<br />

use the mBlk chaining feature to prepend or append data to the packet.<br />

H<br />

NOTE: The various net*Get( ) routines reserve memory from a pre-allocated pool.<br />

Internally, they do not use semaphores. Thus, they are safe to call from places<br />

where a call to malloc( ) would be impossible.<br />

Freeing mBlks, clBlks, and Clusters<br />

When you are done with an mBlk/clBlk/cluster chain and want to return it to the<br />

memory pool, call netMblkClChainFree( ). This frees all mBlks in the chain. It<br />

also decrements the reference counters in all the clBlks in the chain. If the reference<br />

counter for a clBlk drops to zero, that clBlk and its associated cluster are also freed<br />

back to the pool. To free a single mBlk/clBlk/cluster back to the memory pool, use<br />

netMblkClFree( ). For more information on these and other free routines, see the<br />

reference entry for netBufLib.<br />

279


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

H.3.2 Swapping Buffers Between Protocol and Driver<br />

To pass a buffer up to the MUX, a driver calls muxReceive( ), which, in turn, calls<br />

the protocol’s stackRcvRtn( ) routine (see Passing a Packet Up to the Protocol:<br />

stackRcvRtn( ), p.307). When control returns from muxReceive( ), the driver can<br />

consider the data delivered and can forget about the buffers it handed up to the<br />

MUX. When the upper layers are done with the data, they free the buffers back to<br />

the driver’s memory pool.<br />

This system is implicitly a buffer loaning system. If a device cannot receive data<br />

directly into clusters, it must first allocate its own memory (apart from a network<br />

buffer pool) and explicitly copy the data from its private memory into a cluster<br />

before passing it in an mBlk up to the MUX.<br />

H.3.3 Using Private Memory Management Routines<br />

If your device does not allow you to use the MUX memory-management utilities,<br />

you can write replacements for the ones provided by netBufLib. However, your<br />

replacements must conform to the API for these routines.<br />

H.3.4 Supporting Scatter-Gather in Your Driver<br />

Some devices support breaking up a single network packet into separate chunks<br />

of memory. This makes it possible to pass a packet (such as a list of mbufs from a<br />

Berkeley-type TCP/IP protocol) as a chain of mBlk/clBlk/cluster constructs.<br />

When a driver gets a chain of mBlks, it can decide at that point to transmit the<br />

clusters in the chain in any way it likes. If it can do a gather-write, then it need not<br />

do any data copying. If it cannot, then it has to put all of the data from the chain<br />

into a single memory area before transmitting it. This decision is driven by the type<br />

of network device for which the driver is implemented.<br />

H.4 Indicating Error Conditions<br />

Sometimes an END encounters errors or other events that are of interest to the<br />

protocols using that END. For example, the device could have gone down, or the<br />

280


H<br />

Implementing a MUX-Based Network Interface Driver<br />

device was down but is now back on line. When such situations arise, the END<br />

should call muxError( ). This routine passes error information up to the MUX,<br />

which, in turn, passes the information on to all protocols that have registered a<br />

routine to receive it. The muxError( ) routine is declared as follows:<br />

void muxError<br />

(<br />

void* pCookie, /* pointer to END_OBJ */<br />

END_ERR* pError /* pointer to END_ERR structure */<br />

)<br />

Among its input, this routine expects a pointer to an end_err structure, which is<br />

declared in end.h as follows:<br />

typedef struct end_err<br />

{<br />

INT32 errCode; /* error code, see above */<br />

char* pMesg; /* NULL-terminated error message, can be NULL */<br />

void* pSpare; /* pointer to user defined data, can be NULL */<br />

} END_ERR;<br />

The error-receive routine that the protocol registers with the MUX must be of the<br />

following prototype:<br />

void xxError<br />

(<br />

END_OBJ* pEnd, /* pointer to END_OBJ */<br />

END_ERR* pError, /* pointer to END_ERR */<br />

void* pSpare /* pointer to protocol private data passed in muxBind */<br />

)<br />

The errCode member of an end_err structure is 32 bits long. Wind River reserves<br />

the lower 16 bits of errCode for its own error messages. However, the upper 16 bits<br />

are available to user applications. Use these bits to encode whatever error<br />

messages you need to pass between drivers and protocols. The currently defined<br />

error codes are as follows:<br />

H<br />

#define END_ERR_INFO 1 /* information only */<br />

#define END_ERR_WARN 2 /* warning */<br />

#define END_ERR_RESET 3 /* device has reset */<br />

#define END_ERR_DOWN 4 /* device has gone down */<br />

#define END_ERR_UP 5 /* device has come back on line */<br />

#define END_ERR_FLAGS 6 /* device flags have changed */<br />

#define END_ERR_NO_BUF 7 /* device’s cluster pool is exhausted */<br />

281


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

These error codes have the following meaning:<br />

END_ERR_INFO<br />

This error is information only.<br />

END_ERR_WARN<br />

A non-fatal error has occurred.<br />

END_ERR_RESET<br />

An error occurred that forced the device to reset itself, but the device has<br />

recovered.<br />

END_ERR_DOWN<br />

A fatal error occurred that forced the device to go down. The device can no<br />

longer send or receive packets.<br />

END_ERR_UP<br />

The device was down but is now up again and can receive and send packets.<br />

END_ERR_BLOCK<br />

The device is busy, the transaction should be tried again later.<br />

END_ERR_FLAGS<br />

The device flags have changed.<br />

END_ERR_NO_BUF<br />

The device’s cluster pool is exhausted.<br />

H.5 Required Driver Entry Points and Structures<br />

This section describes the API for an END. It describes the structures that are<br />

essential to such a driver and the entry points you must implement in the driver.<br />

NOTE: The organization of an END does not follow the model for a standard<br />

VxWorks I/O driver. The driver is not accessible through the open( ) routine or<br />

other file I/O routines. The driver is organized to communicate with the MUX. The<br />

MUX then handles communication with the network protocols.<br />

282


H<br />

Implementing a MUX-Based Network Interface Driver<br />

H.5.1 Required Structures for a Driver<br />

Within your driver, you must allocate and initialize an END_OBJ. Your driver also<br />

needs to allocate and initialize the structures referenced in END_OBJ structures,<br />

such as DEV_OBJ, NET_FUNCS, and M2_INTERFACETBL. To pass packets up to the<br />

MUX, use an mBlk structure.<br />

Providing Network Device Abstraction: END_OBJ<br />

Your endLoad( ) entry point must allocate, initialize, and return an END_OBJ<br />

structure. The MUX uses this END_OBJ structure as a place to store the tools it<br />

needs to manipulate the stack and the device driver. These tools include data as<br />

well as pointers to functions. The END_OBJ structure is defined in end.h as follows:<br />

typedef struct end_object<br />

{<br />

NODE node; /* root of the device hierarchy */<br />

DEV_OBJ devObject; /* accesses your device’s ctrl struct */<br />

FUNCPTR receiveRtn; /* routine to call on reception */<br />

BOOL attached; /* indicates unit is attached */<br />

SEM_ID txSem; /* transmitter semaphore */<br />

long flags; /* various flags */<br />

struct net_funcs *pFuncTable; /* function table */<br />

M2_INTERFACETBL mib2Tbl; /* MIBII counters */<br />

struct ETHER_MULTI *pAddrList; /* head of the multicast address list */<br />

int nMulti; /* number of elements in the list */<br />

LIST protocols; /* protocol node list */<br />

BOOL snarfProto; /* is someone snarfing us? */<br />

void* pMemPool; /* memory cookie used by MUX bufr mgr. */<br />

M2_ID* pMib2Tbl; /* RFC 2233 MIB objects */<br />

} END_OBJ;<br />

H<br />

Your driver must set and manage some of these members. Other members are<br />

MUX-managed. To know which are which, read the following member<br />

descriptions:<br />

node<br />

The root of the device hierarchy. The MUX sets the value of this member. Your<br />

driver should treat it as opaque.<br />

devObject<br />

The DEV_OBJ structure for this device. Your driver must set this value at load<br />

time. See Tracking Your Device’s Control Structure: DEV_OBJ, p.285.<br />

receiveRtn<br />

A function pointer that references a muxReceive( ) function. The MUX<br />

supplies this pointer by the completion of the muxDevLoad( ) call that loads<br />

283


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

this driver. Your driver uses this function pointer to pass data up to the<br />

protocol.<br />

attached<br />

A BOOL indicating whether or not the device is attached. The MUX sets and<br />

manages this value.<br />

txSem<br />

A semaphore that controls access to this device’s transmission facilities. The<br />

MUX sets and manages this value.<br />

flags<br />

A value constructed from ORing in IFF_* flag constants. Except for IFF_LOAN<br />

and IFF_SCAT, these constants are the same IFF_* flags associated with the<br />

TCP/IP stack.<br />

IFF_UP<br />

IFF_BROADCAST<br />

IFF_DEBUG<br />

IFF_LOOPBACK<br />

IFF_POINTOPOINT<br />

IFF_NOTRAILERS<br />

IFF_RUNNING<br />

IFF_NOARP<br />

IFF_PROMISC<br />

IFF_ALLMULTI<br />

IFF_OACTIVE<br />

IFF_SIMPLEX<br />

IFF_LINK0<br />

IFF_LINK1<br />

IFF_LINK2<br />

IFF_MULTICAST<br />

IFF_LOAN<br />

IFF_SCAT<br />

The interface driver is up.<br />

The broadcast address is valid.<br />

Debugging is on.<br />

This is a loopback net.<br />

The interface is a point-to-point link.<br />

The device must avoid using trailers.<br />

The device has successfully allocated needed<br />

resources.<br />

There is no address resolution protocol.<br />

This device receives all packets. n<br />

This device receives all multicast packets.<br />

Transmission in progress.<br />

The device cannot hear its own transmissions.<br />

A per link layer defined bit.<br />

A per link layer defined bit.<br />

A per link layer defined bit.<br />

The device supports multicast.<br />

The device supports buffer loaning.<br />

The device supports scatter/gather.<br />

pFuncTable<br />

A pointer to a net_funcs structure. This structure contains function pointers to<br />

your driver’s entry points for handling standard requests such as unload or<br />

send. Your driver must allocate and initialize this structure when the device is<br />

loaded. See Identifying the Entry Points into Your Network Driver: NET_FUNCS,<br />

p.286.<br />

284


H<br />

Implementing a MUX-Based Network Interface Driver<br />

mib2Tbl<br />

An M2_INTERFACETBL structure for tracking the MIB-II variables used in<br />

your driver. Your driver must initialize the structure referenced here, although<br />

both your driver and the MUX will later adjust the values stored in the table.<br />

NOTE: The mib2Tbl field is retained for backwards compatibility with RFC 1213.<br />

It is not recommended for new drivers. For new drivers, use the RFC 2233<br />

interface. For more information, see H.7 Converting an END Driver from RFC 1213<br />

to RFC 2233, p.311.<br />

pAddrList<br />

A pointer to the head of a list of multicast addresses. The MUX sets and<br />

manages this list, but it uses your driver’s endMCastAddrAdd( ),<br />

endMCastAddrDel( ), and endMCastAddrGet( ) entry points to do so.<br />

nMulti<br />

A value indicating the number of addresses on the list referenced in the<br />

multiList member. The MUX sets this value using the information returned by<br />

your driver’s endMCastAddrGet( ).<br />

protocols<br />

The head of the list of protocols that have bound themselves to this network<br />

driver. The MUX manages this list.<br />

snarfProto<br />

A BOOL indicating whether a packet-snarfing protocol has bound itself to this<br />

driver. Such a protocol can prevent the packet from passing on to lower<br />

priority protocols (see Snarfing Protocols Block Packets to Lower Priority Protocols,<br />

p.302). The MUX sets and manages this value.<br />

pMemPool<br />

A pointer to a netBufLib-managed memory pool. The MUX sets the value of<br />

this member. Treat it as opaque.<br />

pMib2Tbl<br />

The interface table for RFC 2233 compliance.<br />

H<br />

Tracking Your Device’s Control Structure: DEV_OBJ<br />

Your driver uses the DEV_OBJ structure to tell the MUX the name of your device<br />

and to hand the MUX a pointer to your device’s control structure. This control<br />

structure is a device-specific structure that you define according to your needs.<br />

Your driver uses this control structure to track things such as flags, memory pool<br />

285


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

addresses, and so on. The information stored in the control structure is typically<br />

essential to just about every driver entry point. The DEV_OBJ structure is defined<br />

in end.h as follows:<br />

typedef struct dev_obj<br />

{<br />

char name[END_NAME_MAX]; /* device name */<br />

int unit; /* to support multiple units */<br />

char description[END_DESC_MAX]; /* text description */<br />

void* pDevice; /* pointer back to the device data. */<br />

} DEV_OBJ;<br />

name<br />

A pointer to a string of up to eight characters. This string specifies the name for<br />

this network device.<br />

pDevice<br />

A pointer to your driver’s internal control structure. To preserve the<br />

separation of the protocol and data link layers, the MUX treats the pDevice<br />

pointer as opaque. Thus, the MUX never needs know anything about your<br />

control structure. However, when calling your driver’s entry points, the MUX<br />

passes in a cookie (in all calls except the endLoad( ) call). This cookie is a<br />

pointer to the END_OBJ that you allocated in endLoad( ). Through this cookie,<br />

your entry point can get to its device control structure in<br />

pCookie.devObject.pDevice.<br />

unit<br />

This is the unit number for the particular named device. Unit numbers start at<br />

0 and increase for every device controlled by the same driver. For example, if<br />

a system has two Lance Ethernet devices (named ln) then the first one is ln0<br />

and the second is ln1. If the same system also has a DEC 21x40 Ethernet then<br />

that device (whose name is dc) is dc0.<br />

description<br />

This is a text description of the device driver. For example, the Lance Ethernet<br />

driver puts the string, “AMD 7990 Lance Ethernet Enhanced Network Driver”<br />

into this location. This string is displayed if muxShow( ) is called.<br />

Identifying the Entry Points into Your Network Driver: NET_FUNCS<br />

The MUX uses the NET_FUNCS structure to maintain a table of entry points into<br />

your END. The NET_FUNCS structure is defined as follows:<br />

286


H<br />

Implementing a MUX-Based Network Interface Driver<br />

typedef struct net_funcs<br />

{<br />

STATUS (*start) (void*); /* driver’s start func */<br />

STATUS (*stop) (void*); /* driver’s stop func */<br />

STATUS (*unload) (void*); /* Driver’s unload func */<br />

int (*ioctl) (void*, int, caddr_t); /* driver’s ioctl func */<br />

STATUS (*send) (void* , M_BLK_ID); /* driver’s send func */<br />

STATUS (*mCastAddrAdd) (void*, char*); /* driver’s mcast add func */<br />

STATUS (*mCastAddrDel) (void*, char*); /* driver’s mcast delete func */<br />

STATUS (*mCastAddrGet) (void*, MULTI_TABLE*);<br />

/* driver’s mcast get fun. */<br />

STATUS (*pollSend) (void*, M_BLK_ID); /* driver’s poll send func */<br />

STATUS (*pollRcv) (void*, M_BLK_ID); /* driver’s poll receive func */<br />

STATUS (*addressForm) (M_BLK_ID, M_BLK_ID, M_BLK_ID);<br />

/* driver’s addr formation func */<br />

STATUS (*packetDataGet) (M_BLK_ID, M_BLK_ID);<br />

/* driver’s pkt data get func */<br />

STATUS (*addrGet) (M_BLK_ID, M_BLK_ID, M_BLK_ID, M_BLK_ID, M_BLK_ID);<br />

/* driver’s pkt addr get func */<br />

} NET_FUNCS;<br />

Within your endLoad( ), initialize these members to point to the appropriate<br />

driver entry points. Thus, start should contain a pointer to your endStart( ), stop<br />

to your endStop( ), unload to your endUnload( ), and so on.<br />

Tracking Link-Level Information: LL_HDR_INFO<br />

The MUX uses LL_HDR_INFO structures to keep track of link-level header<br />

information associated with packets passed from an END to the MUX and from<br />

there up to a protocol. An LL_HDR_INFO structure is passed as an argument to all<br />

stack receive routines (see, Passing a Packet Up to the Protocol: stackRcvRtn( ), p.307).<br />

H<br />

typedef struct llHdrInfo<br />

{<br />

int destAddrOffset; /* destination addr offset in mBlk */<br />

int destSize; /* destination address size */<br />

int srcAddrOffset; /* source address offset in mBlk */<br />

int srcSize; /* source address size */<br />

int ctrlAddrOffset; /* control info offset in mBlk */<br />

int ctrlSize; /* control info size */<br />

int pktType; /* type of the packet */<br />

int dataOffset; /* data offset in the mBlk */<br />

} LL_HDR_INFO;<br />

destAddrOffset<br />

Offset into mBlk structure at which the destination address starts.<br />

destSize<br />

Size of destination address.<br />

287


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

srcAddrOffset<br />

Offset into mBlk structure at which the source address starts.<br />

srcSize<br />

Size of source address.<br />

ctrlAddrOffset<br />

Reserved for future use.<br />

ctrlSize<br />

Reserved for future use.<br />

pktType<br />

Type of packet. For a list of valid packet types, see RFC 1700.<br />

dataOffset<br />

Offset into mBlk structure at which the packet data starts.<br />

Tracking Data That Passes Between the Driver and the Protocol: mBlk<br />

Use mBlk structures as a vehicle for passing packets between the driver and<br />

protocol layers. The mBlk structure is defined in netBufLib.h as follows:<br />

typedef struct mBlk<br />

{<br />

M_BLK_HDR mBlkHdr; /* header */<br />

M_PKT_HDR mBlkPktHdr; /* pkthdr */<br />

CL_BLK * pClBlk; /* pointer to cluster blk */<br />

} M_BLK;<br />

mBlkHdr<br />

Contains a pointer to an mHdr structure. For the most part, you should have<br />

no need to access or set this member directly and can treat it as opaque. The<br />

only exception is when you must chain this mBlk to another. In that case, you<br />

need to set the value of mBlk.mHdr.mNext or mBlk.mBlkHdr.mNextPkt or<br />

both. Use mBlk.mBlkHdr.mNext to point to the next mBlk in a chain of<br />

mBlks. Use mBlk.mHdr.mNextPkt to point to an mBlk that contains the head<br />

of the next packet.<br />

mBlkPktHdr<br />

Contains a pointer to an pktHdr structure. You should have no need to access<br />

or set this member directly and can treat it as opaque.<br />

pClBlk<br />

Contains a pointer to an clBlk structure. You should have no need to access or<br />

set this member directly and can treat it as opaque. However, if you are not<br />

288


H<br />

Implementing a MUX-Based Network Interface Driver<br />

using netBufLib to manage the driver’s memory pool, you must provide your<br />

own memory free routine for its associated cluster. To do this, you must update<br />

mBlk.pClBlk.pClFreeRtn to point to your customized free routine. This<br />

routine must use the same API as the netBufLib free routine. This means that<br />

the mBlk.pClBlk.pFreeArg1, mBlk.pClBlk.pFreeArg2, and<br />

mBlk.pClBlk.pFreeArg3 members must also be updated.<br />

Setting appropriate values for the members shown above (and the members of all<br />

the referenced structures) is just a matter of calling the appropriate netBufLib<br />

routines for the creation of an mBlk/clBlk/cluster construct. For more<br />

information, see H.3.1 Setting Up and Using a Memory Pool for Receive and Transmit<br />

Buffers, p.276.<br />

H.5.2 Required Driver Entry Points<br />

The names of all entry points described in this section begin with the prefix end.<br />

This indicates that they are generic driver entry points. Within your particular<br />

network driver, the specific entry points should use a prefix that indicates the<br />

driver of which they are a part. For example, you would use an ln prefix in the<br />

entry points associated with the AMD Lance driver. Thus, your network interface<br />

driver would define the entry points lnLoad( ), lnUnload( ), lnReceive( ), and so<br />

on.<br />

This naming convention for driver entry point is a matter of good coding practice.<br />

Because VxWorks references these entry points using the function pointers you<br />

loaded into a NET_FUNCS structure, you are free to follow other conventions for<br />

assigning names to entry points.<br />

H<br />

Table H-1<br />

Required Driver Entry Points<br />

Routine<br />

endLoad( )<br />

endUnload( )<br />

endStart( )<br />

endStop( )<br />

endSend( )<br />

endIoctl( )<br />

endMCastAddrAdd( )<br />

Purpose<br />

Initialize the driver and load it into the MUX.<br />

Free driver resources.<br />

Start the driver.<br />

Stop the driver.<br />

Send a packet out on the hardware.<br />

Access driver control functions.<br />

Add an address to the device’s multicast address list.<br />

289


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Table H-1<br />

Required Driver Entry Points (Continued)<br />

Routine<br />

endMCastAddrDel( )<br />

endMCastAddrGet( )<br />

endPollSend( )<br />

endPollReceive( )<br />

endAddressForm( )<br />

endPacketDataGet( )<br />

endPacketAddrGet( )<br />

Purpose<br />

Delete an address from the device’s multicast address list.<br />

Get the list of multicast addresses maintained for this device.<br />

Do a polling send.<br />

Do a polling receive.<br />

Add the appropriate link-level information into a mBlk in<br />

preparation for transmission.<br />

Extract packet data (omitting link-level information) from one<br />

mBlk and write it to another.<br />

Extract address information (omitting packet data) from one<br />

mBlk and write out each source and destination address to its<br />

own mBlk. For an Ethernet packet, this requires two output<br />

mBlks. However, for some non-Ethernet packets, this could<br />

require as many as four output mBlks because the local source<br />

and destination addresses can differ from the ultimate source and<br />

destination addresses.<br />

! WARNING: If you are porting a driver from the BSD 4.3 model, you might be<br />

tempted to use the existing xxIoctl( ) entry point as your endIoctl( ) entry point,<br />

skipping the creation of separate entry points for the various MCastAddr entry<br />

points. Do not do this. Your driver must implement all entry points shown in<br />

Table H-1.<br />

Loading the Device: endLoad( )<br />

Your endLoad( ) entry point serves the same function that the attach( ) entry points<br />

do under the 4.3 BSD based system. endLoad( ) is the initial entry point into every<br />

network interface driver. The tUserRoot task specifies your endLoad( ) as an input<br />

parameter when it calls muxDevLoad( ) to load your driver.<br />

Your endLoad( ) must take the following form:<br />

290


H<br />

Implementing a MUX-Based Network Interface Driver<br />

END_OBJ* endLoad<br />

(<br />

char* initString<br />

)<br />

/* a string encoded for the device to use for its<br />

/* initialization arguments. */<br />

Within your endLoad( ), you must handle any device-specific initialization. You<br />

should also set values for most of the members of the END_OBJ. Of particular<br />

interest are the END_OBJ members receiveRtn, pFuncTable, and devObject. See<br />

the member descriptions provided in Providing Network Device Abstraction:<br />

END_OBJ, p.283.<br />

endLoad( ) should return a pointer to an initialized END_OBJ structure. If an error<br />

occurred, return ERROR.<br />

The parameter is:<br />

initString<br />

Passes in any initialization arguments needed.<br />

Unloading the Device: endUnload( )<br />

Your endUnload( ) entry point should handle everything needed to remove this<br />

network driver from the system. Within your endUnload( ), you should handle<br />

things such as cleanup for all the local data-structures. Your endUnload( ) does not<br />

need to worry about notifying protocols about unloading the device. Before calling<br />

your endUnload( ), the MUX sends a shutdown notice to each protocol attached to<br />

the device.<br />

Your endUnload( ) must take the following form:<br />

H<br />

void endUnload<br />

(<br />

void* pCookie /* pointer to device-identifying END_OBJ */<br />

)<br />

This function is declared as void and thus should return no function value.<br />

The parameters are:<br />

pCookie<br />

Passes a pointer to the END_OBJ structure returned by endLoad( ). In your<br />

endUnload( ), you will probably want to free its associated memory.<br />

Be sure to delete any semaphores that were created in the driver.<br />

291


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Providing an Opaque Control Interface to Your Driver: endIoctl( )<br />

Your endIoctl( ) entry point should handle all requests for changes to the state of<br />

the device, such as bringing it up, shutting it down, turning on promiscuous mode,<br />

and so on. You can also use your endIoctl( ) is to provide access to MIB-II interface<br />

statistics.<br />

! WARNING: If you are porting a driver from the BSD 4.3 model, you might be<br />

tempted to use the existing xxIoctl( ) entry point as your endIoctl( ) entry point,<br />

skipping the creation of separate entry points for the MCastAddr entry points. Do<br />

not do this! Your driver must implement all entry points shown in Table H-1.<br />

Your endIoctl( ) must take the following form:<br />

STATUS endIoctl<br />

(<br />

void* pCookie, /* pointer to device-identifying END_OBJ */<br />

int cmd, /* value identifying command */<br />

caddr_t data /* data needed to complete command */<br />

)<br />

This function should return OK or ERROR. If an error occurs, it should set errno.<br />

The parameters are:<br />

pCookie<br />

Passes a pointer to the END_OBJ structure returned by endLoad( ).<br />

cmd<br />

Can pass any of the values shown in the first column of Table H-2. Your<br />

endIoctl( ) must have an appropriate response to each.<br />

data<br />

Passes the data or a pointer to the data that your endIoctl( ) needs to carry out<br />

the command specified in cmd.<br />

Table H-2<br />

Ioctl Commands and Data Types<br />

Command Function Data Type<br />

EIOCSFLAGS Set device flags. int; see description of<br />

END_OBJ.flags (flags, p.284)<br />

EIOCGFLAGS Get device flags. int<br />

EIOCSADDR Set device address. char*<br />

EIOCGADDR Get device address. char*<br />

292


H<br />

Implementing a MUX-Based Network Interface Driver<br />

Table H-2<br />

Ioctl Commands and Data Types (Continued)<br />

Command Function Data Type<br />

EIOCMULTIADD Add multicast address. char*<br />

EIOCMULTIDEL Delete multicast address. char*<br />

EIOCMULTIGET Get multicast list. MULTI_TABLE*<br />

EIOCPOLLSTART Set device into polling mode. NULL<br />

EIOCPOLLSTOP Set device into interrupt mode. NULL<br />

EIOCGFBUF Get minimum first buffer for chaining. int<br />

EIOCGMIB2<br />

Get the MIB-II counters from the<br />

driver.<br />

M2_INTERFACETBL*<br />

Sending Data Out on the Device: endSend( )<br />

The MUX calls your endSend( ) entry point when it has data to send out on the<br />

device. Your endSend( ) must take the following form:<br />

STATUS endSend<br />

(<br />

void* pCookie, /* device structure */<br />

M_BLK_ID pMblk, /* data to send */<br />

)<br />

This function should return OK, ERROR, or END_ERR_BLOCK.<br />

The value END_ERROR_BLOCK should be returned if the packet cannot be<br />

transmitted at this time because it is in polling mode, or because of a lack of<br />

resources. In either case, the packet is not freed from the mBlk chain.<br />

The value OK is returned upon successful acceptance of the data packet. If an error<br />

occurs then ERROR is returned and errno should be set. In these cases, the data<br />

packet is freed from the mBlk chain.<br />

The parameters are:<br />

pCookie<br />

Passes a pointer to the END_OBJ structure returned by endLoad( ).<br />

H<br />

293


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

pMblk<br />

Passes a pointer to an mBlk structure containing the data you want to send.<br />

For more information on how to setup an mBlk, see H.3.1 Setting Up and Using<br />

a Memory Pool for Receive and Transmit Buffers, p.276.<br />

Starting a Stopped but Loaded Driver: endStart( )<br />

Your endStart( ) entry point should do whatever is necessary to make the driver<br />

active. For example, it should register your device driver’s interrupt service<br />

routine.Your endStart( ) must take the following form:<br />

Status endStart<br />

(<br />

void* pCookie /* pointer to device-identifying END_OBJ structure */<br />

)<br />

This function should return OK or ERROR. If an error occurs, it should set errno.<br />

The parameters are:<br />

pCookie<br />

Passes a pointer to the END_OBJ structure returned by endLoad( ).<br />

However, your endStart( ) should probably include this pointer as a<br />

parameter to the sysIntConnect( ) call that it uses to register your ISR. Your<br />

ISR might not have any direct use for this END_OBJ pointer, but it should pass<br />

it in to the driver entry point that handles task-level processing for packet<br />

reception.<br />

When it comes time to pass the packet up to the MUX, your driver must call<br />

the MUX-supplied function referenced in pCookie.receiveRtn. See Providing<br />

Network Device Abstraction: END_OBJ, p.283.<br />

Stopping the Driver Without Unloading It: endStop( )<br />

Your endStop( ) entry point can assume that the driver is already loaded and that<br />

somebody has already called endLoad( ). Within your endStop( ), you should do<br />

whatever is necessary to make the driver inactive without actually unloading the<br />

driver. Your endStop( ) must take the following form:<br />

STATUS endStop<br />

(<br />

void* pCookie /* pointer to a device-identifying END_OBJ structure */<br />

)<br />

294


H<br />

Implementing a MUX-Based Network Interface Driver<br />

This function should return OK or ERROR. If an error occurs, it should set errno.<br />

The parameters are:<br />

pCookie<br />

Passes in a pointer to the END_OBJ structure returned by endLoad( ).<br />

Handling a Polling Send: endPollSend( )<br />

Your endPollSend( ) is used by any task (such as the debug agent) that wants to<br />

do a polling send. Thus, your endPollSend( ) must be able to put a packet directly<br />

onto the network stack without queuing a packet on an output queue.<br />

NOTE: When the system calls your endPollSend( ), it is probably in a mode that<br />

cannot service kernel calls. Thus, this entry point should not call any kernel<br />

functions, such as taking a semaphore or allocating memory. Likewise, this entry<br />

point should not block or busy wait because that would probably hang the entire<br />

system.<br />

Your endPollSend( ) must take the following form:<br />

STATUS endPollSend<br />

(<br />

void* pCookie, /* device structure */<br />

M_BLK_ID pMblk, /* data to send */<br />

)<br />

Within your endPollSend( ), check that the device is set to polled mode (by a<br />

previous endIoctl( ) call). Your endPollSend( ) should then put the packet (passed<br />

using pNBuff) directly onto the network. Your endPollSend( ) bypasses queuing<br />

the packet on any output queue.<br />

This function should return OK or ERROR. If an error occurs, it should set errno.<br />

The parameters are:<br />

pCookie<br />

Passes a pointer to the END_OBJ structure returned by endLoad( ).<br />

pMblk<br />

Passes a pointer to an mBlk structure containing the data you want to send.<br />

For information on setting up an mBlk, see H.3.1 Setting Up and Using a<br />

Memory Pool for Receive and Transmit Buffers, p.276.<br />

H<br />

295


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Handling a Polling Receive: endPollReceive( )<br />

Your endPollReceive( ) is used by any task (such as the debug agent) that wants<br />

to do a polling receive.<br />

NOTE: When the system calls your endPollReceive( ), it is probably in a mode that<br />

cannot service kernel calls. Thus, this entry point should not call any kernel<br />

functions, such as taking a semaphore or allocating memory. Likewise, this entry<br />

point should not block or busy wait because that would probably hang the entire<br />

system.<br />

Your endPollReceive( ) must take the following form:<br />

int endPollReceive<br />

(<br />

void* pCookie, /* device structure */<br />

M_BLK_ID pMblk /* place to return the data */<br />

)<br />

Your endPollReceive( ) should check that the device is set to polled mode (by a<br />

previous endIoctl( ) call). Your endPollReceive( ) should then get a packet directly<br />

from the network and copy it to the mBlk passed in by the pMblk parameter.<br />

Your endPollReceive( ) entry point should return OK or an appropriate error<br />

value. One likely error return value is EAGAIN. Your endPollReceive( ) should<br />

return EAGAIN if the submitted mBlk was not big enough to contain the received<br />

packet, or if no packet is available.<br />

The parameters are:<br />

pCookie<br />

Passes a pointer to the END_OBJ structure returned by endLoad( ).<br />

pMblk<br />

Passes in a pointer to an mBlk structure. This parameter is an output<br />

parameter. Your endPollReceive( ) must copy the data from the stack to the<br />

mBlk structure referenced here.<br />

Adding a Multicast Address: endMCastAddrAdd( )<br />

Your endMCastAddAddr( ) entry point must add an address to the multicast table<br />

that is maintained by the device. Your endMCastAddAddr( ) must take the<br />

following form:<br />

296


H<br />

Implementing a MUX-Based Network Interface Driver<br />

STATUS endMCastAddAddr<br />

(<br />

void* pCookie, /* pointer to a device-identifying END_OBJ structure */<br />

char* pAddress /* pointer to address to add */<br />

)<br />

To help you manage a list of multicast addresses, VxWorks provides the library<br />

etherMultiLib.<br />

This function should return OK or ERROR. If an error occurs, it should set errno.<br />

The parameters are:<br />

pCookie<br />

Passes in a pointer to the END_OBJ structure returned by endLoad( ).<br />

pAddress<br />

Passes in a pointer to the address you want to add to the list. To help you<br />

manage a list of multicast addresses, VxWorks includes the library,<br />

etherMultiLib.<br />

Within your endMCastAddrAdd( ), you must reconfigure the interface in a<br />

hardware-specific way. This reconfiguration should let the driver receive<br />

frames from the specified address and then pass those frames up to the higher<br />

layer.<br />

Deleting a Multicast Address: endMCastAddrDel( )<br />

Your endMCastAddrDel( ) entry point must delete an address from the multicast<br />

table maintained by the device. Your endMCastAddrDel( ) must take the<br />

following form:<br />

H<br />

STATUS endMCastDelAddr<br />

(<br />

void* pCookie, /* pointer to a device-identifying END_OBJ structure */<br />

char* pAddress /* pointer to address to delete */<br />

)<br />

This function should return OK or ERROR. If an error occurred, it should set errno.<br />

The parameters are:<br />

pCookie<br />

Passes a pointer to the END_OBJ structure returned by endLoad( ).<br />

pAddress<br />

Passes a pointer to the address you must delete. To help you manage a list of<br />

multicast addresses, VxWorks includes the library, etherMultiLib.<br />

297


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Your endMCastAddrDel( ) must also reconfigure the driver (in a<br />

hardware-specific way) so that the driver longer receives frames with the<br />

specified address.<br />

Getting the Multicast Address Table: endMCastAddrGet( )<br />

Your endMCastAddrGet( ) must get a table of multicast addresses and return it in<br />

the buffer referenced in the pMultiTable parameter. These addresses are the list of<br />

multicast addresses to which the interface is currently listening. Your<br />

endMCastAddrGet( ) must take the following form:<br />

STATUS endMCastGetAddr<br />

(<br />

void* pCookie,<br />

MULTI_TABLE* pMultiTable<br />

)<br />

To get the list of multicast address, use the routines provided in etherMultiLib.<br />

This function should return OK or ERROR. If an error occurs, it should set errno.<br />

The parameters are:<br />

pCookie<br />

Passes in a pointer to the END_OBJ structure you returned from your<br />

endLoad( ).<br />

pMultiTable<br />

Passes in a pointer to a buffer. This is an output parameter. Your<br />

endMCastAddrGet( ) must write a MULTI_TABLE structure into the<br />

referenced buffer. end.h defines MULTI_TABLE as follows:<br />

typedef struct<br />

{<br />

long len; /* length of table in bytes */<br />

char *pTable; /* pointer to entries */<br />

} MULTI_TABLE;<br />

Modify the len member of the MULTI_TABLE to indicate just how many<br />

addresses you are returning. Write the addresses to the buffer referenced in the<br />

pTable member of the MULTI_TABLE.<br />

298


H<br />

Implementing a MUX-Based Network Interface Driver<br />

Forming an Address into a Packet for Transmission: endAddressForm( )<br />

The endAddressForm( ) routine must take a source address and a destination<br />

address and copy the information into the data portion of the mBlk structure in a<br />

fashion appropriate to the link level. Implementing this functionality is the<br />

responsibility of the driver writer, although some common cases are provided for<br />

in endLib. After adding the addresses to mBlk, your endAddressForm( ) routine<br />

should adjust the mBlk.mBlkHdr.mLen and mBlk.mBlkHdr.mData members<br />

accordingly. This routine must take the following form:<br />

M_BLK_ID endAddressForm<br />

(<br />

M_BLK_ID pMblk, /* packet data */<br />

M_BLK_ID pSrcAddress, /* source address */<br />

M_BLK_ID pDstAddress /* destination address */<br />

)<br />

This function returns an M_BLK_ID, which is potentially the head of a chain of<br />

mBlk structures.<br />

If the cluster referenced by pMblk does not have enough room to contain both the<br />

header and the packet data, this routine must reserve an additional<br />

mBlk/clBlk/cluster construct to contain the header. This routine must then chain<br />

the mBlk in pMblk onto the just-reserved header mBlk and returns a pointer to the<br />

header mBlk as the function value.<br />

The parameters are:<br />

pMblk<br />

The mBlk that contains the packet to be transmitted.<br />

pSrcAddress<br />

The mBlk that contains the link-level address of the source.<br />

pDstAddress<br />

The mBlk that contains the link-level address of the destination.<br />

H<br />

Getting a Data-Only mBlk: endPacketDataGet( )<br />

This routine must provide a duplicate mBlk that contains packet data in the<br />

original but skips the header information. Some common cases are provided for in<br />

endLib. This routine should return OK or ERROR and set errno if an error occurs.<br />

299


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

The routine is of the following form:<br />

STATUS endPacketDataGet<br />

(<br />

M_BLK_ID pBuff, /* packet data and address information */<br />

LL_HDR_INFO* pLinkHdrInfo /* structure to hold link-level info. */<br />

)<br />

The parameters are:<br />

pBuff<br />

Expects a pointer to the mBlk that still contains both header and packet data.<br />

pLinkHdrInfo<br />

Returns an LL_HDR_INFO structure containing header information that is<br />

dependent upon the particular data-link layer that the END implements. For<br />

more information, see Tracking Link-Level Information: LL_HDR_INFO, p.287.<br />

Return Addressing Information: endPacketAddrGet( )<br />

This routine must retrieve the address information associated with a packet. Some<br />

common cases are provided in endLib. The last two parameters are used for<br />

networks where the hardware source and destination addresses at the ultimate<br />

endpoint can differ from the local source and destination addresses. This routine<br />

should return OK or ERROR. If there is an error, it must set errno.<br />

The routine is of the following form:<br />

STATUS endPacketAddrGet<br />

(<br />

M_BLK_ID pMblk, /* M_BLK_ID of the packet */<br />

M_BLK_ID pSrc, /* local source of packet */<br />

M_BLK_ID pDst, /* local destination of packet */<br />

M_BLK_ID pESrc, /* end source of packet */<br />

M_BLK_ID pEDst /* end destination of packet */<br />

)<br />

pMblk<br />

Expects a pointer to the mBlk structure from which you want to extract<br />

address information.<br />

pSrc<br />

Expects NULL or a pointer to the mBlk structure into which to write the<br />

extracted source address (local) of the packet.<br />

300


H<br />

Implementing a MUX-Based Network Interface Driver<br />

pDst<br />

Expects NULL or a pointer to the mBlk structure into which to write the<br />

extracted destination address (local) of the packet.<br />

pESrc<br />

Expects NULL or a pointer to the mBlk structure into which to write the<br />

extracted source address (end, if different) of the packet.end source of packet.<br />

pEDst<br />

Expects NULL or a pointer to the mBlk structure into which to write the<br />

extracted destination address (end, if different) of the packet.<br />

H.6 Writing Protocols That Use the MUX API<br />

This section describes how to port protocols to the MUX-based model. As shown<br />

in Figure H-1, MUX-based protocols bind themselves to the MUX from above and<br />

network interface drivers (ENDs) bind themselves to the MUX from below. Thus,<br />

a protocol is layered on top of the MUX, which is layered on top of a network<br />

interface driver. The responsibilities of each is given in Table H-3.<br />

Table H-3<br />

Layers and Responsibilities<br />

Layer<br />

Protocol<br />

MUX<br />

Network<br />

Interface Driver<br />

Responsibilities<br />

Interface to the transport layer, and, through it, to application programs.<br />

Copying packet data if needed.<br />

Loading and unloading drivers.<br />

Binding and unbinding protocols.<br />

Calling each bound protocol’s receive routine.<br />

Managing memory for buffer loaning.<br />

Dealing with hardware.<br />

Loading a driver into the system.<br />

Unloading a driver from the system.<br />

Loaning buffers to upper layers.<br />

H<br />

301


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

A protocol writer has to deal only with calls to the MUX. Everything<br />

device-specific is handled in the drivers of the data link layer, the layer below the<br />

MUX.<br />

Protocol Startup<br />

Each protocol that wants to receive packets must first attach itself to the MUX. To<br />

do this, the protocol calls muxBind( ). The returned function value is a “cookie”<br />

that identifies the network interface driver to which the MUX has bound the<br />

protocol. The protocol must save this cookie for use in subsequent calls to the<br />

MUX.<br />

As input to the muxBind( ), you must specify the name of a network device (for<br />

example, ln and 0, ln and 1, ei and 0, and so on), the appropriate receive, restart,<br />

and shutdown functions for the protocol, a protocol type (from RFC 1700), and a<br />

name for the attaching protocol.<br />

The MUX uses the protocol type to prioritize the protocols. This priority<br />

determines which protocol sees packets first. When a driver passes a packet up to<br />

the MUX, the driver includes a pointer to its END_OBJ structure. Included in this<br />

structure is the member, protocols, the head of the list of protocols (a list of<br />

NET_PROTOCOL structures) listening to this device. The order of the protocols in<br />

this list determines the order in which the protocols see the packet. Maintaining<br />

this list is the responsibility of the MUX.<br />

If a protocol specifies a type of MUX_PROTO_SNARF in its muxBind( ), the MUX<br />

adds the protocol to the top of the list in END_OBJ.protocols. At any given<br />

moment, the MUX allows only one active protocol of type MUX_PROTO_SNARF.If<br />

a protocol specifies a type of MUX_PROTO_PROMISC in its muxBind( ), the MUX<br />

adds the protocol to the bottom of the list in END_OBJ.protocols. If a protocol<br />

specifies any other type in its muxBind( ), the MUX adds the protocol to the list just<br />

after the MUX_PROTO_SNARF protocol (or the top of the list if there is no protocol<br />

of type MUX_PROTO_SNARF).<br />

This shuffling of protocols ensures that lower priority protocols cannot steal or<br />

damage a packet before a higher priority protocol gets to see the packet.<br />

Snarfing Protocols Block Packets to Lower Priority Protocols<br />

If the receive routine for a protocol returns TRUE, and, if the protocol is not of type<br />

MUX_PROTO_PROMISC, the MUX lets the protocol snarf the packet (that is, the<br />

MUX lets the protocol take delivery of the packet). If a protocol takes delivery of<br />

302


H<br />

Implementing a MUX-Based Network Interface Driver<br />

the packet, the MUX does not show the packet to any of the other protocols further<br />

down on the END_OBJ.protocols list.<br />

If you want a protocol to act as a firewall, the protocol should register as type<br />

MUX_PROTO_SNARF and should return TRUE from its receive function. If you<br />

want a protocol to see all uneaten packets that show up on the device, register the<br />

protocol with type MUX_PROTO_PROMISC.<br />

Protocols and Network Addressing<br />

The system is written to support both RFC 894 type Ethernet packets as well as<br />

802.3 encoded packets. If a protocol wants to use 802.3 style packets, it must<br />

register SAP (Service Access Point) as its protocol type. Otherwise, the protocol<br />

must use one of the accepted protocol types from RFC 1700.<br />

Output Protocols<br />

A single protocol can be bound to each device for the filtering of output packets.<br />

This functionality is provided for applications that want to look at every packet<br />

that is output on a particular device. The type MUX_PROTO_OUTPUT is passed<br />

into muxBind( ) when this protocol is registered. Only the stackRcvRtn parameter<br />

is valid with this type.<br />

Sending Data<br />

To put the appropriate address header information into the buffer, the protocol<br />

calls muxAddressForm( ). Finally, to send the packet, the protocol calls<br />

muxSend( ), passing in the cookie returned from the muxBind( ) as well as the<br />

mBlk that contains the packet it wants to send. The MUX then hands the packet to<br />

the driver.<br />

H<br />

Receiving Data<br />

In response to an interrupt from the network device, VxWorks executes the<br />

device’s previously registered interrupt service routine. This routine gets the<br />

packet off the device and queues it for processing the task level, where the driver<br />

prepares the packet for hand-off to the MUX. For a more detailed description of<br />

this process, see H.3 <strong>Guide</strong>lines for Handling Packet Reception in Your Driver, p.275.<br />

To hand the packet off to the MUX, the driver calls muxReceive( ). The<br />

muxReceive( ) routine determines the protocol type of the packet (0x800 for IP,<br />

303


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

0x806 for ARP, and so on) and then searches its protocol list to see if any have<br />

registered using this protocol type.<br />

If there is a protocol that can handle this packet, the MUX passes the packet into<br />

the stackRcvRtn( ) specified in the protocol’s muxBind( ) call. Before passing the<br />

packet to a numbered protocol (that is, a protocol that is neither a<br />

MUX_PROTO_SNARF nor a MUX_PROTO_PROMISC protocol) muxReceive( ) calls<br />

the muxPacketDataGet( ) routine and passes two mBlks into the protocol.<br />

The first mBlk contains all the link-level information. The second mBlk contains<br />

all the information that comes just after the link-level header. This partitioning of<br />

the data lets the protocol skip over the header information (it also breaks the BSD<br />

4.3 model at the do_protocol_with_type( ) interface). The protocol then takes over<br />

processing the packet.<br />

This new method of multiplexing received packets does away with the method<br />

based on the etherInputHook( ) and etherOutputHook( ) routines. If a protocol<br />

wants to see all the undelivered packets received on an interface, it specifies its<br />

type as MUX_PROTO_PROMISC.<br />

If a protocol needs to modify data received from the network, it should copy that<br />

data first. Because other protocols might also want to see the raw data, the data<br />

should not be modified in place (that is, in the received buffer).<br />

Supporting Scatter/Gather Devices<br />

Some devices support breaking up a single network packet into separate chunks<br />

of memory. This makes it possible to pass a packet down (such as list of mbufs from<br />

a Berkeley-type TCP/IP protocol) as a chain of mBlk/clBlk/cluster constructs.<br />

Each mBlk in the chain is linked to the next mBlk using the<br />

mBlk.mBlkHdr.mNext member. The driver deals with the chain appropriately on<br />

transmission.<br />

Protocol Transmission Restart<br />

One of the features of the MUX/END API is to allow a device to tell a protocol<br />

when it has run out of resources. Protocols usually have a queue of packets that<br />

they are trying to transmit. If the device returns an END_ERR_BLOCK from a<br />

muxSend( ) call, the device is out of the resources necessary to send the data. The<br />

protocol should now stop transmitting. After the device knows that it has the<br />

resources necessary to transmit again, it can call the muxTxRestart( ) routine<br />

which in turn calls the stackTxRestartRtn( ) of each protocol attached to that<br />

304


H<br />

Implementing a MUX-Based Network Interface Driver<br />

particular device. Your protocol should implement a restart routine so that it can<br />

take advantage of this system.<br />

Protocol Shutdown<br />

When a protocol is finished using an interface, or for some reason wants to shut<br />

itself down, it calls the muxUnbind( ) routine. This routine tells the MUX to<br />

deallocate the NET_PROTOCOL and other memory allocated specifically for the<br />

protocol.<br />

H.6.1 Protocol to MUX API<br />

This section presents the routines and data structures that the protocol uses to<br />

interact with the MUX. Most of the work is handled by the MUX routines (listed in<br />

Table H-4). Unlike the driver entry points described earlier, you do not implement<br />

the MUX routines. These routines are utilities that you can call from within your<br />

protocol. For specific information on these MUX routines, see the appropriate<br />

reference entry.<br />

However, these MUX routines do not comprise the entire MUX/protocol interface.<br />

In addition, a protocol must implement a set of standardized routines that handle<br />

things such as shutting down the protocol, restarting the protocol, passing data up<br />

to the protocol, and passing error messages up to the protocol.<br />

Table H-4<br />

MUX Interface Routines<br />

MUX Routine<br />

muxDevLoad( )<br />

muxDevStart( )<br />

muxBind( )<br />

muxSend( )<br />

muxDataPacketGet( )<br />

muxAddressForm( )<br />

muxIoctl( )<br />

muxMCastAddrAdd( )<br />

Purpose<br />

Loads a device into the MUX.<br />

Starts a device from the MUX.<br />

Hooks a protocol to the MUX.<br />

Accepts a packet from the protocol and passes it to the device.<br />

Gets an mBlk containing packet data only. The link-level<br />

header information is omitted.<br />

Forms an address into an outgoing packet.<br />

Accesses control functions.<br />

Adds a multicast address to the list maintained for a device.<br />

H<br />

305


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Table H-4<br />

MUX Interface Routines (Continued)<br />

MUX Routine<br />

muxMCastAddrDel( )<br />

muxMCastAddrGet( )<br />

muxUnbind( )<br />

muxDevStop( )<br />

muxDevUnload( )<br />

muxPacketDataGet( )<br />

muxPacketAddrGet( )<br />

muxTxRestart( )<br />

muxReceive( )<br />

muxShutdown( )<br />

muxAddrResFuncAdd( )<br />

muxAddrResFuncGet( )<br />

muxAddrResFuncDel( )<br />

Purpose<br />

Deletes a multicast address from the list maintained for a<br />

device.<br />

Gets the multicast address table maintained for a device.<br />

Disconnects a protocol from the MUX.<br />

Stops a device.<br />

Unloads a device.<br />

Extracts the packet data (omitting the link-level data) from a<br />

submitted mBlk and writes it to a fresh mBlk.<br />

Extracts source and destination address data (omitting the<br />

packet data) from a submitted mBlk and writes each address<br />

to its own mBlk. If the local source/destination addresses<br />

differ from the end source/destination addresses, this routine<br />

writes to as many as four mBlks.<br />

If a device unblocks transmission after having blocked it, this<br />

routine calls the stackTxRestartRtn( ) routine associated with<br />

each interested protocol.<br />

Sends a packet up to the MUX from the device.<br />

Shuts down all protocols above this device.<br />

Adds an address resolution function to the address resolution<br />

function list.<br />

Gets a particular address resolution function from the list.<br />

Deletes a particular address resolution function from the list.<br />

The Protocol Data Structure NET_PROTOCOL<br />

For each protocol that binds to a device, the MUX allocates a NET_PROTOCOL<br />

structure. The MUX uses this structure to store information relevant to the<br />

protocol, such as the protocol’s type, its receive routine, and its shutdown routine.<br />

These are chained in a linked list whose head rests in the protocols member of the<br />

END_OBJ structure the MUX uses to manage a device. The NET_PROTOCOL<br />

structure is defined in end.h as follows:<br />

306


H<br />

Implementing a MUX-Based Network Interface Driver<br />

typedef struct net_protocol<br />

{<br />

NODE node; /* How we stay in a list. */<br />

char name[32]; /* String name for this protocol. */<br />

long type; /* Protocol type from RFC 1700 */<br />

int flags; /* Is protocol in a promiscuous mode? */<br />

BOOL (*stackRcvRtn) (void *, long, M_BLK_ID, M_BLK_ID, void*);<br />

/* The routine to call when we get */<br />

/* a packet. */<br />

STATUS (*stackShutdownRtn) (void*, void*);<br />

/* The routine to call to shutdown */<br />

/* the protocol stack. */<br />

STATUS (*stackTxRestartRtn) (void*, void*);<br />

/* Callback for restarting on blocked tx. */<br />

void (*stackErrorRtn) (END_OBJ*, END_ERR*, void*);<br />

/* Callback for device errors. */<br />

void* pSpare; /* Spare pointer that can be passed to */<br />

/* the protocol. */<br />

} NET_PROTOCOL;<br />

Passing a Packet Up to the Protocol: stackRcvRtn( )<br />

Each protocol must provide the MUX with a routine that the MUX can use to pass<br />

packets up to the protocol. This routine must take the following form:<br />

void stackRcvRtn<br />

(<br />

void* pCookie, /* returned by muxBind() call */<br />

long type, /* protocol type from RFC 1700 */<br />

M_BLK_ID pNetBuff, /* packet with link level info */<br />

LL_HDR_INFO* pLinkHdr, /* link-level header info structure */<br />

void* pSpare /* a void* the protocol can use to get info */<br />

/* on receive. This was passed to muxBind().*/<br />

)<br />

H<br />

Your protocol must declare its stackRcvRtn( ) as void. Thus, this function returns<br />

no value.<br />

The parameters are:<br />

pCookie<br />

Expects the pointer returned from the muxBind( ) call. This pointer identifies<br />

the device to which the MUX has bound this protocol.<br />

type<br />

Expects the protocol type from RFC1700 or the SAP.<br />

pNetBuff<br />

Expects a pointer to an mBlk structure that contains the packet data and the<br />

link-level information.<br />

307


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

pLinkHdr<br />

Returns an LL_HDR_INFO structure containing header information that is<br />

dependent upon the particular data-link layer that the END implements. For<br />

more information, see Tracking Link-Level Information: LL_HDR_INFO, p.287.<br />

pSpare<br />

Expects a pointer to the spare information (if any) that was passed down to the<br />

MUX using the pSpare parameter of the muxBind( ) call. This information is<br />

passed back up to the protocol by each receiveRtn call. The use of this<br />

information is optional and protocol-specific.<br />

Passing Error Messages Up to the Protocol: stackError( )<br />

The MUX uses the stackError( ) routine to pass error messages from the device to<br />

the protocol. Your code for this routine must have an appropriate response for all<br />

possible error messages. The prototype for the stackError( ) routine is as follows:<br />

void stackError<br />

(<br />

END_OBJ* pEnd, /* pointer to END_OBJ */<br />

END_ERR* pError, /* pointer to END_ERR */<br />

void* pSpare /* pointer to protocol private data passed in muxBind */<br />

)<br />

You must declare your stackShutdownRtn( ) as returning void. Thus, there is no<br />

returned function value for this routine. The parameters are:<br />

pEnd<br />

Expects the pointer returned as the function value of the muxBind( ) for this<br />

protocol. This pointer identifies the device to which the MUX has bound this<br />

protocol.<br />

pError<br />

Expects a pointer to an END_ERR structure, which end.h defines as follows:<br />

typedef struct end_err<br />

{<br />

INT32 errCode; /* error code, see above */<br />

char* pMesg; /* NULL-terminated error message, can be NULL */<br />

void* pSpare; /* pointer to user defined data, can be NULL */<br />

} END_ERR;<br />

308


H<br />

Implementing a MUX-Based Network Interface Driver<br />

Within your code for the stackError( ) routine, you must have appropriate<br />

responses to the flags stored in the errCode member. Wind River reserves the<br />

lower 16 bits of errCode for its own error messages, which are as follows:<br />

END_ERR_INFO<br />

END_ERR_WARN<br />

END_ERR_RESET<br />

END_ERR_DOWN<br />

END_ERR_UP<br />

This error is information only.<br />

A non-fatal error has occurred.<br />

An error occurred that forced the device to reset<br />

itself, but the device has recovered.<br />

A fatal error occurred that forced the device to go<br />

down. The device can no longer send or receive<br />

packets.<br />

The device was down but is now up again and can<br />

receive and send packets.<br />

The upper 16 bits of the errCode member are available to user applications.<br />

Use these bits to encode whatever error messages you need to pass between<br />

drivers and protocols.<br />

pSpare<br />

Expects pointer to protocol-specific data. Originally, the protocol passed this<br />

data to the MUX when it called muxBind( ). This data is optional and<br />

protocol-specific.<br />

Shutting Down a Protocol: stackShutdownRtn( )<br />

The MUX uses stackShutdownRtn( ) to shut down a protocol. Within this routine,<br />

you must do everything necessary to shut down your protocol in an orderly<br />

manner. Your stackShutdownRtn( ) must take the following form:<br />

H<br />

void stackShutdownRtn<br />

(<br />

void* pCookie /* Returned by muxBind() call. */<br />

void* pSpare /* a void* that can be used by the protocol to get<br />

/* info on receive. This was passed to muxBind().*/<br />

)<br />

You must declare your stackShutdownRtn( ) as returning void. Thus, there is no<br />

returned function value for this routine.<br />

The parameters are:<br />

pCookie<br />

Expects the pointer returned as the function value of the muxBind( ) for this<br />

protocol. This pointer identifies the device to which the MUX has bound this<br />

protocol.<br />

309


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

pSpare<br />

Expects the pointer passed into muxBind( ) as pSpare.<br />

Restarting Protocols: stackTxRestartRtn( )<br />

The MUX uses the stackTxRestartRtn( ) to restart protocols that had to stop<br />

transmitting because the device was out of resources. In high-traffic situations, a<br />

muxSend( ) can return END_ERR_BLOCK. This error return indicates that the<br />

device is out of resources for transmitting more packets and that the protocol<br />

should wait before trying to transmit any more packets.<br />

When the device has determined that it has enough resources to start transmitting<br />

again, it can call the muxTxRestart( ) function, which, in turn, calls the protocol’s<br />

stackTxRestartRtn( ).<br />

Your stackTxRestartRtn( ) must take the following form:<br />

void muxTxRestart<br />

(<br />

void* pCookie /* Returned by muxBind() call. */<br />

)<br />

The parameters are:<br />

pCookie<br />

Expects the pointer returned as the function value of the muxBind( ) for this<br />

protocol. This pointer identifies the device to which the MUX has bound this<br />

protocol.<br />

H.6.2 Network Layer to Data Link Layer Address Resolution<br />

The MUX provides several functions for adding network layer to data link layer<br />

address resolution functions. Resolving a network layer address into a data link<br />

layer address is usually carried out by a separate protocol. In most IP over Ethernet<br />

environments this is carried out by ARP (the Address Resolution Protocol).<br />

Using the MUX any protocol/datalink can register its own address resolution<br />

function. The functions are added and deleted by the following pair of routines:<br />

STATUS muxAddrResFuncAdd<br />

(<br />

long ifType, /* Media interface type from m2Lib.h */<br />

long protocol, /* Protocol type from RFC 1700 */<br />

FUNCPTR addrResFunc /* Function to call. */<br />

)<br />

310


H<br />

Implementing a MUX-Based Network Interface Driver<br />

STATUS muxAddrResFuncDel<br />

(<br />

long ifType,/* Media interface type from m2Lib.h */<br />

long protocol /* Protocol type from RFC 1700 */<br />

)<br />

These functions add and delete address resolution routines. The exact arguments<br />

to that routine are the responsibility of the protocol writer to ascertain. Currently<br />

the only address resolution routine provided by Wind River is arpresolve( ).<br />

To find out what address resolution routine to use for a particular<br />

network/datalink pair, call the following routine:<br />

FUNCPTR muxAddrResFuncGet<br />

(<br />

long ifType, /* ifType from m2Lib.h */<br />

long protocol /* protocol from RFC 1700 */<br />

)<br />

This routine returns a pointer to a function that you can call to resolve data link<br />

addresses for the network protocol specified as the second argument.<br />

H.7 Converting an END Driver from RFC 1213 to RFC 2233<br />

To convert an END driver to use RFC 2233, perform the following steps:<br />

(1) Modify the END load routine to set up the RFC 2233-type MIB in the END_OBJ.<br />

(2) Modify the END unload routine to delete the RFC 2233-type MIB from the<br />

END_OBJ.<br />

(3) Change the hardware address macro to point to the new location of the<br />

physical address.<br />

(4) Add the EIOCGMIB2233 case in the ioctl routine.<br />

(5) Replace the old RFC 1213 interface API with the RFC 2233 interface API; then<br />

delete the old RFC 1213 interface API.<br />

It is vital that all MIB calls be located such that their validity can be guaranteed. In<br />

other words, do not log a successful receipt or send of a packet until it is absolutely<br />

certain that the packet will be successfully received or sent.<br />

Take special care to ensure that all failure conditions are properly logged.<br />

H<br />

311


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Step 1:<br />

Modify the END load routine to set up the RFC 2233-type MIB in the END_OBJ.<br />

In the xxxEndLoad( ) routine, initialize the MIB-II entries (for RFC 2233). For<br />

example:<br />

pDrvCtrl->endObj.pMib2Tbl = m2IfAlloc(M2_ifType_ethernet_csmacd,<br />

(UINT8*) enetAddr, 6,<br />

ETHERMTU, speed,<br />

DEV_NAME, pDrvCtrl->unit);<br />

if (pDrvCtrl->endObj.pMib2Tbl == NULL)<br />

{<br />

logMsg ("%s%d - MIB-II initializations failed\n",<br />

DEV_NAME, pDrvCtrl->unit,0,0,0,0);<br />

goto errorExit;<br />

}<br />

/*<br />

* Set the RFC2233 flag bit in the END object flags field and<br />

* install the counter update routines.<br />

*/<br />

m2IfPktCountRtnInstall(pDrvCtrl->endObj.pMib2Tbl, m2If8023PacketCount);<br />

/*<br />

* Make a copy of the data in the mib2Tbl struct as well. We do this<br />

* mainly for backward compatibility issues. There might be some<br />

* code that references the END pointer and does lookups on the mib2Tbl,<br />

* which causes all sorts of problems.<br />

*/<br />

bcopy ((char *)&pDrvCtrl->endObj.pMib2Tbl->m2Data.mibIfTbl,<br />

(char *)&pDrvCtrl->endObj.mib2Tbl, sizeof (M2_INTERFACETBL));/*<br />

Mark the device ready */<br />

END_OBJ_READY (&pDrvCtrl->endObj,<br />

IFF_NOTRAILERS | IFF_MULTICAST | IFF_BROADCAST |<br />

END_MIB_2233);<br />

Step 2:<br />

Modify the END unload routine to delete the RFC 2233-type MIB from the END_OBJ.<br />

In the xxxEndUnload( ) routine, add MIB-II free routine entries. For example:<br />

m2IfFree(pDrvCtrl->endObj.pMib2Tbl);<br />

pDrvCtrl->endObj.pMib2Tbl = NULL;<br />

Step 3:<br />

Change the hardware address macro to point to the new location of the<br />

physical address.<br />

The hardware address macro is usually defined with the name<br />

END_HADDR(pEnd) but may be defined with the prefix reflecting the actual<br />

driver, such as in the fei82557End driver, where it is FEI_HADDR(pEnd).<br />

312


H<br />

Implementing a MUX-Based Network Interface Driver<br />

Set the hardware address macro to point to where the physical address is stored in<br />

the RFC 2233-type MIB. For RFC 2233-type MIBs, the physical address for an<br />

Ethernet device is stored in the pMib2Tbl in the END_OBJ. For example:<br />

#define END_HADDR(pEnd) \<br />

((pEnd)->pMib2Tbl->m2Data.mibIfTbl.ifPhysAddress.phyAddress)<br />

Step 4:<br />

Add the EIOCGMIB2233 case in the ioctl routine.<br />

For example:<br />

/* New RFC 2233 mib2 interface */<br />

case EIOCGMIB2233:<br />

if ((data == NULL) || (pEndObj->pMib2Tbl == NULL))<br />

error = EINVAL;<br />

else<br />

*((M2_ID **)data) = pEndObj->pMib2Tbl;<br />

break;<br />

Step 5:<br />

Replace the old RFC 1213 interface API with the RFC 2233 interface API; then delete<br />

the old RFC 1213 interface API.<br />

RFC 1213 interface API. The old RFC 1213 interface used the END_ERR_ADD<br />

macro for both updating packet counts and for counting error conditions.<br />

(a) Replace all instances of END_ERR_ADD calls. After an END_ERR_ADD<br />

instance is replaced, it can be deleted. For example:<br />

END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1);<br />

(b) Replace the deleted RFC 1213 interface.<br />

H<br />

RFC 2233 Interface API. The RFC 2233 interface API consists of<br />

m2IfGenericPacketCount( ) and m2IfCounterUpdate( ). These routines are<br />

accessed through pointers stored in pMib2Tbl of the END_OBJ. The pointer to<br />

m2IfGenericPacketCount( ) is held in pDrvCtrl-> endObj.pMib2Tbl-><br />

m2PktCountRtn. The pointer to m2IfCounterUpdate( ) is in pDrvCtrl-><br />

endObj.pMib2Tbl-> m2CtrUpdateRtn.<br />

The APIs for these routines are as follows:<br />

m2If8023PacketCount. Increment the interface packet counters for an 802.3 device.<br />

This function is used to update basic interface counters for a packet. The ctrl<br />

argument specifies whether the packet is being sent or received<br />

(M2_PACKET_IN or M2_PACKET_OUT). This function works for the 802.3<br />

313


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

device only, because it understands the Ethernet packet format. The following<br />

counters are updated:<br />

ifInOctets<br />

ifInNUcastPkts<br />

ifOutUcastPkts<br />

ifInMulticastPkts<br />

ifOutMulticastPkts<br />

ifHCInOctets<br />

ifHCOutOctets<br />

ifHCInMulticastPkts<br />

ifHCOutMulticastPkts<br />

ifCounterDiscontinuityTime<br />

ifInUcastPkts<br />

ifOutOctets<br />

ifOutNUcastPkts<br />

ifInBroadcastPkts<br />

ifOutBroadcastPkts<br />

ifHCInUcastPkts<br />

ifHCOutUcastPkts<br />

ifHCInBroadcastPkts<br />

ifHCOutBroadcastPkts<br />

This function should be called immediately after the netMblkToBufCopy( )<br />

function has been completed. The first 6 bytes in the resulting buffer must<br />

contain the destination MAC address; the second 6 bytes of the buffer must<br />

contain the source MAC address.<br />

The type of MAC address (that is, broadcast, multicast, or unicast) is<br />

determined by the following:<br />

broadcast address<br />

multicast address<br />

unicast address<br />

ff:ff:ff:ff:ff:ff<br />

The first bit is set<br />

Any other address not matching the above<br />

RETURNS: ERROR if the M2_ID is NULL or the ctrl is invalid, OK if the<br />

counters were updated.<br />

STATUS m2If8023PacketCount<br />

(<br />

M2_ID * pId, /* The pointer to the device M2_ID object */<br />

UINT ctrl, /* Update In or Out counters */<br />

UCHAR * pPkt, /* The incoming/outgoing packet */<br />

ULONG pktLen /* Length of the packet */<br />

)<br />

m2IfCounterUpdate. Increment interface counters.<br />

This function is used to directly update an interface counter. The counter is<br />

specified by ctrId and the amount by which to increment it is specified by value.<br />

If the counter rolls over, the ifCounterDiscontinuityTime is updated with the<br />

current system uptime.<br />

RETURNS: ERROR if the M2_ID is NULL, OK if the counter was updated.<br />

314


H<br />

Implementing a MUX-Based Network Interface Driver<br />

STATUS m2IfCounterUpdate<br />

(<br />

M2_ID * pId, /* The pointer to the device M2_ID object */<br />

UINT ctrId, /* Counter to update */<br />

ULONG value /* Amount to update the counter by */<br />

)<br />

Code Conversion from RFC 1213 to RFC 2233<br />

■<br />

Send Routines<br />

In the Send( ) and PollSend( ) routines, add an RFC 2233 MIB-II counter<br />

update for outgoing packets.<br />

For example, change a Send( ) routine as follows:<br />

■<br />

if (pDrvCtrl->endObj.pMib2Tbl != NULL)<br />

{<br />

pDrvCtrl->endObj.pMib2Tbl->m2PktCountRtn(pDrvCtrl->endObj.pMib2Tbl,<br />

M2_PACKET_OUT, pEnetHdr,<br />

len);<br />

}<br />

For example, change a PollSend routine as follows:<br />

if (pDrvCtrl->endObj.pMib2Tbl != NULL)<br />

{<br />

pDrvCtrl->endObj.pMib2Tbl->m2PktCountRtn(pDrvCtrl->endObj.pMib2Tbl,<br />

M2_PACKET_OUT, pEnetHdr,<br />

len);<br />

}<br />

Receive Routines<br />

In Receive( ) and PollReceive( ) routines, add an RFC 2233 MIB-II counter<br />

update for incoming packets.<br />

For example, change a Receive( ) routine as follows:<br />

if (pDrvCtrl->endObj.pMib2Tbl != NULL)<br />

{<br />

pDrvCtrl->endObj.pMib2Tbl->m2PktCountRtn(pDrvCtrl->endObj.pMib2Tbl,<br />

M2_PACKET_IN,<br />

pMblk->mBlkHdr.mData,<br />

pMblk->mBlkHdr.mLen);<br />

}<br />

For example, change a PollReceive( ) routine as follows:<br />

if (pDrvCtrl->endObj.pMib2Tbl != NULL)<br />

{<br />

pDrvCtrl->endObj.pMib2Tbl->m2PktCountRtn(pDrvCtrl->endObj.pMib2Tbl,<br />

M2_PACKET_IN,<br />

H<br />

315


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

}<br />

pMblk->mBlkHdr.mData,<br />

pMblk->mBlkHdr.mLen);<br />

Step 6:<br />

Take special care to ensure that all failure conditions be properly logged.<br />

The RFC 2233 interface provides the routine m2IfCounterUpdate( ) to maintain<br />

the various counters relevant for failure conditions. All failure conditions are<br />

considered errors. However, there are two general classes of failure conditions. The<br />

device can return an error status either because of failure to accomplish a requested<br />

action, or because of the driver’s inability to handle a packet due to a lack of<br />

available resources.<br />

Device failure conditions can be further categorized into errors-only and<br />

errors-with-discards, based on whether the failure causes packets to be dropped or<br />

not. If no packet is dropped, the failure is only an error; if data is dropped, the<br />

failure is both an error and a discard. Most device errors are both.<br />

If the driver receives a packet that was corrupted at receipt, this constitutes an error<br />

only. However, if a driver is unable to handle a perfectly good packet due to a lack<br />

of resources, this is always both an error and a discard.<br />

The RFC 2233 interface maintains counters for both incoming and outgoing errors<br />

and discards. The API provides selection by providing corresponding flags that<br />

designate each particular counter. This flag is passed as the second argument to<br />

m2IfCounterUpdate( ).<br />

The relevant flags are:<br />

M2_ctrId_ifInDiscards<br />

M2_ctrId_ifInErrors<br />

M2_ctrId_ifOutDiscards<br />

M2_ctrId_ifOutErrors<br />

For example:<br />

/* New RFC 2233 mib2 interface */<br />

if (pDrvCtrl->endObj.pMib2Tbl != NULL)<br />

{<br />

pDrvCtrl->endObj.pMib2Tbl->m2CtrUpdateRtn(pDrvCtrl->endObj.pMib2Tbl,<br />

M2_ctrId_ifInErrors, 1);<br />

pDrvCtrl->endObj.pMib2Tbl->m2CtrUpdateRtn(pDrvCtrl->endObj.pMib2Tbl,<br />

M2_ctrId_ifInDiscards, 1);<br />

}<br />

316


I<br />

Writing a SCSI-2 Device Driver<br />

I.1 Introduction<br />

The VxWorks SCSI-2 subsystem consists of the following components:<br />

■<br />

■<br />

SCSI libraries, an architecture-independent component<br />

SCSI controller driver, an architecture-specific component<br />

■<br />

SCSI-2 subsystem initialization code, a board-specific component<br />

You must first understand the basic functionality of each of these components<br />

before you can extend the functionality of the SCSI libraries or add new SCSI<br />

controller drivers. To help you gain that understanding, this chapter describes the<br />

general layout of the various SCSI modules, discusses the internals of the SCSI<br />

libraries (and their programming interface with the SCSI controller drivers), and<br />

describes the process of developing a controller-specific SCSI driver.<br />

For information on the interface between the I/O system and the SCSI libraries,<br />

including configuring SCSI peripheral devices within VxWorks, see the VxWorks<br />

Programmer’s <strong>Guide</strong>: I/O System.<br />

NOTE: In this chapter, the term SCSI refers to SCSI-2 in all cases. The SCSI library<br />

interfaces and SCSI controller drivers described in this chapter refer to SCSI-2 only.<br />

VxWorks offers only limited support for SCSI-1. Eventually, VxWorks will<br />

eliminate all SCSI-1 support.<br />

317


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

I.2 Overview of SCSI<br />

This section describes the relationships between the various SCSI modules,<br />

introduces the different SCSI objects and data structures, and tells you how to form<br />

SCSI commands.<br />

Layout of SCSI Modules<br />

Figure I-1 shows all the SCSI library modules and the relationship between them<br />

and several typical drivers. The SCSI libraries contain a variety of data structures.<br />

The important data structures and their relationships are described in the<br />

following subsections. The general design of the data structures is object-oriented;<br />

data structures represent real and abstract SCSI objects such as peripheral devices,<br />

controllers, and block devices.<br />

Figure I-1<br />

Layout of SCSI Modules<br />

direct access file system<br />

(example: dosFs)<br />

sequential access file system<br />

(example: tapeFs)<br />

scsiDirectLib<br />

scsiCommonLib<br />

scsiSeqLib<br />

scsiLib<br />

scsi1Lib<br />

scsi2Lib<br />

scsiMgrLib<br />

wd33c93Lib1<br />

ncr710Lib1<br />

ncr810Lib<br />

scsiCtrlLib<br />

ncr710init<br />

ncr810init<br />

wd33c93Lib2<br />

318


I<br />

Writing a SCSI-2 Device Driver<br />

SCSI Objects and Data Structures<br />

Figure I-2 illustrates the relationship between the various physical and logical<br />

SCSI objects and the corresponding data structures.<br />

Figure I-2<br />

Relationship of SCSI Devices and Data Structures<br />

hardware<br />

data structures<br />

representing<br />

SCSI logical<br />

devices<br />

disk drive<br />

tape drive<br />

BLK_DEV<br />

SEQ_DEV<br />

SCSI_PHYS_DEV<br />

SCSI_PHYS_DEV<br />

data structures<br />

representing<br />

SCSI physical<br />

devices<br />

SCSI_BVS<br />

SCSI_CTRL<br />

SCSI controller<br />

CPU<br />

DRAM<br />

data structure<br />

representing<br />

SCSI controller<br />

Figure I-3 describes the contents of these data structures and their relationships in<br />

more detail.<br />

I<br />

SCSI_CTRL<br />

This structure contains a list of all physical devices and all allocated SCSI<br />

threads.<br />

SCSI_THREAD<br />

Each thread is represented by a dynamic data structure, which is manipulated<br />

at various levels in scsi2Lib, scsiMgrLib, and the device drivers. It contains a<br />

SCSI_TRANSACTION and the rest of the thread-state information.<br />

SCSI_TRANSACTION<br />

Each SCSI command from the I/O system is translated into one of these<br />

structures, which consists of a SCSI command descriptor block plus all the<br />

required pointer addresses.<br />

319


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

SCSI_PHYS_DEV<br />

This structure contains information about available logical devices plus<br />

information about the various threads.<br />

SEQ_DEV<br />

This structure represents a sequential logical device such as a tape drive.<br />

BLK_DEV<br />

This structure represents a block device such as a disk drive.<br />

Figure I-3<br />

Controller- and Driver-Specific Data Structures<br />

SCSI_CTRL<br />

LIST<br />

UINT<br />

RING_ID<br />

RING_ID<br />

RING_ID<br />

RING_ID<br />

SCSI_PHYS_DEV *<br />

{virtual function pointers}<br />

.<br />

.<br />

{other state information}<br />

.<br />

.<br />

SCSI_THREAD<br />

SCSI_CTRL<br />

SCSI_PHYS_DEV<br />

MSG_Q_ID<br />

WDOG_ID<br />

UINT<br />

{thread state information}<br />

{replication of<br />

SCSI_TRANSACTION<br />

information}<br />

.<br />

.<br />

freeThreads<br />

nThreads<br />

requestQ<br />

replyQ<br />

eventQ<br />

timeoutQ<br />

physDevArr[ ]<br />

*pScsiCtrl<br />

*pScsiPhysDev<br />

replyQ<br />

wdog<br />

tagNumber<br />

SCSI_PHYS_DEV<br />

{device information from INQUIRY}<br />

LIST<br />

blkDevList<br />

SEQ_DEV *pScsiSeqDev<br />

LIST<br />

waitingThreads<br />

LIST<br />

activeThreads<br />

{other state information}<br />

.<br />

.<br />

SEQ_DEV<br />

.<br />

.<br />

.<br />

BLK_DEV<br />

.<br />

.<br />

.<br />

{command description block}<br />

UINT8 *dataAddress<br />

UINT8 *cmdAddress<br />

.<br />

.<br />

SCSI_TRANSACTION<br />

320


I<br />

Writing a SCSI-2 Device Driver<br />

Forming SCSI Commands<br />

Within the SCSI libraries, the SCSI commands all work in a similar fashion. All<br />

information needed by the command is delivered by passing in appropriate<br />

parameters. The command first builds a SCSI command descriptor block with<br />

pointers to all required data and stores the block in a SCSI_TRANSACTION<br />

structure. The command then calls the scsiTransact( ) routine, passing it the<br />

structures SCSI_TRANSACTION and SCSI_PHYS_DEV.<br />

The scsiTransact( ) routine is the general routine in scsi2Lib that handles<br />

processing of all SCSI commands originating in scsiDirectLib, scsiCommonLib,<br />

and scsiSeqLib. This paradigm should be used to extend SCSI library support to<br />

other device classes (scsiXXXLib).<br />

STATUS scsiXxxCmd<br />

(<br />

char * buf<br />

SCSI_PHYS_DEV * pScsiPhysDev<br />

:<br />

)<br />

SCSI_COMMAND xxxCommand;<br />

SCSI_TRANSACTION scsiXaction;<br />

...<br />

/* build a SCSI command descriptor block in xxxComand */<br />

...<br />

scsiXaction.cmdAddress = xxxComand;<br />

scsiXaction.dataAddress = buf;<br />

scsiXaction.dataLength = strLen(buf);<br />

...<br />

return ((*pScsiPhysDev->pScsiCtrl->scsiTransact)<br />

(pScsiPhysDev, &scsiXaction));<br />

...<br />

I<br />

I.3 The SCSI Libraries<br />

This section describes the following libraries:<br />

■<br />

■<br />

■<br />

■<br />

■<br />

The SCSI Manager (scsiMgrLib)<br />

SCSI Controller Library (scsiCtrlLib)<br />

SCSI Direct Access Library (scsiDirectLib)<br />

SCSI Sequential Access Library (scsiSeqLib)<br />

SCSI Common Access Library (scsiCommonLib)<br />

321


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

This section ends with a brief discussion of how VxWorks typically handles the<br />

execution of a SCSI command.<br />

I.3.1 SCSI Manager (scsiMgrLib)<br />

The SCSI manager functions as a task within VxWorks. There is one SCSI manager<br />

per SCSI controller, and it is responsible for managing all SCSI interaction between<br />

VxWorks tasks and the SCSI controller. Any number of VxWorks tasks can request<br />

services from SCSI peripheral devices. The SCSI bus is a shared critical resource<br />

which requires multitasking support and synchronization.<br />

For the sake of performance and efficiency, the SCSI manager controls all the SCSI<br />

traffic within the operating system. SCSI traffic includes requests for SCSI services<br />

by VxWorks tasks. These requests are asynchronous events from the SCSI bus and<br />

include SCSI reconnects, SCSI connection timeouts, and SCSI responses to requests<br />

by VxWorks tasks. This work flow is managed by SCSI threads, which are<br />

SCSI-library-specific abstractions. A SCSI thread is assigned to each unit of SCSI<br />

work. In other words, one SCSI thread is assigned per SCSI request.<br />

Each SCSI thread is created in the context of the calling VxWorks task. The thread<br />

is managed by the SCSI manager, while the calling VxWorks task remains blocked.<br />

When the SCSI thread completes, the VxWorks task is unblocked and the SCSI<br />

thread is deleted.<br />

A SCSI thread has its own context or state variables, which are manipulated by the<br />

SCSI libraries and the controller driver. A maximum of one SCSI thread can be<br />

executing at any one time. In addition to managing the SCSI-thread state<br />

information, the SCSI manager is responsible for scheduling these SCSI threads.<br />

When there are multiple threads in existence, the different threads can be in<br />

various states representing different requirements. A SCSI thread can represent a<br />

new request for service, a connection timeout, a completion of service, or an event<br />

from the SCSI bus. As requests for service are submitted to the SCSI manager by<br />

VxWorks tasks, the associated threads must be processed based on priority or on a<br />

first-come-first-serves basis if their priority is the same.<br />

When multiple threads are eligible for activation, the SCSI manager follows a strict<br />

hierarchy of processing. Asynchronous bus events have the highest priority and<br />

are processed before any other type of SCSI thread. The order of processing is:<br />

events, timeouts, requests, and finally responses. The SCSI manager handles any<br />

race condition that develops between activation of a request and the asynchronous<br />

occurrence of an event from the SCSI bus.<br />

322


I<br />

Writing a SCSI-2 Device Driver<br />

Once an appropriate SCSI thread is selected for execution, the SCSI manager<br />

despatches that thread and actual execution is handled by the controller-specific<br />

driver.<br />

Limitations<br />

The SCSI manager uses standard VxWorks ring buffers to manage SCSI requests.<br />

Using ring buffers is fast and efficient. The amount of SCSI work that can be<br />

queued depends upon the size of the allocated ring buffers. The SCSI manager also<br />

has some limitations such as the maximum number of threads allowed<br />

(scsiMaxNumThreads), the maximum number of SCSI requests from VxWorks<br />

tasks that can be put on the SCSI manager’s request queue<br />

(scsiMgrRequestQSize), the maximum number of SCSI bus events that can be put<br />

on the SCSI manager’s event queue (scsiMgrEventQSize), the maximum number<br />

of replies that can be put on the reply queue (scsiMgrReplyQSize), the maximum<br />

number of timeouts that can be put on the timeout queue (scsiMgrTimeoutQSize),<br />

and timeout values.<br />

Configuration<br />

It is possible to tune the size of the ring buffers and the number of SCSI threads to<br />

optimize a specific environment. In most cases, however, the default values are<br />

sufficient. These parameters—scsiMaxNumThreads, scsiMgrRequestQSize,<br />

scsiMgrReplyQSize, scsiMgrEventQSize, scsiMgrTimeoutQSize—are defined<br />

as global variables within the SCSI library and are assigned default values defined<br />

in scsiLib.h. These values can be reassigned in the <strong>BSP</strong> routine sysScsiInit( ) prior<br />

to the invocation of the driver’s xxxCtrlInit( ) routine. Then when scsiCtrlInit( )is<br />

invoked by the driver’s xxxCtrlInit( )routine, the new parameters are used for data<br />

structure allocation.<br />

The name, priority, and stack size of the scsiMgr task can also be customized from<br />

the controller driver’s xxxCtrlCreate( ) routine. Defaults are provided in scsiLib.h.<br />

For example, the default task name SCSI_DEF_TASK_NAME is tScsiTask, the<br />

default priority, SCSI_DEF_TASK_PRIORITY, is 5, and the default stack size,<br />

SCSI_DEF_TASK_STACK_SIZE, is 4000.<br />

I<br />

NOTE: The larger the number of expected VxWorks SCSI tasks, the larger the stack<br />

space required. Thought should be given to the stack size parameter when<br />

customizing the SCSI manager.<br />

323


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

I.3.2 SCSI Controller Library (scsiCtrlLib)<br />

The SCSI controller library is designed for the older generation of SCSI-2<br />

controllers that require the protocol state machine (and transitions) to be handled<br />

by a higher level of software.These basic SCSI controller drivers (those that need<br />

to use the SCSI state machine provided by the SCSI library) use the SCSI controller<br />

library. More advanced SCSI controllers allow such protocol state machines to be<br />

implemented at the SCSI controller level. This significantly reduces the number of<br />

SCSI interrupts to the CPU per I/O process which improves performance.<br />

There is a well defined interface between the SCSI libraries and the controller<br />

driver of such drivers, and this interface is defined in I.4 The SCSI Driver<br />

Programming Interface, p.325.<br />

I.3.3 SCSI Direct Access Library (scsiDirectLib)<br />

The SCSI direct access library scsiDirectLib encapsulates all the routines that<br />

implement the SCSI direct access commands as defined in the SCSI ANSI<br />

Specification I. In addition to all the direct access commands, scsiDirectLib<br />

provides the routines that supply the BLK_DEV abstraction for SCSI direct access<br />

peripheral devices.<br />

I.3.4 SCSI Sequential Access Library (scsiSeqLib)<br />

The SCSI sequential access library scsiSeqLib provides all the routines that<br />

implement the mandatory SCSI sequential access commands as defined in the<br />

SCSI ANSI Specification I. Some optional features are also implemented. Routines<br />

that manipulate the SEQ_DEV abstraction are also supplied in this library.<br />

I.3.5 SCSI Common Access Library (scsiCommonLib)<br />

SCSI commands that are common to all SCSI peripheral device types are provided<br />

in the common access library. These commands are described in the SCSI ANSI<br />

Specification I. The programming interface to such commands can be found in the<br />

relevant reference entries or by looking at the header file scsi2Lib.h.<br />

324


I<br />

Writing a SCSI-2 Device Driver<br />

I.3.6 An Execution Example<br />

Let us take a brief look at what happens when a VxWorks task requests SCSI<br />

service by invoking a SCSI library routine such as scsiInquiry( ). Since we are<br />

assuming a SCSI-2 configuration, first the scsi2Inquiry( ) routine is invoked which<br />

in turn invokes scsiTransact( ) (see Forming SCSI Commands, p.321). scsiTransact( )<br />

invokes scsiCommand( ), the routine that allocates a SCSI thread, executes the<br />

thread, and then deletes it.<br />

The execution of the thread via scsiThreadExecute( ) causes the SCSI manager to<br />

be informed of a new thread to execute, and subsequent blocking of that VxWorks<br />

task on a message queue until a response has been received. This is the boundary<br />

where a VxWorks task is blocked and the SCSI manager is awakened to start the<br />

execution of a new thread as well as management of any other threads that it may<br />

be dealing with.<br />

After the SCSI thread has executed and has received a response, the calling<br />

VxWorks task is unblocked and eventually the SCSI thread associated with that<br />

task is deleted.<br />

I.4 The SCSI Driver Programming Interface<br />

To better explain the interface between the controller driver and the SCSI libraries<br />

for the two types of SCSI controllers (basic and advanced), this section discusses<br />

each type of driver separately. A skeletal driver is provided along with the<br />

programming interface between the SCSI libraries and the controller driver. The<br />

controller driver routines provide all the hardware register accesses and<br />

controller-specific functionality. For the sake of simplicity, such accesses and<br />

controller-specific information have not been shown. It is the purpose of the<br />

template drivers to show the overall structure and programming interface<br />

between the driver, the SCSI libraries, and the <strong>BSP</strong>.<br />

I<br />

I.4.1 Basic SCSI Controller Driver<br />

This section presents the basic programming interface SCSI controller and the SCSI<br />

libraries. Following that description, this section presents a template you should<br />

use when writing your own SCSI controller driver.<br />

325


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

The Programming Interface<br />

A well-defined programming interface exists between the controller driver of any<br />

basic SCSI controller and the SCSI libraries. Every basic controller driver must<br />

provide the following functions to the SCSI libraries:<br />

xxxDevSelect( )<br />

This routine selects a SCSI peripheral device with the Attention (ATN) signal<br />

asserted.<br />

xxxInfoXfer( )<br />

All information transfer phases are handled by this routine, including the<br />

DATA_IN, DATA_OUT, MSG_IN, MSG_OUT, and STATUS phases.<br />

xxxXferParamsQuery( )<br />

This routine updates the synchronous data transfer parameters to match the<br />

capabilities of the driver and returns the optimal synchronous offset and<br />

period.<br />

xxxXferParamsSet( )<br />

This routine sets the synchronous data transfer parameters on the SCSI<br />

controller.<br />

xxxBusControl( )<br />

This routine controls some of the SCSI bus lines from the controller. This<br />

routine must reset the SCSI bus, assert ATN, or negate ACK.<br />

Similarly, the controller driver invokes the following routines in order to get SCSI<br />

library services:<br />

scsiCtrlInit( )<br />

This routine initializes the SCSI library data structures. It is called only once<br />

per SCSI controller.<br />

scsiMgrEventNotify( )<br />

This routine notifies the SCSI manager of a SCSI event that has occurred.<br />

Events are defined in scsi2Lib.h. However, more events can be defined by the<br />

controller driver, and events can also be bundled by the driver. In this case, the<br />

SCSI_CTRL field scsiEventProc must be set to this driver-specific routine<br />

during driver initialization.<br />

326


I<br />

Writing a SCSI-2 Device Driver<br />

A Template Driver<br />

The following example shows a template for a basic SCSI controller driver, without<br />

any specific hardware constraints. The basic structure of the driver is like any other<br />

VxWorks driver. The main routines consist of the following:<br />

– AxxxCtrlCreate( ) routine, that is invoked from the <strong>BSP</strong> routine sysScsiInit( )<br />

located in the <strong>BSP</strong> file sysScsi.c.<br />

– An ISR called xxxIntr( ) that handles all the interrupts, deciphers what SCSI<br />

event has occurred, and passes that event information to the SCSI manager via<br />

the scsiMgrEventNotify( ) routine.<br />

The SCSI libraries instruct the driver via the xxxDevSelect( ) and xxxInfoXfer( )<br />

routines, and the controller driver communicates back to the libraries by means of<br />

the scsiMgrEventNotify( ) routine.<br />

Example I-1<br />

Basic SCSI Controller Driver<br />

/* xxxLib.c - XXX SCSI-Bus Interface Controller library (SCSI-2) */<br />

/* Copyright 1989-1996 Wind River Systems, Inc. */<br />

#include "copyright_wrs.h"<br />

/*<br />

modification history<br />

--------------------<br />

01a,12sep96,dds written<br />

*/<br />

/*<br />

DESCRIPTION<br />

This library contains part of the I/O driver for the XXX family of SCSI-2<br />

Bus Interface Controllers (SBIC). It is designed to work with scsi2Lib.<br />

The driver routines in this library depend on the SCSI-2 ANSI specification;<br />

for general driver routines and for overall SBIC documentation, see xxxLib.<br />

I<br />

INCLUDE FILES<br />

xxx.h<br />

SEE ALSO: scsiLib, scsi2Lib,<br />

.pG "I/O System"<br />

*/<br />

#include "vxWorks.h"<br />

#include "drv/scsi/xxx.h"<br />

typedef XXX_SCSI_CTRL SBIC; /* SBIC: SCSI Bus Interface Controller struct */<br />

/* globals */<br />

327


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

int xxxXferDoneSemOptions = SEM_Q_PRIORITY;<br />

char *xxxScsiTaskName = SCSI_DEF_TASK_NAME;<br />

IMPORT SCSI_CTRL *pSysScsiCtrl;<br />

/***************************************************************************<br />

*<br />

* xxxCtrlCreate - create and partially initialize a SCSI controller structure<br />

*<br />

* This routine creates a SCSI controller data structure and must be called<br />

* before using a SCSI controller chip. It should be called once and only<br />

* once for a specified SCSI controller. Since it allocates memory for a<br />

* structure needed by all routines in xxxLib, it must be called before<br />

* any other routines in the library.<br />

* After calling this routine, at least one call to xxxCtrlInit() should<br />

* be made before any SCSI transaction is initiated using the SCSI controller.<br />

*<br />

* RETURNS: A pointer to the SCSI controller structure, or NULL if memory is<br />

* insufficient or parameters are invalid.<br />

*/<br />

XXX_SCSI_CTRL *xxxCtrlCreate<br />

(<br />

FAST UINT8 *sbicBaseAdrs, /* base address of the SBIC */<br />

int regOffset, /* address offset between SBIC registers */<br />

UINT clkPeriod, /* period of the SBIC clock (nsec) */<br />

FUNCPTR sysScsiBusReset, /* function to reset SCSI bus */<br />

int sysScsiResetArg, /* argument to pass to above function */<br />

UINT sysScsiDmaMaxBytes, /* maximum byte count using DMA */<br />

FUNCPTR sysScsiDmaStart, /* function to start SCSI DMA transfer */<br />

FUNCPTR sysScsiDmaAbort, /* function to abort SCSI DMA transfer */<br />

int sysScsiDmaArg /* argument to pass to above functions */<br />

)<br />

{<br />

FAST SBIC *pSbic; /* ptr to SBIC info */<br />

/* calloc the controller info structure; return NULL if unable */<br />

pSbic = (SBIC *) calloc (1, sizeof (SBIC))<br />

/*<br />

* Set up sizes of event and thread structures. Must be done before<br />

* calling "scsiCtrlInit()".<br />

*/<br />

/* fill in driver-specific routines for scsiLib interface */<br />

pSbic->scsiCtrl.scsiDevSelect = xxxDevSelect;<br />

pSbic->scsiCtrl.scsiInfoXfer = xxxInfoXfer;<br />

pSbic->scsiCtrl.scsiXferParamsQuery = xxxXferParamsQuery;<br />

pSbic->scsiCtrl.scsiXferParamsSet = (FUNCPTR)xxxXferParamsSet;<br />

/* Fill in driver specific variables for scsiLib interface */<br />

pSbic->scsiCtrl.maxBytesPerXfer = sysScsiDmaMaxBytes;<br />

328


I<br />

Writing a SCSI-2 Device Driver<br />

/* fill in generic SCSI info for this controller */<br />

xxxCtrlInit (&pSbic->scsiCtrl);<br />

/* initialize SBIC info transfer synchronization semaphore */<br />

if (semBInit (&pSbic->xferDoneSem, xxxXferDoneSemOptions, SEM_EMPTY)<br />

== ERROR)<br />

{<br />

(void) free ((char *) pSbic);<br />

return ((XXX_SCSI_CTRL *) NULL);<br />

}<br />

/* initialize state variables */<br />

/* fill in board-specific SCSI bus reset and DMA xfer routines */<br />

/* spawn SCSI manager - use generic code from "scsiLib.c" */<br />

pSbic->scsiCtrl.scsiMgrId = taskSpawn (xxxTaskName,<br />

xxxTaskPriority,<br />

xxxTaskOptions,<br />

xxxTaskStackSize,<br />

(FUNCPTR) scsiMgr,<br />

(int) pSbic,<br />

0, 0, 0, 0, 0, 0, 0, 0, 0);<br />

return (pSbic);<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxCtrlInit - initialize a SCSI controller structure<br />

*<br />

* After a SCSI controller structure is created with xxxCtrlCreate, but<br />

* before using the SCSI controller, it must be initialized by calling this<br />

* routine.<br />

* It may be called more than once if desired. However, it should only be<br />

* called while there is no activity on the SCSI interface.<br />

*<br />

* RETURNS: OK, or ERROR if out-of-range parameter(s).<br />

*/<br />

I<br />

LOCAL STATUS xxxCtrlInit<br />

(<br />

FAST SBIC *pSbic, /* ptr to SBIC info */<br />

FAST int scsiCtrlBusId, /* SCSI bus ID of this SBIC */<br />

FAST UINT defaultSelTimeOut /* default dev. select timeout (microsec) */<br />

)<br />

{<br />

pSbic->scsiCtrl.scsiCtrlBusId = scsiCtrlBusId;<br />

/* initialize the SBIC hardware */<br />

xxxHwInit (pSbic);<br />

329


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

return (OK);<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxHwInit - initialize the SCSI controller to a known state<br />

*<br />

* This routine puts the SCSI controller into a known quiescent state. It<br />

* does not reset the SCSI bus (and any other devices thereon).<br />

*/<br />

LOCAL void xxxHwInit<br />

(<br />

SBIC *pSbic /* ptr to an SBIC structure */<br />

)<br />

{<br />

/*<br />

* Initialize the SCSI controller hardware registers and place the<br />

* chip in a known quiescent state<br />

*/<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxDevSelect - attempt to select a SCSI device<br />

*<br />

* RETURNS: OK (no error conditions)<br />

*/<br />

LOCAL STATUS xxxDevSelect<br />

(<br />

SCSI_CTRL *pScsiCtrl, /* ptr to SCSI controller info */<br />

int devBusId, /* SCSI bus ID of device to select */<br />

UINT selTimeOut, /* select t-o period (usec) */<br />

UINT8 *msgBuf, /* ptr to identification message */<br />

UINT msgLen /* maximum number of message bytes */<br />

)<br />

{<br />

int lockKey; /* saved interrupt lock key */<br />

lockKey = intLock ();<br />

/* Select device */<br />

intUnlock (lockKey);<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxXferParamsQuery - get (synchronous) transfer parameters<br />

*<br />

* Updates the synchronous transfer parameters suggested in the call to match<br />

* the SCSI controller's capabilities. Transfer period is in SCSI units<br />

* (multiples of 4 ns).<br />

*<br />

* RETURNS: OK<br />

330


I<br />

Writing a SCSI-2 Device Driver<br />

*/<br />

LOCAL STATUS xxxXferParamsQuery<br />

(<br />

SCSI_CTRL *pScsiCtrl, /* ptr to SBIC info */<br />

UINT8 *pOffset, /* max REQ/ACK offset [in/out] */<br />

UINT8 *pPeriod /* min transfer period [in/out] */<br />

)<br />

{<br />

/* read offset and period values */<br />

return (OK);<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxXferParamsSet - set transfer parameters<br />

*<br />

* Programs the SCSI controller to use the specified transfer parameters. An<br />

* offset of zero specifies asynchronous transfer (period is then irrelevant).<br />

*<br />

* RETURNS: OK if transfer parameters are OK, else ERROR.<br />

*/<br />

LOCAL STATUS xxxXferParamsSet<br />

(<br />

SCSI_CTRL *pScsiCtrl, /* ptr to SBIC info */<br />

UINT8 offset, /* max REQ/ACK offset */<br />

UINT8 period /* min transfer period */<br />

)<br />

{<br />

/* set the appropriate SCSI controller registers */<br />

return (OK);<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxInfoXfer - transfer information bytes to/from target via SCSI bus<br />

*<br />

* Executes a "Transfer Info" command to read (write) bytes from (to) the<br />

* SCSI bus. If the transfer phase is DATA IN or DATA OUT and there is a<br />

* DMA routine available, DMA is used - otherwise it's a tight programmed<br />

* i/o loop.<br />

*<br />

* RETURNS: Number of bytes transferred across SCSI bus, or ERROR.<br />

*/<br />

I<br />

LOCAL int xxxInfoXfer<br />

(<br />

FAST SCSI_CTRL *pScsiCtrl, /* ptr to SCSI controller info */<br />

int phase, /* SCSI phase being transferred */<br />

FAST UINT8 *pBuf, /* ptr to byte buffer for i/o */<br />

UINT bufLength /* number of bytes to be transferred */<br />

)<br />

{<br />

331


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

pSbic = (SBIC *) pScsiCtrl;<br />

/* Handle phase changes */<br />

/* Start DMA, if used, or programmed i/o loop to transfer data */<br />

/* Wait for transfer to complete: find out how many bytes transferred */<br />

semTake (&pSbic->xferDoneSem, WAIT_FOREVER);<br />

/*<br />

* If there are bytes left to be transferred return ERROR<br />

* If DMA is used for tranfer do a SCSI DMA Abort<br />

*/<br />

xxxXferCountGet (pSbic, &bytesLeft);<br />

return (bufLength - bytesLeft);<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxXferCountSet - load the SCSI controller transfer counter with count.<br />

*<br />

* RETURNS: OK if count is in range 0 - 0xffffff, otherwise ERROR.<br />

*<br />

*/<br />

LOCAL STATUS xxxXferCountSet<br />

(<br />

FAST SBIC *pSbic, /* ptr to SBIC info */<br />

FAST UINT count /* count value to load */<br />

)<br />

{<br />

/* set the appropriate SCSI controller registers */<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxXferCountGet - fetch the SCSI controller transfer count<br />

*<br />

* The value of the transfer counter is copied to *pCount.<br />

*<br />

*/<br />

LOCAL void xxxXferCountGet<br />

(<br />

FAST SBIC *pSbic, /* ptr to SBIC info */<br />

FAST UINT *pCount /* ptr to returned value */<br />

)<br />

{<br />

/* read the appropriate SCSI controller registers */<br />

}<br />

/***************************************************************************<br />

*<br />

332


I<br />

Writing a SCSI-2 Device Driver<br />

* xxxCommand - write a command code to the SCSI controller Command Register<br />

*<br />

*/<br />

LOCAL void xxxCommand<br />

(<br />

SBIC *pSbic, /* ptr to SBIC info */<br />

UINT8 cmdCode /* new command code */<br />

)<br />

{<br />

/* set the appropriate SCSI controller registers */<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxIntr - interrupt service routine for the SCSI controller<br />

*<br />

*/<br />

LOCAL void xxxIntr<br />

(<br />

SBIC *pSbic /* ptr to SBIC info */<br />

)<br />

{<br />

SCSI_EVENT event;<br />

/* Check the SCSI status. Handle state transitions */<br />

switch (scsiStatus)<br />

{<br />

...<br />

/* the list of event types is defined is scsi2Lib.h */<br />

case ...<br />

event.type = SCSI_EVENT_XFER_REQUEST;<br />

event.phase = busPhase;<br />

break;<br />

I<br />

case ...<br />

}<br />

/* Synchronize with task-level code */<br />

semGive (&pSbic->xferDoneSem);<br />

/* Post event to SCSI manager for further processing */<br />

scsiMgrEventNotify ((SCSI_CTRL *)pSbic, &event, sizeof (event));<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxRegRead - Get the contents of a specified SCSI controller register<br />

*/<br />

333


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

LOCAL void xxxRegRead<br />

(<br />

SBIC *pSbic, /* ptr to an SBIC structure */<br />

UINT8 regAdrs, /* address of register to read */<br />

int *pDatum /* buffer for return value */<br />

)<br />

{<br />

/* read the appropriate SCSI controller registers */<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxRegWrite - write a value to a specified SCSI controller register<br />

*<br />

*/<br />

LOCAL void xxxRegWrite<br />

(<br />

SBIC *pSbic, /* ptr to an SBIC structure */<br />

UINT8 regAdrs, /* address of register to write */<br />

UINT8 datum /* value to be written */<br />

)<br />

{<br />

/* write the appropriate SCSI controller registers */<br />

}<br />

I.4.2 Advanced SCSI Controller Driver<br />

The advanced SCSI controller incorporates all the low-level state machine<br />

functions within the driver. This functionality replaces that provided by<br />

scsiCtrlLib. Most advanced SCSI controllers have their own SCSI I/O processor<br />

which enhances performance by managing all the low-level activities on the SCSI<br />

bus, such as phase changes and DMA data transfers. Usually the instructions to the<br />

I/O processor are machine language instructions which are written in a higher<br />

level assembly language and compiled into machine instructions. These machine<br />

instructions reside in the main DRAM area and are fetched by the I/O processor<br />

from DRAM by using a SCSI program counter and some form of indirect<br />

addressing.<br />

In the case of advanced SCSI controllers, there is usually additional event<br />

information described in a driver-specific structure such as XXX_EVENT (where<br />

XXX refers to the SCSI driver module prefix). Many thread management routines<br />

are part of the controller driver, which is not true of the basic SCSI controller<br />

drivers.<br />

334


I<br />

Writing a SCSI-2 Device Driver<br />

The Programming Interface<br />

The programming interface between the advanced SCSI controller driver and the<br />

SCSI libraries consists of routines that must be supplied by the driver and library<br />

routines which are invoked by the driver. The driver routines are not required to<br />

conform to the naming convention used here, because the routines are accessed by<br />

means of function pointers which are set in the xxxCtrlCreate( ) routine. However,<br />

this naming convention is recommended. The routines (or equivalents) that the<br />

driver must supply are:<br />

xxxEventProc( ) 1<br />

This routine is invoked by the SCSI manager to parse events and take<br />

appropriate action.<br />

xxxThreadInit( )<br />

This routine initializes the SCSI thread structures and adds any driver-specific<br />

initialization required beyond what is provided by scsiThreadInit( ).<br />

xxxThreadActivate( )<br />

This routine activates a SCSI connection, setting the appropriate thread context<br />

in the SCSI_THREAD data structure and setting all the controller registers with<br />

the appropriate values. It may call other driver routines as well as SCSI library<br />

routines.<br />

xxxThreadAbort( )<br />

If the thread is not actually connected, this routine does nothing. If the thread<br />

is connected, it sends an ABORT TAG message which causes the SCSI target to<br />

disconnect.<br />

xxxBusControl( )<br />

This routine controls some of the SCSI bus lines from the controller. This<br />

routine must reset the SCSI bus, assert ATN, or negate ACK.<br />

xxxXferParamsQuery( )<br />

This routine updates the synchronous data transfer parameters to match the<br />

capabilities of the driver and returns the optimal synchronous offset and<br />

period.<br />

xxxXferParamsSet( )<br />

This routine sets the synchronous data transfer parameters on the SCSI<br />

controller.<br />

I<br />

1. The xxx in the function name is just a place holder for whatever prefix you assign to your<br />

SCSI driver module.<br />

335


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

xxxWideXferParamsQuery( )<br />

This routine updates the wide data transfer parameters in the call to match<br />

those of the SCSI controller.<br />

xxxWideXferParamsSet( )<br />

This routine sets the wide data transfer parameters on the SCSI controller.<br />

The advanced controller driver also uses many of the facilities provided by the<br />

SCSI libraries. All the routines invoked by the SCSI controller library can also be<br />

invoked by the driver. Examining the SCSI controller library and the header file<br />

scsi2Lib.h shows all the routines available for the controller driver. The following<br />

list is a typical but not exhaustive list of routines that can be invoked by the driver:<br />

scsiCtrlInit( )<br />

This routine initializes the SCSI library data structures. It is called only once<br />

per SCSI controller.<br />

scsiMgrEventNotify( )<br />

This routine notifies the SCSI manager of an event that occurred on the SCSI<br />

bus.<br />

scsiWideXferNegotiate( )<br />

This routine initiates or continues wide data transfer negotiation. See the<br />

relevant reference entries and scsi2Lib.h for more details. It is typically<br />

invoked from the xxxThreadActivate( ) routine.<br />

scsiSyncXferNegotiate( )<br />

This routine initiates or continues synchronous data transfer negotiations. See<br />

the relevant reference entries and scsi2Lib.h for more details. It is typically<br />

invoked from the xxxThreadActivate( ) routine.<br />

scsiMgrCtrlEvent( )<br />

This routine sends an event to the SCSI controller state machine. It is usually<br />

called by the driver xxxEventProc( ) routine after a selection, reselection, or<br />

disconnection.<br />

scsiMgrBusReset( )<br />

This routine resets all physical devices in the SCSI library upon a bus-initiated<br />

reset. It is typically invoked from xxxEventProc( ).<br />

scsiMgrThreadEvent( )<br />

This routine sends an event to the thread state machine. It is called by the<br />

thread management routines within the driver; the entry point to the thread<br />

routines is by way of xxxEventProc( ). In general, xxxEventProc( ) is the<br />

general routine which calls other driver-specific thread-management routines.<br />

336


I<br />

Writing a SCSI-2 Device Driver<br />

For a better understanding, look at the advanced SCSI controller driver<br />

template and also examine an actual driver.<br />

scsiMsgOutComplete( )<br />

This routine performs post-processing after a SCSI message out has been sent.<br />

It is also invoked from the driver thread management routines.<br />

scsiMsgInComplete( )<br />

This routine performs post-processing after a SCSI message in is received. It is<br />

invoked from the driver thread management routines.<br />

scsiMsgOutReject( )<br />

This routine performs post-processing when an outgoing message has been<br />

rejected.<br />

scsiIdentMsgParse( )<br />

This routine parses an incoming identify message when VxWorks has been<br />

selected or reselected.<br />

scsiIdentMsgBuild( )<br />

This routine builds an identify message in the caller’s buffer.<br />

scsiCacheSnoopEnable( )<br />

This routine informs the library that hardware cache snooping is enabled and<br />

that it is unnecessary to call cache-specific routines.<br />

scsiCacheSnoopDisable( )<br />

This routine informs the library that hardware snooping has been disabled or<br />

does not exist and that the library must perform cache coherency.<br />

scsiCacheSynchronize( )<br />

This routine is called by the driver for all cache-coherency needs.<br />

scsiThreadInit( )<br />

This routine performs general thread initialization; it is invoked by the driver<br />

xxxThreadInit( ) routine.<br />

Example I-2 provides an advanced SCSI controller driver template and<br />

Example I-3 shows a SCSI I/O processor assembly language template. These<br />

examples show how such drivers may be structured. Many details are not<br />

included in the templates; these templates simply serve to provide a high-level<br />

picture of what is involved. Once the basic structure of the template is understood,<br />

examining an actual advanced controller driver will clarify the issues involved,<br />

especially thread management.<br />

I<br />

337


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Example I-2<br />

Template: Advanced Controller Driver<br />

/* xxxLib.c - XXX SCSI I/O Processor (SIOP) library */<br />

/* Copyright 1989-1996 Wind River Systems, Inc. */<br />

#include "copyright_wrs.h"<br />

/*<br />

modification history<br />

--------------------<br />

01g,19aug96,dds written<br />

*/<br />

/*<br />

DESCRIPTION<br />

This is the I/O driver for the XXX SCSI I/O Processor (SIOP).<br />

It is designed to work with scsiLib and scsi2Lib. This driver<br />

runs in conjunction with a script program for the XXX controller.<br />

These scripts use DMA transfers for all data, messages and status.<br />

This driver supports cache functions through scsi2Lib.<br />

USER-CALLABLE ROUTINES<br />

Most of the routines in this driver are accessible only through the I/O<br />

system. The following routines must be called directly: xxxCtrlCreate()<br />

to create a controller structure, and xxxCtrlInit() to initialize it.<br />

The XXX SCSI Controller's hardware registers need to be configured according<br />

to the hardware implementation. If the default configuration is not proper,<br />

the routine xxxSetHwRegister() should be used to properly configure<br />

the registers.<br />

INTERNAL<br />

This driver supports multiple initiators, disconnect/reconnect, tagged<br />

command queueing, synchronous data transfer and wide data transfer protocols.<br />

In general, the SCSI system and this driver automatically choose the<br />

best combination of these features to suit the target devices used.<br />

However, the default choices may be over-ridden by using the function<br />

"scsiTargetOptionsSet()" (see scsi2Lib).<br />

There are debug variables to trace events in the driver.<br />

scsiLib debug variable, trace event in scsiLib, xxxScsiPhase(),<br />

and xxxTransact().<br />

prints interrupt informations.<br />

INCLUDE FILES<br />

xxx.h, xxxScript.h and scsiLib.h<br />

*/<br />

#define INCLUDE_SCSI2<br />

#include "vxWorks.h"<br />

#include "memLib.h"<br />

#include "ctype.h"<br />

#include "stdlib.h"<br />

#include "string.h"<br />

#include "stdio.h"<br />

#include "logLib.h"<br />

338


I<br />

Writing a SCSI-2 Device Driver<br />

#include "semLib.h"<br />

#include "intLib.h"<br />

#include "errnoLib.h"<br />

#include "cacheLib.h"<br />

#include "taskLib.h"<br />

#include "drv/scsi/xxx.h"<br />

#include "drv/scsi/xxxScript.h"<br />

/* defines */<br />

typedef XXX_SCSI_CTRL SIOP;<br />

/* Configurable options */<br />

int xxxSingleStepSemOptions = SEM_Q_PRIORITY;<br />

char *xxxScsiTaskName<br />

= SCSI_DEF_TASK_NAME;<br />

int xxxScsiTaskOptions = SCSI_DEF_TASK_OPTIONS;<br />

int xxxScsiTaskPriority = SCSI_DEF_TASK_PRIORITY;<br />

int xxxScsiTaskStackSize = SCSI_DEF_TASK_STACK_SIZE;<br />

/***************************************************************************<br />

*<br />

* xxxCtrlCreate - create a control structure for the XXX SCSI controller<br />

*<br />

* This routine creates a SCSI controller data structure and must be called<br />

* before using a SCSI controller chip. It should be called once and only<br />

* once for a specified SCSI controller. Since it allocates memory<br />

* for a structure needed by all routines in xxxLib, it must be called before<br />

* any other routines in the library. After calling this routine,<br />

* xxxCtrlInit() should be called at least once before any SCSI transactions<br />

* are initiated using the SCSI controller.<br />

*<br />

* RETURNS: A pointer to XXX_SCSI_CTRL structure, or NULL if memory<br />

* is unavailable or there are invalid parameters.<br />

*/<br />

XXX_SCSI_CTRL *xxxCtrlCreate<br />

(<br />

UINT8 *baseAdrs, /* base address of the SCSI controller */<br />

UINT clkPeriod, /* clock controller period (nsec*100) */<br />

UINT16 devType /* XXX SCSI device type */<br />

)<br />

I<br />

{<br />

FAST SIOP *pSiop; /* ptr to SCSI controller info */<br />

/* check that dma buffers are cache-coherent */<br />

/* cacheDmaMalloc the controller structure and other driver structures */<br />

pScsiCtrl = (SCSI_CTRL *) pSiop;<br />

/* inform the SCSI libraries about the size of an XXX event and thread */<br />

pScsiCtrl->eventSize = sizeof (XXX_EVENT);<br />

pScsiCtrl->threadSize = sizeof (XXX_THREAD);<br />

339


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

pScsiCtrl->scsiTransact = (FUNCPTR) scsiTransact;<br />

pScsiCtrl->scsiEventProc<br />

= (VOIDFUNCPTR) xxxEvent;<br />

pScsiCtrl->scsiThreadInit = (FUNCPTR) xxxThreadInit;<br />

pScsiCtrl->scsiThreadActivate = (FUNCPTR) xxxThreadActivate;<br />

pScsiCtrl->scsiThreadAbort = (FUNCPTR) xxxThreadAbort;<br />

pScsiCtrl->scsiBusControl = (FUNCPTR) xxxScsiBusControl;<br />

pScsiCtrl->scsiXferParamsQuery = (FUNCPTR) xxxXferParamsQuery;<br />

pScsiCtrl->scsiXferParamsSet = (FUNCPTR) xxxXferParamsSet;<br />

pScsiCtrl->scsiWideXferParamsQuery = (FUNCPTR) xxxWideXferParamsQuery;<br />

pScsiCtrl->scsiWideXferParamsSet = (FUNCPTR) xxxWideXferParamsSet;<br />

/* the following virtual functions are not used with this driver */<br />

pScsiCtrl->scsiDevSelect = NULL;<br />

pScsiCtrl->scsiInfoXfer = NULL;<br />

/* fill in generic SCSI info for this controller */<br />

scsiCtrlInit (&pSiop->scsiCtrl);<br />

/* fill in SCSI controller specific data for this controller */<br />

/* initialize controller state variables */<br />

/*<br />

* Initialize fixed fields in client shared data area. This "shared"<br />

* area of memory is shared between this driver and the scripts I/O<br />

* processor. Fields like data pointers, data size, message pointer,<br />

* message size, status pointer and size, etc. are typically the<br />

* pieces of information shared. These fields are updated and managed<br />

* before and after an I/O process.<br />

*/<br />

xxxSharedMemInit (pSiop, pSiop->pClientShMem);<br />

/* spawn SCSI manager - use generic code from "scsiLib.c" */<br />

pScsiCtrl->scsiMgrId = taskSpawn (xxxScsiTaskName,<br />

xxxScsiTaskPriority,<br />

xxxScsiTaskOptions,<br />

xxxScsiTaskStackSize,<br />

(FUNCPTR) scsiMgr,<br />

(int) pSiop, 0, 0, 0, 0, 0, 0, 0, 0, 0);<br />

return (pSiop);<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxCtrlInit - initialize a XXX SCSI controller structure<br />

*<br />

* This routine initializes an SCSI controller structure, after the structure<br />

* is created with xxxCtrlCreate(). This structure must be initialized before<br />

* the SCSI controller can be used. It may be called more than once if<br />

* needed;however,it should only be called while there is no activity on the<br />

* SCSI interface. A detailed description of the input parameters follows:<br />

340


I<br />

Writing a SCSI-2 Device Driver<br />

*<br />

* RETURNS: OK, or ERROR if parameters are out of range.<br />

*/<br />

STATUS xxxCtrlInit<br />

(<br />

FAST XXX_SCSI_CTRL *pSiop, /* ptr to SCSI controller struct */<br />

int scsiCtrlBusId /* SCSI bus ID of this SCSI controller */<br />

)<br />

{<br />

SCSI_CTRL * pScsiCtrl = (SCSI_CTRL *) pSiop;<br />

/* initialize the SCSI controller */<br />

xxxHwInit (pSiop);<br />

/*<br />

* Put the scripts I/O processor in a state whereby it is ready for<br />

* selections or reselection from the SCSI bus. Such a state continues<br />

* until either a selection or selection occurs or the driver interrupts<br />

* the scripts processor and resets its program counter to begin<br />

* execution elsewhere.<br />

*/<br />

xxxScriptStart (pSiop, (XXX_THREAD *) pScsiCtrl->pIdentThread,<br />

XXX_SCRIPT_WAIT);<br />

return (OK);<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxHwInit - initialize the SCSI controller chip to a known state<br />

*<br />

* RETURNS: N/A<br />

*/<br />

LOCAL void xxxHwInit<br />

(<br />

FAST SIOP *pSiop /* ptr to a SCSI controller info structure */<br />

)<br />

{<br />

/* initialize hardware independent registers */<br />

}<br />

I<br />

/***************************************************************************<br />

*<br />

* xxxScsiBusReset - assert the RST line on the SCSI bus<br />

*<br />

* Issue a SCSI Bus Reset command to the XXX SCSI controller. This should put<br />

* all devices on the SCSI bus in an initial quiescent state.<br />

*<br />

* RETURNS: N/A<br />

*/<br />

341


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

LOCAL void xxxScsiBusReset<br />

(<br />

FAST SIOP *pSiop /* ptr to SCSI controller info */<br />

)<br />

{<br />

/* set appropriate register values in order to reset the SCSI bus */<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxIntr - interrupt service routine for the SCSI controller<br />

*<br />

* Find the event type corresponding to this interrupt, and carry out any<br />

* actions which must be done before the SCSI controller is re-started.<br />

* Determine whether or not the SCSI controller is connected to the bus<br />

* (depending on the event type - see note below). If not, start a client<br />

* script if possible or else just make the SCSI controller wait for something<br />

* else to happen.<br />

*<br />

* Notify the SCSI manager of a controller event.<br />

*<br />

* RETURNS: N/A<br />

*/<br />

void xxxIntr<br />

(<br />

SIOP *pSiop<br />

)<br />

{<br />

XXX_EVENT<br />

SCSI_EVENT<br />

event;<br />

pScsiEvent = (SCSI_EVENT *) &event;<br />

BOOL connected = FALSE;<br />

BOOL notify = TRUE;<br />

int oldState = (int) pSiop->state;<br />

/* Save (partial) SCSI controller register context in current thread */<br />

/* Get event type */<br />

pScsiEvent-type = xxxEventTypeGet (pSiop);<br />

/* fill in event information based upon the nature of the event */<br />

/* controller is now idle: if possible, make it run a script. */<br />

xxxScriptStart (pSiop, (XXX_THREAD *) pScsiCtrl->pIdentThread,<br />

XXX_SCRIPT_WAIT);<br />

/* Send the event to the SCSI manager to be processed. */<br />

scsiMgrEventNotify ((SCSI_CTRL *) pSiop, pScsiEvent, sizeof (event));<br />

}<br />

342


I<br />

Writing a SCSI-2 Device Driver<br />

/***************************************************************************<br />

*<br />

* xxxEventTypeGet - parse SCSI and DMA status registers at interrupt time<br />

*<br />

* RETURNS: an interrupt (event) type code<br />

*/<br />

LOCAL int xxxEventTypeGet<br />

(<br />

SIOP * pSiop<br />

)<br />

{<br />

/* Read interrupt status registers */<br />

key = intLock ();<br />

/* Check for fatal errors first */<br />

/* No fatal errors; try the rest (order of tests is important) */<br />

return (INTERRUPT_TYPE);<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxThreadActivate - activate a SCSI connection for an initiator thread<br />

*<br />

* Set whatever thread/controller state variables need to be set. Ensure that<br />

* all buffers used by the thread are coherent with the contents of the<br />

* system caches (if any).<br />

*<br />

* Set transfer parameters for the thread based on what its target device<br />

* last negotiated.<br />

*<br />

* Update the thread context (including shared memory area) and note that<br />

* there is a new client script to be activated (see "xxxActivate()").<br />

*<br />

* Set the thread's state to ESTABLISHED.<br />

* Do not wait for the script to be activated. Completion of the script is<br />

* signalled by an event which is handled by "xxxEvent()".<br />

*<br />

* RETURNS: OK or ERROR<br />

*/<br />

LOCAL STATUS xxxThreadActivate<br />

(<br />

SIOP * pSiop, /* ptr to controller info */<br />

XXX_THREAD * pThread /* ptr to thread info */<br />

)<br />

{<br />

scsiCacheSynchronize (pScsiThread, SCSI_CACHE_PRE_COMMAND);<br />

I<br />

scsiWideXferNegotiate (pScsiCtrl, pScsiTarget, WIDE_XFER_NEW_THREAD);<br />

scsiSyncXferNegotiate (pScsiCtrl, pScsiTarget, SYNC_XFER_NEW_THREAD);<br />

if (xxxThreadParamsSet (pThread, pScsiTarget->xferOffset,<br />

pScsiTarget->xferPeriod) != OK)<br />

return (ERROR);<br />

343


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

/* Update thread context; activate the thread */<br />

xxxThreadUpdate (pThread);<br />

if (xxxActivate (pSiop, pThread) != OK)<br />

return (ERROR);<br />

pScsiCtrl->pThread = pScsiThread;<br />

xxxThreadStateSet (pThread, SCSI_THREAD_ESTABLISHED);<br />

return (OK);<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxThreadAbort - abort a thread<br />

*<br />

* If the thread is not currently connected, do nothing and return FALSE to<br />

* indicate that the SCSI manager should abort the thread.<br />

*<br />

* RETURNS: TRUE if the thread is being aborted by this driver (i.e. it is<br />

* currently active on the controller, else FALSE.<br />

*/<br />

LOCAL BOOL xxxThreadAbort<br />

(<br />

SIOP * pSiop, /* ptr to controller info */<br />

XXX_THREAD * pThread /* ptr to thread info */<br />

)<br />

{<br />

xxxAbort (pSiop);<br />

xxxThreadStateSet (pThread, SCSI_THREAD_ABORTING);<br />

return (TRUE);<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxEvent - XXX SCSI controller event processing routine<br />

*<br />

* Parse the event type and act accordingly. Controller-level events are<br />

* handled within this function, and the event is then passed to the current<br />

* thread (if any) for thread-level processing.<br />

*<br />

* RETURNS: N/A<br />

*/<br />

LOCAL void xxxEvent<br />

(<br />

SIOP * pSiop,<br />

XXX_EVENT * pEvent<br />

)<br />

{<br />

SCSI_CTRL * pScsiCtrl = (SCSI_CTRL *) pSiop;<br />

SCSI_EVENT * pScsiEvent = (SCSI_EVENT *) pEvent;<br />

XXX_THREAD * pThread = (XXX_THREAD *) pScsiCtrl->pThread;<br />

344


I<br />

Writing a SCSI-2 Device Driver<br />

/* Do controller-level event processing */<br />

/* If there's a thread on the controller, forward the event to it */<br />

if (pThread != 0)<br />

xxxThreadEvent (pThread, pEvent);<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxThreadEvent - SCSI controller thread event processing routine<br />

*<br />

* Forward the event to the proper handler for the thread's current role.<br />

*<br />

* If the thread is still active, update the thread context (including<br />

* shared memory area) and resume the thread.<br />

*<br />

* RETURNS: N/A<br />

*/<br />

LOCAL void xxxThreadEvent<br />

(<br />

XXX_THREAD * pThread,<br />

XXX_EVENT * pEvent<br />

)<br />

{<br />

SCSI_EVENT * pScsiEvent = (SCSI_EVENT *) pEvent;<br />

SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;<br />

SIOP * pSiop = (SIOP *) pScsiThread->pScsiCtrl;<br />

XXX_SCRIPT_ENTRY entryPt;<br />

switch (pScsiThread->role)<br />

{<br />

case SCSI_ROLE_INITIATOR:<br />

xxxInitEvent (pThread, pEvent);<br />

entryPt = XXX_SCRIPT_INIT_CONTINUE;<br />

break;<br />

case SCSI_ROLE_IDENT_INIT:<br />

xxxInitIdentEvent (pThread, pEvent);<br />

I<br />

entryPt = XXX_SCRIPT_INIT_CONTINUE;<br />

break;<br />

case SCSI_ROLE_IDENT_TARG:<br />

xxxTargIdentEvent (pThread, pEvent);<br />

entryPt = XXX_SCRIPT_TGT_DISCONNECT;<br />

break;<br />

case SCSI_ROLE_TARGET:<br />

default:<br />

logMsg ("xxxThreadEvent: thread 0x%08x: invalid role (%d)\n",<br />

(int) pThread, pScsiThread->role, 0, 0, 0, 0);<br />

345


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

}<br />

entryPt = XXX_SCRIPT_TGT_DISCONNECT;<br />

break;<br />

/* Resume thread if it is still connected */<br />

xxxResume (pSiop, pThread, entryPt);<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxResume - resume a script corresponding to a suspended thread<br />

*<br />

* NOTE: the script can only be resumed if the controller is currently idle.<br />

* To avoid races, interrupts must be locked while this is checked and the<br />

* script re-started.<br />

*<br />

* Reasons why the controller might not be idle include SCSI bus reset and<br />

* unexpected disconnection, both of which might occur in practice. Hence<br />

* this is not considered to be a major software error.<br />

*<br />

* RETURNS: OK, or ERROR if the controller is in an invalid state (this<br />

* should not be treated as a major software failure).<br />

*/<br />

LOCAL STATUS xxxResume<br />

(<br />

SIOP * pSiop, /* ptr to controller info */<br />

XXX_THREAD * pThread, /* ptr to thread info */<br />

XXX_SCRIPT_ENTRY entryId /* entry point of script to resume */<br />

)<br />

{<br />

STATUS status;<br />

int key;<br />

/*<br />

* Check validity of connection and start script if OK<br />

*/<br />

key = intLock ();<br />

xxxScriptStart (pSiop, pThread, entryId);<br />

pSiop->state = NCR810_STATE_ACTIVE;<br />

status = OK;<br />

intUnlock (key);<br />

return (status);<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxInitEvent - XXX SCSI controller initiator thread event processing rout<br />

*<br />

* Parse the event type and handle it accordingly. This may result in state<br />

* changes for the thread, state variables being updated, etc.<br />

346


I<br />

Writing a SCSI-2 Device Driver<br />

*<br />

* RETURNS: N/A<br />

*/<br />

LOCAL void xxxInitEvent<br />

(<br />

XXX_THREAD * pThread,<br />

XXX_EVENT * pEvent<br />

)<br />

{<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxSharedMemInit - initialize the fields in a shared memory area<br />

*<br />

* Initialize pointers and counts for all message transfers. These are<br />

* always directed to buffers provided by the SCSI_CTRL structure.<br />

*<br />

* RETURNS: N/A<br />

*/<br />

LOCAL void xxxSharedMemInit<br />

(<br />

SIOP *<br />

pSiop,<br />

XXX_SHARED * pShMem<br />

)<br />

{<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxThreadInit - initialize a client thread structure<br />

*<br />

* Initialize the fixed data for a thread (i.e., independent of the command).<br />

* Called once when a thread structure is first created.<br />

*<br />

* RETURNS: OK, or ERROR if an error occurs<br />

*/<br />

LOCAL STATUS xxxThreadInit<br />

(<br />

SIOP *<br />

pSiop,<br />

XXX_THREAD * pThread<br />

)<br />

{<br />

scsiThreadInit (&pThread->scsiThread);<br />

I<br />

return (OK);<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxActivate - activate a script corresponding to a new thread<br />

*<br />

* Request activation of (the script for) a new thread, if possible; do not<br />

* wait for the script to complete (or even start) executing. Activation<br />

* is requested by signalling the controller, which causes an interrupt.<br />

347


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

* The script is started by the ISR in response to this event.<br />

*<br />

* NOTE: Interrupt locking is required to ensure that the correct action<br />

* is taken once the controller state has been checked.<br />

*<br />

* RETURNS: OK, or ERROR if the controller is in an invalid state (this<br />

* indicates a major software failure).<br />

*/<br />

LOCAL STATUS xxxActivate<br />

(<br />

SIOP *<br />

pSiop,<br />

XXX_THREAD * pThread<br />

)<br />

{<br />

key = intLock ();<br />

/* Activate controller for the current thread */<br />

intUnlock (key);<br />

return (status);<br />

}<br />

/****************************************************************************<br />

*<br />

* xxxAbort - abort the active script corresponding to the current thread<br />

*<br />

* Check that there is currently an active script running. If so, set the<br />

* SCSI controller Abort flag which halts the script and causes an<br />

* interrupt.<br />

*<br />

* RETURNS: N/A<br />

*/<br />

LOCAL void xxxAbort<br />

(<br />

SIOP * pSiop /* ptr to controller info */<br />

)<br />

{<br />

STATUS status;<br />

int key;<br />

key = intLock ();<br />

/* Abort the active script corresponding to the current thread */<br />

intUnlock (key);<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxScriptStart - start the SCSI controller executing a script<br />

*<br />

* Restore the SCSI controller register context, including the shared memory<br />

* area, from the thread context. Put the address of the script entry point<br />

348


I<br />

Writing a SCSI-2 Device Driver<br />

* into the DSP register. If not in single-step mode, start the script.<br />

*<br />

* NOTE: should always be called with SCSI controller's interrupts locked.<br />

*<br />

* RETURNS: N/A<br />

*/<br />

LOCAL void xxxScriptStart<br />

(<br />

SIOP *pSiop, /* pointer to SCSI controller info */<br />

XXX_THREAD *pThread, /* ncr thread info */<br />

XXX_SCRIPT_ENTRY entryId /* routine address entry point */<br />

)<br />

{<br />

static ULONG * xxxScriptEntry [] =<br />

{<br />

xxxWait, /* wait for re-select or host cmd */<br />

xxxInitStart, /* start an initiator thread */<br />

xxxInitContinue, /* continue an initiator thread */<br />

xxxTgtDisconnect, /* disconnect a target thread */<br />

};<br />

/* Restore the SCSI controller register context for this thread. */<br />

/*<br />

* Set the shared data address, load the script start address,<br />

* then start the SCSI controller.<br />

*/<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxXferParamsQuery - get (synchronous) transfer parameters<br />

*<br />

* Updates the synchronous transfer parameters suggested in the call to match<br />

* the XXX SCSI controller's capabilities. Transfer period is in SCSI units<br />

* (multiples * of 4 ns).<br />

*<br />

* RETURNS: OK<br />

*/<br />

I<br />

LOCAL STATUS xxxXferParamsQuery<br />

(<br />

SCSI_CTRL *pScsiCtrl, /* ptr to controller info */<br />

UINT8 *pOffset, /* max REQ/ACK offset [in/out] */<br />

UINT8 *pPeriod /* min transfer period [in/out] */<br />

)<br />

{<br />

return (OK);<br />

}<br />

349


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

/***************************************************************************<br />

*<br />

* xxxWideXferParamsQuery - get wide data transfer parameters<br />

*<br />

* Updates the wide data transfer parameters suggested in the call to match<br />

* the XXX SCSI controller's capabilities. Transfer width is in the units<br />

* of the WIDE DATA TRANSFER message's transfer width exponent field. This is<br />

* an 8 bit field where 0 represents a narrow transfer of 8 bits, 1 represents<br />

* a wide transfer of 16 bits and 2 represents a wide transfer of 32 bits.<br />

*<br />

* RETURNS: OK<br />

*/<br />

LOCAL STATUS xxxWideXferParamsQuery<br />

(<br />

SCSI_CTRL *pScsiCtrl, /* ptr to controller info */<br />

UINT8 *xferWidth /* suggested transfer width */<br />

)<br />

{<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxXferParamsSet - set transfer parameters<br />

*<br />

* Validate the requested parameters, convert to the XXX SCSI controller's<br />

* native format and save in the current thread for later use (the chip's<br />

* registers are not actually set until the next script activation for this<br />

* thread).<br />

*<br />

* Transfer period is specified in SCSI units (multiples of 4 ns). An offset<br />

* of zero specifies asynchronous transfer.<br />

*<br />

* RETURNS: OK if transfer parameters are OK, else ERROR.<br />

*/<br />

LOCAL STATUS xxxXferParamsSet<br />

(<br />

SCSI_CTRL *pScsiCtrl, /* ptr to controller info */<br />

UINT8 offset, /* max REQ/ACK offset */<br />

UINT8 period /* min transfer period */<br />

)<br />

{<br />

}<br />

/***************************************************************************<br />

*<br />

* xxxWideXferParamsSet - set wide transfer parameters<br />

*<br />

* Assume valid parameters and set the XXX's thread parameters to the<br />

* appropriate values. The actual registers are not written yet, but will<br />

* be written from the thread values when it is activated.<br />

*<br />

* Transfer width is specified in SCSI transfer width exponent units.<br />

*<br />

* RETURNS: OK<br />

350


I<br />

Writing a SCSI-2 Device Driver<br />

*/<br />

LOCAL STATUS xxxWideXferParamsSet<br />

(<br />

SCSI_CTRL *pScsiCtrl, /* ptr to controller info */<br />

UINT8 xferWidth /* wide data transfer width */<br />

)<br />

{<br />

}<br />

Example I-3<br />

Template: Advanced I/O Processor Driver<br />

; xxxInit.n Script I/O processor assembly code for xxxLib Driver<br />

;<br />

; Copyright 1989-1996 Wind River Systems, Inc.<br />

;<br />

;/*<br />

;Modification history<br />

;--------------------<br />

;01a,28jun95,jds Created. Adapted from ncr710init.n<br />

;<br />

;<br />

;INTERNAL<br />

;This file contains the assembly level SCSI scripts instructions which are<br />

;used in conjunction with a higher level controller driver. To operate in<br />

;SCSI SCRIPTS mode the SCSI I/O Processor requires only a SCRIPTS start<br />

;address and a signal to begin operation. At that point, the processor<br />

;begins fetching instructions from external memory and then executes them.<br />

;The start address is written to the DMA SCRIPTS Pointer (DSP) register,<br />

;which acts like a typical program counter. All SCRIPT instructions are<br />

;fetched from external memory. The SCSI I/O Processor fetches and executes<br />

;its own instructions by becoming a bus master on the host bus. Instructions<br />

;are executed until a SCSI SCRIPTS interrupt instruction is encountered or<br />

;until an unexpected interrupt causes an interrupt to the external<br />

;processor. Once an interrupt is generated, the SCSI I/O Processor halts all<br />

;operations until the interrupt is serviced. The further execution of<br />

;SCRIPTS is then controlled by the SCSI controller driver which decides<br />

;at which entry point should the SCRIPT processor start executing.<br />

;<br />

;There are four SCRIPT entry points which could be used by the controller<br />

;driver. Execution thereafter is a function of the logic flow within the<br />

;SCRIPTS and cannot be controlled by the driver. Thus, controll is<br />

;transferred to the SCRIPTS processor by the controller driver at well known<br />

;entry points and this control is returned to the controller driver by the<br />

;SCRIPTS by generating a SCRIPTS interrupt. The four SCRIPTS entry points<br />

;are described below:<br />

;<br />

;1) xxxWait<br />

; If the SCSI controller is not connected to the bus, this entry point is<br />

; used. The SCRIPTS processor waits for selection or re-selection by a SCSI<br />

; target device (which acts as an initiator during selection), or can be<br />

; interrupted by a new command from the host. This is done by signalling<br />

; the processor via register bits. Thus this entry point puts the SCRIPTS<br />

; processor into a passive mode.<br />

I<br />

351


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

;<br />

;2) xxxInitStart<br />

; This entry point is used to start a new initiator thread or I/O process<br />

; (in SCSI parlance), selecting a target, sending the identify message and<br />

; thus establishing the ITL nexus, and then continuing to follow the SCSI<br />

; protocol as dictated by the SCSI target, which drives the bus; thus,<br />

; transferring the command, data, messages and status. This processing is<br />

; actually done, within the code of the xxxInitContinue entry point. i.e<br />

; if no stopping condition is encountered, execution continues on into the<br />

; next logical entry point.<br />

;<br />

;3) xxxInitContinue<br />

; This entry point resumes a suspended SCSI thread. SCSI threads are<br />

; when futher processing is required by the controller driver and an int<br />

; instruction is executed. However, when the higher level management has<br />

; been worked out, control comes back to a suspended thread and the process<br />

; of cycling through all the SCSI infromation tranfer phases continues. In<br />

; essence, this entry point is the "meat" of an I/O process. The following<br />

; phases are managed by this entry point.<br />

; DATA_OUT<br />

; DATA_IN<br />

; COMMAND<br />

; STATUS<br />

; MSG_OUT<br />

; MSG_IN<br />

; XXX_ILLEGAL_PHASE<br />

;<br />

;4) xxxTgtDisconnect<br />

; Disconnects a target from the SCSI bus. It is the last entry point in<br />

; an I/O process.<br />

;<br />

;<br />

;The description level of the code is close to assembly language and is<br />

;infact the language of the SCRIPTS processor. The assembly code is compiled<br />

;using an NCR compiler which generates opcodes in the form of a static C<br />

;language structure, which is then compiled and loaded into memory.<br />

;<br />

;The opcode is a pair of 32bit words, that allow operations and offsets for<br />

;the SCRIPTS processor. A deailed discussion can be found in the chip's<br />

;programmer's guide. Some of the important instructions and their formats<br />

;are listed below.<br />

;<br />

;block move instruction.<br />

; move from when PHASE_NAME<br />

; ........<br />

;I/O instructions<br />

; set target<br />

; wait DISCONNECT<br />

; wait RESELECT<br />

; select from ,@jump<br />

; .........<br />

;read/write register instructions<br />

; move REG_NAME to SFBR<br />

;SFBR acts like an accumulator allowing branch instructions based on its<br />

;value<br />

; .........<br />

352


I<br />

Writing a SCSI-2 Device Driver<br />

;<br />

;control transfer instructions<br />

; jump <br />

; int when PHASE_NAME<br />

; ...........<br />

;<br />

;INTERRUPT SOURCES<br />

;The SCSI I/O Processor has three main kind of interrupt, scsi, dma interrupt<br />

;and script interrupt. The int instruction allows the controller driver to<br />

;be interrupted with an interrupt value which is stored in the DSPS register.<br />

;*/<br />

#define NCR_COMPILE<br />

#include "xxxScript.h"<br />

;/**************************************************************************<br />

;*<br />

;* xxxWait - wait for re-selection by target, selection by initiator, or<br />

;* new command from host<br />

;*/<br />

PROC xxxWait:<br />

;setup instuctions here<br />

wait<br />

reselect REL(checkNewCmd)<br />

;<br />

; have been re-selected by a SCSI target<br />

;<br />

reselected:<br />

; handle reselects, insert the reselect logic<br />

int XXX_RESELECTED ; all seems OK so far<br />

;<br />

; May have a new host command to handle<br />

;<br />

checkNewCmd:<br />

I<br />

; insert logic for checking if the processor is connected to the bus<br />

int XXX_READY ; processor is ready for a new thread<br />

;/**************************************************************************<br />

;*<br />

;* xxxInitStart - start new initiator thread, selecting target and<br />

;* continuing to transfer command, data, messages as requested.<br />

;*<br />

;* At this point the script requires some data in the scratch registers.<br />

;* This is the threads context information.<br />

;*<br />

;* When the script finishes, these registers are updated with the new context<br />

;* information<br />

353


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

;*<br />

;*/<br />

PROC xxxInitStart:<br />

;<br />

; If required to identify, select w. ATN and try to transfer IDENTIFY message<br />

; (if this fails, continue silently). Otherwise, select without ATN.<br />

;<br />

select atn from OFFSET_DEVICE, REL(checkNewCmd)<br />

; add code to test various processor states and conditions interrupt driver<br />

; if neccessary.<br />

jump<br />

REL(nextPhase)<br />

;/**************************************************************************<br />

;*<br />

;* xxxInitContinue - resume an initiator thread<br />

;*<br />

;* At this point the script requires the threads context information in<br />

;* scratch registers<br />

;*<br />

;* When the script finishes, these scratch registers are updated with the<br />

;* the latest context information<br />

;*/<br />

PROC xxxInitContinue:<br />

; some setup code...<br />

nextPhase:<br />

;<br />

; Normal info transfer request processing<br />

;<br />

phaseSwitch:<br />

jump REL(doDataOut), when DATA_OUT<br />

jump REL(doDataIn) if DATA_IN<br />

jump REL(doCommand) if COMMAND<br />

jump REL(doStatus) if STATUS<br />

jump REL(doMsgOut) if MSG_OUT<br />

jump REL(doMsgIn) if MSG_IN<br />

int XXX_ILLEGAL_PHASE<br />

;/**************************************************************************<br />

;*<br />

;* doDataOut - handle DATA OUT phase<br />

;*/<br />

doDataOut:<br />

;...<br />

jump<br />

REL(nextPhase)<br />

354


I<br />

Writing a SCSI-2 Device Driver<br />

;/**************************************************************************<br />

;*<br />

;* doDataIn - handle DATA IN phase<br />

;*/<br />

doDataIn:<br />

;...<br />

jump<br />

REL(nextPhase)<br />

;/**************************************************************************<br />

;*<br />

;* doCommand - handle COMMAND phase<br />

;*/<br />

doCommand:<br />

;...<br />

jump<br />

REL(nextPhase)<br />

;/**************************************************************************<br />

;*<br />

;* doStatus - handle STATUS phase<br />

;*/<br />

doStatus:<br />

;...<br />

jump<br />

REL(nextPhase)<br />

;/***************************************************************************<br />

;*<br />

;* doMsgOut - handle MSG OUT phase<br />

;*/<br />

doMsgOut:<br />

I<br />

;...<br />

jump<br />

REL(nextPhase)<br />

;/**************************************************************************<br />

;*<br />

;* doMsgIn - handle MSG IN phase<br />

;*<br />

;* Note: there is little point in having the '810 parse the message type<br />

;* unless it can save the host some work by doing so; DISCONNECT and<br />

;* COMMAND COMPLETE are really the only cases in point. Multi-byte messages<br />

;* are handled specially - see the comments below.<br />

;*/<br />

doMsgIn:<br />

355


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

;...<br />

int XXX_MESSAGE_IN_RECVD ; driver handles all others<br />

;<br />

; Have received a DISCONNECT message<br />

;<br />

disconn:<br />

;...<br />

int<br />

XXX_DISCONNECTED<br />

;<br />

; Have received a COMMAND COMPLETE message<br />

;<br />

complete:<br />

;...<br />

int<br />

XXX_CMD_COMPLETE<br />

extended:<br />

int<br />

XXX_EXT_MESSAGE_SIZE<br />

contExtMsg:<br />

int XXX_MESSAGE_IN_RECVD ; at last !<br />

/****************************************************************************<br />

*<br />

* xxxTgtDisconnect - disconnect from SCSI bus<br />

*<br />

*/<br />

PROC xxxTgtDisconnect:<br />

;...<br />

disconnect<br />

int<br />

XXX_DISCONNECTED<br />

356


I<br />

Writing a SCSI-2 Device Driver<br />

I.5 The <strong>BSP</strong> Interface<br />

Example I-4<br />

The <strong>BSP</strong> provides the board information to the driver in its invocations of the<br />

initialization routines. The main tasks of the <strong>BSP</strong> sysScsiInit( ) routine, which is<br />

located in a file named sysScsi.c (included from the standard sysLib.c), are as<br />

follows:<br />

■<br />

Address all preliminary board-specific hardware initializations.<br />

■<br />

Create a controller driver object by invoking the driver’s xxxCtrlCreate( )<br />

routine and supplying the board-specific hardware information such as the<br />

base address to the SCSI controller registers.<br />

■<br />

■<br />

Connect the SCSI controller’s interrupt vector to the driver’s interrupt service<br />

routine (ISR).<br />

Perform additional driver initializations by invoking the xxxCtrlInit( ) routine<br />

and optionally the driver’s xxxHwInit( ) routine supplying board-specific<br />

information such as the SCSI initiator bus ID, and specific hardware register<br />

values.<br />

■<br />

Supply any DMA routines if an external DMA controller is being used and is<br />

not part of the SCSI controller driver.<br />

Any other board-specific configurations to initialize SCSI peripheral devices such<br />

as hard disks and tapes or block/sequential devices and file systems must also be<br />

accomplished by sysScsi.c. Such configuration initialization shall be located in<br />

sysScsiConfig( ).<br />

The following subsection introduces a template sysScsiInit( ) routine located in<br />

sysScsi.c.<br />

Template for SCSI Initialization in the <strong>BSP</strong> (sysScsi.c)<br />

/* sysScsi.c - XXX <strong>BSP</strong> SCSI-2 initialization for sysLib.c */<br />

/* Copyright 1984-1996 Wind River Systems, Inc. */<br />

#include "copyright_wrs.h"<br />

/*<br />

modification history<br />

--------------------<br />

01a,29nov95,jds written<br />

*/<br />

/*<br />

Description<br />

This file contains the sysScsiInit() and related routines necessary for<br />

I<br />

357


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

initializing the SCSI subsystem for this <strong>BSP</strong>.<br />

*/<br />

#ifdef INCLUDE_SCSI<br />

/* external inclusions */<br />

#include "drv/scsi/xxx.h"<br />

#include "tapeFsLib.h"<br />

/****************************************************************************<br />

*<br />

* sysScsiInit - initialize XXX SCSI chip<br />

*<br />

* This routine creates and initializes an SIOP structure, enabling use of the<br />

* on-board SCSI port. It also connects the proper interrupt service routine<br />

* to the desired vector, and enables the interrupt at the desired level.<br />

*<br />

* RETURNS: OK, or ERROR if the control structure is not created or the<br />

* interrupt service routine cannot be connected to the interrupt.<br />

*/<br />

STATUS sysScsiInit ()<br />

{<br />

/* perform preliminary board specific hardware initializations */<br />

/* Create the SCSI controller */<br />

if ((pSysScsiCtrl = (SCSI_CTRL *) xxxCtrlCreate<br />

(<br />

(UINT8 *) SCSI_BASE_ADRS,<br />

(UINT) XXX_40MHZ,<br />

devType<br />

{<br />

return (ERROR);<br />

}<br />

)) == NULL)<br />

/* connect the SCSI controller's interrupt service routine */<br />

if (intConnect (INUM_TO_IVEC (SCSI_INT_VEC),<br />

xxxIntr, (int) pSysScsiCtrl) == ERROR)<br />

{<br />

return (ERROR);<br />

}<br />

/* Enable SCSI interrupts */<br />

intEnable (SCSI_INT_LVL);<br />

/* initialize SCSI controller with default parameters (user tuneable) */<br />

if (xxxCtrlInit ((XXX_SCSI_CTRL *)pSysScsiCtrl,<br />

SCSI_DEF_CTRL_BUS_ID) == ERROR)<br />

358


I<br />

Writing a SCSI-2 Device Driver<br />

return (ERROR);<br />

#if (USER_D_CACHE_MODE & CACHE_SNOOP_ENABLE)<br />

#else<br />

#endif<br />

scsiCacheSnoopEnable ((SCSI_CTRL *) pSysScsiCtrl);<br />

scsiCacheSnoopDisable ((SCSI_CTRL *) pSysScsiCtrl);<br />

/* Set the appropriate board specific hardware registers for the SIOP */<br />

if (xxxSetHwRegister ((XXX_SCSI_CTRL *)pSysScsiCtrl, &hwRegs)<br />

== ERROR)<br />

return(ERROR);<br />

/* Include tape support if configured in config.h */<br />

#ifdef INCLUDE_TAPEFS<br />

tapeFsInit (); /* initialize tapeFs */<br />

#endif /* INCLUDE_TAPEFS */<br />

return (OK);<br />

}<br />

I.6 <strong>Guide</strong>lines for Developing a SCSI Driver<br />

This section provides useful tips on how to develop a new SCSI controller.<br />

Breaking the project up into small easily managed steps is generally the best<br />

approach.<br />

1. Understand the template drivers and the interfaces with the SCSI libraries.<br />

2. Copy the template driver into your new driver directory. Replace the variable<br />

routine and macro names with your chosen driver name (for example,<br />

xxxShow( ) might become myDriverShow( )).<br />

3. Make sure that the interrupt mechanism is working correctly so that upon<br />

getting a SCSI interrupt, the driver’s ISR is invoked. A good method to ensure<br />

that the ISR is invoked is to write to a well known location in memory or<br />

NVRAM so that upon re-initialization of the board the developer can tell that<br />

the ISR was entered. Getting the ISR to work is a major milestone.<br />

I<br />

359


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

4. Get the driver to select a SCSI peripheral device. A SCSI bus analyzer can<br />

clarify what is really happening on the bus, and a xxxShow( ) routine is also<br />

extremely helpful. Selecting a device is the next major milestone.<br />

5. Refine the driver using a standard programming step-wise process until the<br />

desired result is achieved.<br />

6. Run the standard Wind River SCSI tests in order to test various aspects of the<br />

SCSI bus, including multiple threads, multiple initiators, and multiple<br />

peripheral devices working concurrently as well as the performance and<br />

throughput of the driver.<br />

I.7 Test Suites<br />

The following sections list and describe the tests provided by Wind River. The<br />

source code for these test routines is located in the directory target/src/test/scsi.<br />

scsciDiskThruputTest( )<br />

This test partitions a 16MB block device into blocks of sizes 4,096, 65,536, or<br />

1,048,576 bytes. Sectors consist of blocks of 512 bytes. This test writes and reads the<br />

block size to the disk drive and calculates the time taken, thus computing the<br />

throughput.<br />

Invoke this test as follows:<br />

scsiDiskThruputTest "scsiBusId devLun numBlocks blkOffset"<br />

The individual parameters must fit the guidelines described below:<br />

scsBusId<br />

Target device ID<br />

devLun<br />

Device logical unit ID<br />

numBlocks<br />

Number of blocks in block device<br />

blkOffset<br />

Address of first block in volume<br />

360


I<br />

Writing a SCSI-2 Device Driver<br />

For example:<br />

scsiDiskThruputTest "4 0 0x0000 0x0000"<br />

scsiDiskTest( )<br />

This test performs any or all of the tests described below. The invocation for<br />

scsiDiskTest( ) is as follows:<br />

scsiDiskTest "test scsiBusId devLun Iterations numBlocks blkOffset"<br />

The individual parameters must fit the guidelines described below:<br />

test<br />

One of the following:<br />

#1: runs only commonCmdsTest( )<br />

#2: runs only directRwTest( )<br />

#3: runs only directCmdsTest( )<br />

-[a]: runs all disk tests<br />

scsBusId<br />

Target device ID<br />

devLun<br />

Device logical unit ID<br />

Iterations<br />

Number of times to execute read/write tests<br />

numBlocks<br />

Number of blocks in block device<br />

blkOffset<br />

Address of first block in volume<br />

For example, the following invocation exercises all disk tests, repeating the<br />

read/write exercise 10 times:<br />

I<br />

scsiDiskTest "-a 4 0 10 0x0000 0x0000"<br />

The default test mode is to execute all of the following three tests.<br />

361


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

commonCmdsTest( )<br />

This test exercises all mandatory SCSI common-access commands for SCSI<br />

peripheral devices. These common access commands are:<br />

– TEST UNIT READY<br />

– REQUEST SENSE<br />

– INQUIRY<br />

directRwTest( )<br />

This test exercises write, read, and check data pattern for:<br />

– 6-byte SCSI commands<br />

– 10-byte SCSI commands<br />

directCmdsTest( )<br />

This test exercises all of the direct-access commands listed below. Optionally,<br />

the FORMAT command can be tested by specifying a value of TRUE for the<br />

parameter doFormat.<br />

– MODE SENSE<br />

– MODE SELECT<br />

– RESERVE<br />

– RELEASE<br />

– READ CAPACITY<br />

– READ<br />

– WRITE<br />

– START STOP UNIT<br />

– FORMAT (optional)<br />

scsiSpeedTest( )<br />

This test initializes a block device for use with a dosFs file system. The test uses a<br />

large buffer to read and write from and to contiguous files with both buffered and<br />

non-buffered I/O.<br />

scsiSpeedTest( ) runs a number of laps, and uses timex to time the write and read<br />

operations. The speed test should be run on only one drive at a time to obtain<br />

maximum throughput.<br />

Invoke this test as follows:<br />

scsiSpeedTest "scsiBusId devLun numBlocks blkOffset"<br />

362


I<br />

Writing a SCSI-2 Device Driver<br />

The individual parameters must fit the guidelines described below:<br />

scsBusId<br />

Target device ID<br />

devLun<br />

Device logical unit ID<br />

numBlocks<br />

Number of blocks in block device<br />

blkOffset<br />

Address of first block in volume<br />

For example:<br />

scsiSpeedTest "4 0 0x0000 0x0000"<br />

tapeFsTest( )<br />

This test creates a tape file system and issues various commands to test the tape<br />

device. You can choose to test fixed-block-size tape devices, variable-block-size<br />

tape devices, or both. Fixed-block tests assume 512-byte blocks.<br />

The invocation for tapeFsTest( ) is as follows:<br />

tapeFsTest "test scsiBusId devLun"<br />

The individual parameters must fit the guidelines described below:<br />

test<br />

One of the following:<br />

-f runs only the fixed-block-size test<br />

-v runs only the variable-block-size test<br />

-a runs both tests<br />

scsBusId<br />

Target device ID<br />

devLun<br />

Device logical unit ID<br />

For example, the following invocation exercises both tests:<br />

I<br />

tapeFsTest "-a 1 0"<br />

363


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

I.8 Troubleshooting and Debugging<br />

This section provides several suggestions for troubleshooting techniques and<br />

debugging shortcuts.<br />

SCSI Cables and Termination<br />

A poor cable connection or poor SCSI termination is one of the most common<br />

sources of erratic behavior, of the VxWorks target hanging during SCSI execution,<br />

and even of unknown interrupts. The SCSI bus must be terminated at both ends,<br />

but make sure that no device in the middle of the daisy chain has pull-up<br />

terminator resistors or some other form of termination.<br />

SCSI Library Configuration<br />

Check to see that the test does not exceed the memory constraints within the<br />

library, such as the permitted number of SCSI threads, the size of the ring buffers,<br />

and the stack size of the SCSI manager. In most cases, the default values are<br />

appropriate.<br />

Data Coherency Problems<br />

Data coherency problems usually occur in hardware environments where the CPU<br />

supports data caching. First disable the data caches and verify that data corruption<br />

is occurring. If the problem disappears with the caches disabled, then the<br />

coherency problem is related to caches. (Caches can usually be turned off in the<br />

<strong>BSP</strong> by #undef USER_D_CACHE_ENABLE.) In order to further troubleshoot the<br />

data cache coherency problem, use cacheDmaMalloc( ) in the driver for all<br />

memory allocations. However, if hardware snooping is enabled then the problem<br />

may lie elsewhere.<br />

Data Address in Virtual Memory Environments<br />

If the CPU board has a Memory Management Unit (MMU), then the driver<br />

developer has to be careful when setting data address pointers during Direct<br />

Memory Access (DMA) transfers. When DMA is used in this environment, the<br />

physical memory address must be used instead of the virtual memory address.<br />

This is because during DMA transfers from the SCSI bus, the SCSI or DMA<br />

controller is the bus master and therefore the MMU on the CPU cannot translate<br />

the virtual address to the physical address. Instead, the macro<br />

CACHE_DMA_VIRT_TO_PHYS must be used when providing the data address to<br />

the DMA controller.<br />

364


J<br />

<strong>BSP</strong> Validation Test Suite<br />

Reference Entries<br />

This chapter presents the reference entries for the main <strong>BSP</strong> VTS script, bspVal,<br />

and all its subsidiary scripts.<br />

bspVal – shell script to configure and run <strong>BSP</strong> Validation Test Suite................................ 366<br />

auxClock – auxiliary clock tests ................................................................................................... 372<br />

baudConsole – console baud rate test................................................................................................ 374<br />

bootline – functionality test for bootline................................................................................... 376<br />

busTas – bus test-and-set test................................................................................................... 377<br />

eprom – EPROM tests............................................................................................................... 380<br />

error1 – error handling tests ................................................................................................... 381<br />

error2 – error handling tests ................................................................................................... 382<br />

model – sysModel( ) test ......................................................................................................... 384<br />

network – I/O tests for network ................................................................................................ 385<br />

nvRam – non-volatile RAM tests ............................................................................................. 387<br />

procNumGet – sysProcNumGet( ) test ............................................................................................. 389<br />

ram – RAM tests.................................................................................................................... 390<br />

rlogin – testing rlogin .............................................................................................................. 391<br />

scsi – SCSI test ...................................................................................................................... 393<br />

serial – serial I/O tests............................................................................................................ 395<br />

sysClock – system clock tests....................................................................................................... 397<br />

timestamp – tests timestamp timer................................................................................................ 399<br />

365


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

bspVal<br />

NAME<br />

SYNOPSIS<br />

DESCRIPTION<br />

bspVal – shell script to configure and run <strong>BSP</strong> Validation Test Suite<br />

bspVal [-h] [-all] [-r] [-c] serverID -b bspName<br />

[-s secondServerID] [-sb secondBspname]<br />

[-t1SerDev T1SerialDevice] [-t1SerBaud T1SerialBaud]<br />

[-t2SerDev T2SerialiDevice] [-t2SerBaud T2SerialBaud]<br />

[testName ... ] "<br />

This script provides the high-level user interface to the <strong>BSP</strong> Validation Test Suite (VTS).<br />

After initializing the environment required for the test, this script executes a Tcl script that<br />

runs the specified <strong>BSP</strong> test, testName, on the target. To run all possible tests, use the -all<br />

option.<br />

This VTS is designed to use the host-based windsh to run the tests. Internally, these tests<br />

use a combination of windsh commands and WTX Tcl API calls. This allows the same<br />

scripts to run under UNIX and as well as Windows. Also referenced is a specialized set of<br />

functions that the tests use to access host serial ports for target/console interaction. See<br />

the Tornado API <strong>Guide</strong>, for information on the WTX protocol functions and WTX Tcl API.<br />

NOTE: The target has to be connected with a target server by some type of WDB<br />

connection to run VTS. Please refer to Tornado manuals for different types of WDB<br />

connection if the target does not support ethernet connectivity, the default connection.<br />

NOTE: VTS can also run on targets booting VxWorks ROM images but the target has to<br />

be connected to a target server. If the target is booting a VxWorks ROM image, certain<br />

tests (like bootline) that require the VxWorks boot prompt will fail.<br />

Under UNIX, this script can be directly invoked from the command line. Under Windows,<br />

you must first invoke bash:<br />

1. Change directories to:<br />

windbasehost+<br />

Where windbase is the directory pointed to by the WIND_BASE environment<br />

variable.<br />

2. Edit bashrc.bspVal to configure the Tornado environment. (The instructions are in<br />

the file.)<br />

3. Invoke the bash shell:<br />

bash -rcfile bashrc.bspVal<br />

After the bash shell responds with a prompt (bash$), type in the bspVal command<br />

exactly as you would on a UNIX host (described below). For example:<br />

bash$ bspVal tgtSvr1 -b mv147 -s tgtSvr2 -sb mv147 -all<br />

366


J<br />

<strong>BSP</strong> Validation Test Suite Reference Entries<br />

OPTIONS<br />

If you specify a two-target test, make sure that the second target (reference board) is a<br />

valid <strong>BSP</strong>. In addition, the required command-line arguments for bspVal varies according<br />

to whether you select a single-target or a two-target test. For single-target tests, the<br />

required parameters are:<br />

serverID<br />

Specifies the target server name.<br />

-b bspName<br />

Specifies the name of the <strong>BSP</strong> being validated.<br />

testName<br />

Specifies the name of the test to be performed.<br />

For two-target tests, you must specify all the parameters shown above, as well as the<br />

following:<br />

-s secondServerID<br />

Specifies the reference board target server name.<br />

-sb secondBspName<br />

Specifies the reference board <strong>BSP</strong> name<br />

Use the other bspVal options as follows:<br />

-t1SerDev T1SerialDevice<br />

Specifies the host serial device of the main target.<br />

-t1SerBaud T1SerialBaud<br />

Specifies baud rate of the host serial device of the main target.<br />

-t2SerDev T2SerialDevice<br />

Specifies the host serial device of the reference board target.<br />

-t2SerBaud T2SerialBaud<br />

Specifies baud rate of the host serial device of the reference board target.<br />

-h<br />

Print the usage information about VTS.<br />

-r<br />

Cancel Reboot of target(s) before starting the test.<br />

-c<br />

Delete the previous log files.<br />

-all<br />

Run all tests.<br />

J<br />

CONFIGURATION FILES<br />

The VTS uses a configuration file called bspName.T1. Where bspName is the name of the<br />

<strong>BSP</strong> you want to validate. It must reside in the $WIND_BASE/host/resource/test/bspVal<br />

directory. If you want to perform tests involving two targets (network, rlogin, busTas),<br />

367


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

you must also specify an additional configuration file called secondBspName.T2. Where<br />

secondBspName is the name of the <strong>BSP</strong> running on the reference board used by the second<br />

target. All the configuration parameters for the first target should use a T1_ prefix and all<br />

parameters for the reference board should use a T2_ prefix. See the sample set of<br />

configuration files provided in the $WIND_BASE/host/resource/test/bspVal directory.<br />

Parameters referred to as optional need not be defined because the <strong>BSP</strong> tests have default<br />

values associated with these macros. All other parameters must be defined, even if they<br />

are set to "".<br />

If two target tests are run with the targets on a common VME backplane then the test<br />

assumes T1 target as the system controller by default. The user can set an optional<br />

configuration parameter T1_BUS_MASTER to FALSE for overriding this default<br />

configuration. This is particularly useful to run busTas test with T2 target as a slave on<br />

the common VME backplane. This has an impact on the rebooting sequence of targets<br />

since the system controller is required to reboot before any slaves on the VME backplane<br />

are rebooted.<br />

The VTS configuration parameters T1_SER_DEVICE, T1_SER_BAUD, T2_SER_DEVICE<br />

and T2_SER_BAUD can be optionally specified as command line parameters to the<br />

bspVal command. If any of these configuration parameters are specified as command line<br />

parameters to the bspVal command, the default values specified in the configuration files<br />

are overwritten.<br />

LOG FILES<br />

By default, the bspVal script creates a directory named vtsLogs in the <strong>BSP</strong> directory. In<br />

this directory a log file of the form bspValidationLog.PID, where PID is the ID of the<br />

process associated with the bspVal script execution, is created for each run of VTS. Make<br />

sure that the <strong>BSP</strong> directory has required permissions to allow creation of the vtsLogs<br />

directory.<br />

Alternatively, you can use the TEST_LOG_FILE environment variable to specify the full<br />

path name of a user-defined log file. Note that as long as the TEST_LOG_FILE<br />

environment variable remains defined, all subsequent runs of the bspVal will append<br />

their log output to this file. To return to the default log-file location, unset<br />

TEST_LOG_FILE.<br />

VTS ORGANIZATION<br />

The organization of the VTS over the Tornado tree is as shown below:<br />

$WIND_BASE/<br />

target/src/test/bspVal/ (pklib.c, the target test library)<br />

host/<br />

resource/test/bspVal/ (configuration files)<br />

src/test/<br />

tclserial/ (all, required source files)<br />

bspVal/<br />

src/tests/ (all tests)<br />

src/lib/ (all library routines)<br />

368


J<br />

<strong>BSP</strong> Validation Test Suite Reference Entries<br />

TEST LIST<br />

The target test library pkLib.c is compiled for each <strong>BSP</strong> by copying the file into the <strong>BSP</strong><br />

directory. The bspVal script checks for the existence of pkLib.o, copies the source file to<br />

the <strong>BSP</strong> directory if necessary, generates pkLib.o, and loads it onto the target. If you make<br />

any changes to the files in $WIND_BASE/target/src/test/bspVal, you must delete pkLib.o<br />

and unload the previous object module from the target so that the latest code is used.<br />

The tclserial directory contains the source files for the functions used to access the serial<br />

port on the host that is bound to Tcl. The serLib.tcl file contains a set of library functions<br />

that are an extension of tclserial.<br />

Every test has to be invoked using the bspVal command with required options. Tests<br />

involving single target and no reboot are run first, followed by tests involving two targets,<br />

followed by clock tests, followed by tests that reboot the target. Within these limitations,<br />

you can specify the order in which the tests are run.<br />

After parsing through the command line parameters, bspVal:<br />

1. Checks the validity of the target server(s) specified using a checkServerName library<br />

function.<br />

2. Sources the configuration parameters from the resource directory.<br />

3. Reboots the target(s) if necessary (an option you can specify).<br />

4. Loads pkLib.o on the target.<br />

5. Opens a pipeline to windsh to send commands to source the Tcl scripts and run the<br />

tests.<br />

You can abort the test scripts at any time using an interrupt signal (normally CTRL+c).<br />

However, the target board might continue to execute local tasks. This situation could<br />

leave the board in such a state that a power-cycle reset is necessary.<br />

This section lists all the tests currently included in the <strong>BSP</strong> validation test suite. Some tests<br />

run stand-alone. Some require a reference board. The tests listed below run stand-alone.<br />

auxClock<br />

Tests auxiliary clock’s functionality.<br />

baudConsole<br />

Tests console’s ability to communicate at all supported serial baud rates.<br />

bootline<br />

Verifies commands executable from vxWorks boot prompt.<br />

eprom<br />

Verifies ROM read operations.<br />

error1<br />

Verifies the target local bus access, off-board bus access and divide by zero exceptions<br />

initiated from the target shell.<br />

J<br />

369


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

error2<br />

Another set of error tests involving testing of reboot and catastrophic errors.<br />

model<br />

Tests return value of sysModel( ) routine.<br />

nvRam<br />

Verifies non-volatile RAM manipulation routines functionality.<br />

procNumGet<br />

Verifies return value of sysProcNumGet( ) routine.<br />

ram<br />

Verifies RAM read operations.<br />

scsi<br />

Verifies scsi read/write operations.<br />

serial<br />

Tests serial driver functionality.<br />

sysClock<br />

Tests system clock’s functionality.<br />

timestamp<br />

Verifies <strong>BSP</strong> timestamp timer functionality.<br />

The following tests require a reference board, a valid <strong>BSP</strong>.<br />

busTas<br />

Verifies sysBusTas( ) operation between 2 vxWorks target boards in a common VME<br />

backplane.<br />

network<br />

Verifies basic network functionality.<br />

rlogin<br />

Verifies ability to rlogin.<br />

TARGET CONFIGURATION USING <strong>BSP</strong> CONFIGURATION FILE<br />

Most bspVal tests should run under the default VxWorks 5.4 configuration, but some<br />

tests require that the target include utilities not typically included in the default<br />

configuration. The list below shows which tests require which macros. Add these macros<br />

to target’s config.h prior to building its VxWorks image. These requirements are as<br />

follows:<br />

auxClock<br />

busTas<br />

error2<br />

INCLUDE_AUXCLK<br />

INCLUDE_SHOW_ROUTINES<br />

INCLUDE_AUXCLK<br />

370


J<br />

<strong>BSP</strong> Validation Test Suite Reference Entries<br />

network<br />

INCLUDE_PING<br />

INCLUDE_NET_SHOW<br />

rlogin<br />

INCLUDE_SHOW_ROUTINES<br />

INCLUDE_RLOGIN<br />

INCLUDE_SHELL<br />

INCLUDE_NET_SYM_TBL<br />

INCLUDE_LOADER<br />

timestamp<br />

INCLUDE_TIMESTAMP<br />

TARGET CONFIGURATION USING PROJECT FACILITY<br />

If the Tornado project facility is used to configure the target the components required for<br />

each test differ slightly from target configuration using config.h file in the <strong>BSP</strong>. The list<br />

below shows the components that are required to be configured for each test.<br />

auxClock<br />

busTas<br />

error2<br />

network<br />

INCLUDE_AUX_CLK<br />

INCLUDE_SM_NET_SHOW<br />

INCLUDE_AUX_CLK<br />

INCLUDE_PING<br />

INCLUDE_NET_SHOW<br />

rlogin<br />

INCLUDE_RLOGIN<br />

INCLUDE_SHELL<br />

INCLUDE_NET_SYM_TBL<br />

J<br />

INCLUDE_LOADER<br />

INCLUDE_SM_NET_SHOW<br />

INCLUDE_SYM_TBL_SHOW<br />

INCLUDE_SHELL_BANNER<br />

timestamp<br />

INCLUDE_TIMESTAMP<br />

Additionally, the scsi test (not listed above) requires that the target be configured for SCSI<br />

and that a SCSI drive be connected.<br />

371


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

ERRORS<br />

The following is the list of errors the user might come across while running the VTS.<br />

FATAL ERROR<br />

This error message is displayed whenever any important functionality of the test<br />

fails.<br />

SKIP count<br />

Certain tests may be skipped if the test detects that the target is not configured for the<br />

test (for example, timestamp)<br />

FAIL count<br />

Count indicating tests failed.<br />

target server ambiguity<br />

This error occurs when target server with the same name is run on different<br />

machines.<br />

networking<br />

If there is highly active networking over the subnet then the user may get different<br />

kinds of WTX error messages due to network problems and the tests may fail.<br />

file error messages<br />

If the test detects that required files are missing, these messages may come up.<br />

abnormal termination (CTRL+c)<br />

The user is notified of the abnormal termination of test.<br />

auxClock<br />

NAME<br />

SYNOPSIS<br />

DESCRIPTION<br />

auxClock – auxiliary clock tests<br />

bspVal options auxClock<br />

This test verifies the functionality of the auxiliary clock for the <strong>BSP</strong>. Its run-time is seven<br />

to ten minutes. See bspVal.sh for an explanation of options.<br />

The tests within this script connect a routine to the auxiliary clock interrupt handler using<br />

the sysAuxClkConnect( ) routine. This disconnects any routine previously connected to<br />

the auxiliary clock ISR by the <strong>BSP</strong>.<br />

In order to run this test, the target has to be configured with auxiliary clock. To do this,<br />

add INCLUDE_AUXCLK to config.h file of the <strong>BSP</strong> or include the component<br />

INCLUDE_AUX_CLK, if using project facility.<br />

NOTE: This reference entry lists the most likely reasons for a test’s failure. However, it<br />

does not list all possible reasons.<br />

372


J<br />

<strong>BSP</strong> Validation Test Suite Reference Entries<br />

Tests 1 through 4 check the accuracy of the auxiliary clock at several frequencies: an<br />

optional extra rate, minimum, maximum, and the default rate, respectively. To measure<br />

the rate of the auxiliary clock, a simple callback routine is connected to the auxiliary clock<br />

ISR using sysAuxClkConnect( ). This callback routine increments a counter on every<br />

clock tick. The counter is then cleared, and the auxiliary clock is enabled at the rate being<br />

tested. The counter is read after 10 seconds and again after 130 seconds. The counter<br />

values are used to calculate the average interrupt rate of the auxiliary clock. Three<br />

measurements are taken to cancel the fixed portion of measurement latency error. The<br />

computed clock rate error is reported with one percent resolution. If the measured clock<br />

rate is more than 10 percent off the value being tested, the test for that rate fails.<br />

If any of these tests fail, check that the timer chip is properly initialized and is<br />

programmed with an appropriate scaling factor, if necessary. Interrupts should be<br />

enabled in sysAuxClkEnable( ) before the timer is started. Check that the<br />

sysAuxClkRoutine( ) is getting connected by sysAuxClkConnect( ), and that the<br />

sysAuxClkRoutine( ) is being called on every auxiliary clock interrupt.<br />

The fifth test verifies the operation of sysAuxClkDisable( ). This is done by periodically<br />

checking the same counter incremented by the first four tests. After sysAuxClkDisable( )<br />

is called, this counter should not continue to increment. If this test fails, check that the<br />

sysAuxClkDisable( ) routine is disabling timer interrupts, turning off the timer, and<br />

setting the running flag to FALSE.<br />

The sixth test performs parameter checking of the sysAuxClkRateSet( ) routine. This test<br />

checks that the proper return value is given for erroneous input parameters. If this test<br />

fails, check that sysAuxClkRateSet( ) performs error checking based on the<br />

AUX_CLK_RATE_MIN and AUX_CLK_RATE_MAX macros.<br />

The seventh test checks the return values of the sysAuxClkRateSet( ) and<br />

sysAuxClkRateGet( ) routines when first passed valid rates followed by erroneous rates.<br />

If this test fails, check that sysAuxClkRateSet( ) is setting the global rate variable, and that<br />

sysAuxClkRateGet( ) is reading the same variable.<br />

Barring serious hardware or software limitations (such as an identifiable VxWorks<br />

problem), the target board must pass all tests for the <strong>BSP</strong> to be validated.<br />

J<br />

CONFIGURATION PARAMETERS<br />

T1_EXTRA_AUXCLK<br />

Another rate to test (optional).<br />

EXAMPLE<br />

Output consists of:<br />

<strong>BSP</strong> VALIDATION TEST<br />

-------------------<br />

Target server : t53-160<br />

<strong>BSP</strong><br />

: mv147<br />

Log file<br />

: /tmp/bspValidationLog.5219<br />

Auxiliary Clock Test :<br />

373


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

auxClk at 4321 hertz (rate = 4325 error = 0%)<br />

auxClk at 3 hertz (rate = 3 error = 0%)<br />

auxClk at 5000 hertz (rate = 5002 error = 0%)<br />

auxClk at 60 hertz (rate = 60 error = 0%)<br />

sysAuxClkDisable() disables auxClk<br />

sysAuxClkRateSet() parameter checking<br />

sysAuxClkRateGet() return value<br />

Tests RUN 7<br />

Tests PASSED 7<br />

Tests FAILED 0<br />

Tests SKIPPED 0<br />

: PASS<br />

: PASS<br />

: PASS<br />

: PASS<br />

: PASS<br />

: PASS<br />

: PASS<br />

SEE ALSO<br />

bspVal.sh, cloclkLib.tcl, bspPkCommonProc.tcl, envLib.tcl, pkLib.c<br />

baudConsole<br />

NAME<br />

SYNOPSIS<br />

DESCRIPTION<br />

baudConsole – console baud rate test<br />

bspVal options baudConsole<br />

This test verifies the target console’s ability to communicate at all supported serial baud<br />

rates. It has a run-time of several minutes. See bspVal.sh for an explanation of options.<br />

NOTE: This reference entry lists the most likely reasons for a test’s failure. However, it<br />

does not list all possible reasons.<br />

This script consists of one test for each serial baud rate supported by both the host and the<br />

target. The host’s supported rates are given in the macro <strong>BSP</strong>TEST_HOST_RATES. The<br />

target’s supported rates are determined by the return value of an ioctl( ) call to the serial<br />

driver. A return of OK (0) indicates that the requested baud rate is supported. A return of<br />

ERROR (-1) indicates that the rate is unsupported. Baud rates supported by the target but<br />

not by the host cannot be tested. The actual communication verification amounts to<br />

simply being able to check the present baud rate from the shell, and calling ioctl( ) to set<br />

the console to the next baud rate. If any of these tests fail, check that the serial device is<br />

capable of supporting the given rate. The baud rate generator must be properly initialized<br />

and enabled, if present. Also check that the serial driver’s ioctl( ) routine performs error<br />

checking consistent with intended baud rate support.<br />

If the test execution ends prematurely, the target board might be left set to a baud rate<br />

other than T1_SER_BAUD. This situation could leave the board in such a state that a<br />

power cycle reset would be necessary to continue with other tests.<br />

374


J<br />

<strong>BSP</strong> Validation Test Suite Reference Entries<br />

Barring serious hardware or software limitations (such as an identifiable VxWorks<br />

problem), the target board must pass all tests for the <strong>BSP</strong> to be validated.<br />

CONFIGURATION PARAMETERS<br />

<strong>BSP</strong>TEST_HOST_RATES<br />

Host supported baud rates (required).<br />

T1_SER_DEVICE<br />

Serial device to be used on host (required).<br />

T1_SER_BAUD<br />

Default serial baud rate (required).<br />

EXAMPLE<br />

SEE ALSO<br />

Output consists of:<br />

<strong>BSP</strong> VALIDATION TEST<br />

-------------------<br />

Target server : t53-160<br />

<strong>BSP</strong><br />

: mv147<br />

Log file<br />

: /tmp/bspValidationLog.5219<br />

Baud Console Test :<br />

console at 150 baud<br />

: PASS<br />

console at 300 baud<br />

: PASS<br />

console at 600 baud<br />

: PASS<br />

console at 1200 baud<br />

: PASS<br />

console at 1800 baud<br />

: PASS<br />

console at 2400 baud<br />

: PASS<br />

console at 4800 baud<br />

: PASS<br />

console at 9600 baud<br />

: PASS<br />

console at 19200 baud<br />

: PASS<br />

console at 38400 baud<br />

: PASS<br />

Tests RUN 10<br />

Tests PASSED 10<br />

Tests FAILED 0<br />

Tests SKIPPED 0<br />

bspVal.sh, bspCommonProc.tcl, serLib.tcl, envLib.tcl, pkLib.c<br />

J<br />

375


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

bootline<br />

NAME<br />

SYNOPSIS<br />

DESCRIPTION<br />

bootline – functionality test for bootline<br />

bspVal options bootline<br />

This test verifies the commands executable from the VxWorks boot ROM prompt. It has a<br />

run-time of up to a few minutes. See bspVal.sh for an explanation of options.<br />

NOTE: This reference entry lists the most likely reasons for a test’s failure. However, it<br />

does not list all possible reasons.<br />

The first test reboots the target while sending characters to the serial console, causing<br />

possible problems with pending serial interrupts. If this test fails, check that CPU<br />

interrupts are properly disabled in romInit( ), a routine defined in romInit.s, and that all<br />

serial device interrupts are disabled and cleared in the sysLib routine, sysSerialHwInit( ).<br />

The second and third tests check the bus error exception handling functionality (local and<br />

off-board addresses, respectively). If these tests fail, check that the memory controller is<br />

initialized properly and that any memory watchdog timers are configured to reasonable<br />

values (if present).<br />

If there is not a local (on-board) memory address that can cause a bus error when<br />

accessed, the macro T1_BOOT_LOCAL_ERR_ADRS should be set to an invalid off-board<br />

address.<br />

The fourth test checks that the bootline commands and booting mechanisms all act as<br />

expected. This test can fail for a variety of reasons. Check that the memory controller is set<br />

up properly and that the network connection is attached.<br />

This test script does not work properly with a VxWorks standalone image in ROM. If the<br />

target can execute VxWorks only out of ROM, this test script should not be part of the <strong>BSP</strong><br />

validation procedure.<br />

Make sure that all the boot line parameters in the configuration file represent the actual<br />

target boot parameters. Failing to do so can leave target in a state where a power cycle<br />

reset is necessary with change in boot parameters.<br />

Barring serious hardware or software limitations (such as an identifiable VxWorks<br />

problem), the target board must pass all tests for the <strong>BSP</strong> to be validated.<br />

CONFIGURATION PARAMETERS<br />

T1_BOOT_LOCAL_ERR_ADRS<br />

Local memory address that causes bus error. (required)<br />

T1_BOOT_OFFBOARD_ERR_ADRS<br />

Off-board address that causes bus error. (required)<br />

376


J<br />

<strong>BSP</strong> Validation Test Suite Reference Entries<br />

T1_BOOT_LOCAL_BUS_ERR_MSG<br />

Local bus error message keyword. (required)<br />

T1_BOOT_OFFBOARD_BUS_ERR_MSG<br />

Off-board bus error message keyword. (required)<br />

T1_SER_DEVICE<br />

Serial device to be used on host. (required)<br />

T1_SER_BAUD<br />

Default serial baud rate. (required)<br />

T1_TMO_BOOT<br />

Timeout value for booting vxWorks. (required)<br />

EXAMPLE<br />

SEE ALSO<br />

Output consists of:<br />

<strong>BSP</strong> VALIDATION TEST<br />

-------------------<br />

Target server : t53-160<br />

<strong>BSP</strong><br />

: mv147<br />

Log file<br />

: /tmp/bspValidationLog.5219<br />

Bootline Test :<br />

Control X test<br />

: PASS<br />

Bus error test for local error address<br />

: PASS<br />

Bus error test for off-board error address<br />

: PASS<br />

boot commands test<br />

: PASS<br />

Tests RUN 4<br />

Tests PASSED 4<br />

Tests FAILED 0<br />

Tests SKIPPED 0<br />

bspVal.sh, bspPkCommonProc.tcl, serLib.tcl, envLib.tcl, pkLib.c<br />

J<br />

busTas<br />

NAME<br />

SYNOPSIS<br />

DESCRIPTION<br />

busTas – bus test-and-set test<br />

bspVal options busTas<br />

This module is the Tcl code for the test-and-set test. It verifies the sysBusTas( ) operation<br />

between two VxWorks target boards in a common VME backplane. This module is<br />

implemented in Tcl and WTX protocols functions. The entire test takes approximately 10<br />

minutes to run. See bspVal.sh for an explanation of options.<br />

377


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

If this test is run between two targets using shared memory, make sure the target is<br />

configured to include shared memory show routines. To do this, add<br />

INCLUDE_SHOW_ROUTINES to config.h of the <strong>BSP</strong>s or include the component<br />

INCLUDE_SM_NET_SHOW, if using project facility.<br />

NOTE: This reference entry lists the most likely reasons for a test’s failure. However, it<br />

does not list all possible reasons.<br />

The script does not reboot the targets. It assumes that the two targets and their respective<br />

target servers are up and running.<br />

By default the test assumes that T1 target is the system controller on the common VME<br />

backplane. An optional configuration parameter T1_BUS_MASTER can be set to FALSE<br />

to override this default configuration. In this case the T2 target is assumed to be the<br />

system controller. It is necessary to make sure that T1_BUS_MASTER has the correct<br />

value in case targets have to be rebooted before running any test.<br />

The test starts by obtaining two cache-coherent memory locations by calls to<br />

cacheDmaMalloc( ) on the master. These two memory locations are used for the<br />

semaphore and the access counter. The pkTestRamByte function checks that the<br />

addresses returned by cacheDmaMalloc( ) are readable and writable.<br />

Next, the local addresses are used to compute the bus addresses by calling the function<br />

sysLocalToBusAdrs( ) on the master. The bus addresses returned by<br />

sysLocalToBusAdrs( ) are passed to the slave, which uses the function<br />

sysBusToLocalAdrs( ) to get its own local addresses that it must apply to access the<br />

semaphore and counter locations on the master’s shared memory. The smAdrsFind<br />

procedure is called to verify that the counter and semaphore locations are seen by both the<br />

master and the slave. The memory locations are then initialized and the test is started by<br />

spawning the pkTasTest task on both master and slave. The functions<br />

wtxContextCreate( ) and wtxContextResume( ) are used here to spawn and start the<br />

tasks. The function pkTasTest( ) uses the semaphore location for mutual exclusion. When<br />

the master gets the semaphore, it increments the counter, if it is odd, and runs a busy-wait<br />

loop until it finally clears the semaphore. The slave runs the same way except that it<br />

increments the counter if it is even. This scheme ensures that the two tasks take turns<br />

grabbing the semaphore and incrementing the counter.<br />

The counter is monitored from the script, which takes two readings of the counter one<br />

second apart. If the second reading is larger than the first one, the short-term test is<br />

successful. After a pause of ten minutes, the two readings are retaken. If the counter is still<br />

increasing, the long-term test is successful.<br />

If this test fails, check that the master and slave are both accessing the same two master<br />

memory locations. If the master sysLocalToBusAdrs( ) or the slave sysBusToLocalAdrs( )<br />

routines are not functioning properly, the test will not be able to find appropriate slave<br />

addresses that access the master memory locations. The master memory locations must be<br />

cache-coherent and must be writable. The VME controller chips must be initialized to<br />

378


J<br />

<strong>BSP</strong> Validation Test Suite Reference Entries<br />

CONFIGURATION PARAMETERS<br />

proper values. For fast target boards, it might be necessary to increase the busy-wait<br />

delays given by the T1_TAS_DELAY (T2_TAS_DELAY) macro.<br />

The two tests in this script require two unique cache-coherent memory locations on master<br />

that can be accessed by both master and slave. By default, these locations are obtained by<br />

calls to cacheDmaMalloc( ) on the master. Alternatively, the macros T1_COUNT_ADRS<br />

and/or T1_SEM_ADRS can be changed from the default of “-1” to point to unique shared<br />

memory addresses on master. In this case, the user must make sure that these are free<br />

cache-coherent memory locations. The ability to explicitly declare these locations is<br />

provided for debugging purposes and for boards with hardware limitations. The final<br />

validation should leave the macros set to “-1”, and allocate the memory dynamically by<br />

calling cacheDmaMalloc( ).<br />

Barring serious hardware or software limitations (such as an identifiable VxWorks<br />

problem), the target board must pass all tests for the <strong>BSP</strong> to be validated. Of course, if the<br />

VME backplane is not supported by the target board, then this test is not a <strong>BSP</strong> validation<br />

requirement.<br />

T1_COUNT_ADRS<br />

Address of master’s shared counter (optional).<br />

T1_SEM_ADRS<br />

Address of master’s shared semaphore (optional).<br />

T1_TAS_DELAY<br />

Busy delay during TAS on master (optional).<br />

T2_TAS_DELAY<br />

Busy delay during TAS on slave (optional).<br />

EXAMPLE<br />

SEE ALSO<br />

Output consists of:<br />

<strong>BSP</strong> VALIDATION TEST<br />

-------------------<br />

Target server : t53-160<br />

<strong>BSP</strong><br />

: mv147<br />

Second target server : t214-2<br />

Second <strong>BSP</strong><br />

: mv147<br />

Log file<br />

: /tmp/bspValidationLog.6425<br />

busTas:<br />

short-term TAS test<br />

: PASS<br />

long-term TAS test<br />

: PASS<br />

Tests RUN 2<br />

Tests PASSED 2<br />

Tests FAILED 0<br />

Tests SKIPPED 0<br />

bspVal.sh, smLib.tcl, pkLib.c<br />

J<br />

379


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

eprom<br />

NAME<br />

SYNOPSIS<br />

DESCRIPTION<br />

eprom – EPROM tests<br />

bspVal options eprom<br />

This test verifies ROM read operations. The execution time of the tests run by this script<br />

depends on the CPU speed and the amount of ROM being tested. See bspVal.sh for an<br />

explanation of options.<br />

NOTE: This reference entry lists the most likely reasons for a test’s failure. However, it<br />

does not list all possible reasons.<br />

The three tests in this script call pkRead( ) to perform read operations of the ROM<br />

locations between ROM_BASE_ADRS and (ROM_BASE_ADRS + ROM_SIZE). The<br />

reads are done using 1-, 2-, or 4-byte accesses, depending on which test is being run. If any<br />

of these tests fail, but the memory hardware is known to be functioning properly, check<br />

that the memory controller is initialized to the correct values. Make sure that<br />

ROM_BASE_ADRS and ROM_SIZE are set to the correct values. If an MMU is present, it<br />

might need to be configured so that the entire ROM space is accessible.<br />

Barring serious hardware or software limitations (such as an identifiable VxWorks<br />

problem), the target board must pass all tests for the <strong>BSP</strong> to be validated.<br />

CONFIGURATION PARAMETERS<br />

None.<br />

EXAMPLE<br />

SEE ALSO<br />

Output consists of:<br />

<strong>BSP</strong> VALIDATION TEST<br />

-------------------<br />

Target server : t53-160<br />

<strong>BSP</strong><br />

: mv147<br />

Log file<br />

: /tmp/bspValidationLog.5219<br />

EPROM Test :<br />

1-byte read of EPROM<br />

: PASS<br />

2-byte read of EPROM<br />

: PASS<br />

4-byte read of EPROM<br />

: PASS<br />

Tests RUN 3<br />

Tests PASSED 3<br />

Tests FAILED 0<br />

Tests SKIPPED 0<br />

bspVal.sh, bspPkCommonProc.tcl, pkLib.c<br />

380


J<br />

<strong>BSP</strong> Validation Test Suite Reference Entries<br />

error1<br />

NAME<br />

SYNOPSIS<br />

DESCRIPTION<br />

error1 – error handling tests<br />

bspVal options error1<br />

This script tests the target’s local bus access. The off-board bus access and divide by zero<br />

exceptions are initiated from the target shell. See bspVal.sh for an explanation of options.<br />

NOTE: This reference entry lists the most likely reasons for a test’s failure. However, it<br />

does not list all possible reasons.<br />

The first and second tests check the bus error exception handling functionality (local and<br />

off-board addresses, respectively). If these tests fail, check that the memory controller is<br />

initialized properly and that any memory watchdog timers are configured to reasonable<br />

values (if present).<br />

If there is not a local (on-board) memory address that causes a bus error when accessed,<br />

set the T1_LOCAL_ERR_ADRS macro to an invalid off-board address.<br />

The third test causes a divide by zero exception and checks for the return messages from<br />

the console.<br />

CONFIGURATION PARAMETERS<br />

T1_LOCAL_ERR_ADRS<br />

Local error address that causes a bus error (required).<br />

T1_OFFBOARD_ERR_ADRS<br />

Off-board error address that causes a bus error (required).<br />

T1_DIV_ZERO_MSG<br />

Bus error message keyword (required).<br />

T1_LOCAL_BUS_ERR_MSG<br />

Local bus error message keyword (required).<br />

T1_OFFBOARD_BUS_ERR_MSG<br />

Off-board bus error message keyword (required).<br />

T1_SER_DEVICE<br />

Serial device on host (required).<br />

T1_SER_BAUD<br />

Default serial baud rate (required).<br />

T1_TMO_BOOT<br />

Timeout value for booting VxWorks (required).<br />

J<br />

381


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

EXAMPLE<br />

SEE ALSO<br />

Output consists of:<br />

<strong>BSP</strong> VALIDATION TEST<br />

-------------------<br />

Target server : t53-160<br />

<strong>BSP</strong><br />

: mv147<br />

Log file<br />

: /tmp/bspValidationLog.5219<br />

First Error Test :<br />

bus-error test for local address<br />

: PASS<br />

bus-error test for offboard address<br />

: PASS<br />

Divide by zero test<br />

: PASS<br />

Tests RUN 3<br />

Tests PASSED 3<br />

Tests FAILED 0<br />

Tests SKIPPED 0<br />

bspVal.sh, bspPkCommonProc.tcl, serLib.tcl, envLib.tcl, pkLib.c<br />

error2<br />

NAME<br />

SYNOPSIS<br />

DESCRIPTION<br />

error2 – error handling tests<br />

bspVal options error2<br />

This test verifies that the target board does not hang while handling errors initiated from<br />

the VxWorks shell. The entire test can take several minutes to run. See bspVal.sh for an<br />

explanation of options.<br />

In order to run this test, the target has to be configured with auxiliary clock. To do this,<br />

add INCLUDE_AUXCLK to config.h file of the <strong>BSP</strong> or include the component<br />

INCLUDE_AUX_CLK, if using project facility.<br />

NOTE: This reference entry lists the most likely reasons for a test’s failure. However, it<br />

does not list all possible reasons.<br />

The first test connects a routine that causes a bus error to the target’s system clock<br />

interrupt. This causes an exception at interrupt level, known as a “catastrophic” error.<br />

This exception should result in a reboot of the board. An appropriate error message<br />

should be displayed by the target. If this test fails, check that the sysToMonitor( ) routine<br />

in sysLib.c is functioning properly. Also check that the address of sysExcMsg is set<br />

correctly in sysLib.c.<br />

382


J<br />

<strong>BSP</strong> Validation Test Suite Reference Entries<br />

The second test reboots the target from the shell while characters are sent to the serial<br />

console and the auxiliary clock is enabled at the maximum rate. This checks that pending<br />

interrupts do not cause problems while rebooting. If this test fails, check that CPU<br />

interrupts are properly disabled in romInit( ), which is defined in romInit.s, and that all<br />

serial device interrupts are disabled and cleared in sysSerialHwInit( ). Also, check that<br />

the auxiliary clock routine sysAuxClkRoutine( ) is initialized to NULL and, if it is NULL,<br />

that the auxiliary clock is not called in sysAuxClkInt( ).<br />

Make sure that all the boot-line parameters in the configuration file represent the actual<br />

target boot parameters. Failing to do so could leave target in a state where a power cycle<br />

reset would be necessary with change in boot parameters.<br />

Barring serious hardware or software limitations (such as an identifiable VxWorks<br />

problem), the target board must pass all tests for the <strong>BSP</strong> to be validated.<br />

CONFIGURATION PARAMETERS<br />

T1_OFFBOARD_ERR_ADRS<br />

Off-board address that causes a bus error. (required)<br />

T1_CATASTROPHIC_ERR_MSG<br />

catastrophic error message keyword (required)<br />

T1_SER_DEVICE<br />

Serial device that is used on host. (required)<br />

T1_SER_BAUD<br />

Serial baud rate used. (required)<br />

T1_TMO_BOOT<br />

Timeout value for booting vxWorks. (required)<br />

EXAMPLE<br />

SEE ALSO<br />

Output consists of:<br />

<strong>BSP</strong> VALIDATION TEST<br />

-------------------<br />

Target server : t53-160<br />

<strong>BSP</strong><br />

: mv147<br />

Log file<br />

: /tmp/bspValidationLog.5219<br />

Second Error Test :<br />

catastrophic error test<br />

: PASS<br />

reboot with interrupts<br />

: PASS<br />

Tests RUN 2<br />

Tests PASSED 2<br />

Tests FAILED 0<br />

Tests SKIPPED 0<br />

bspVal.sh, bspPkCommonProc.tcl, serLib.tcl, envLib.tcl<br />

J<br />

383


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

model<br />

NAME<br />

SYNOPSIS<br />

DESCRIPTION<br />

model – sysModel( ) test<br />

bspVal options model<br />

This test verifies that the target board matches the target configuration file. To do this, it<br />

verifies the return value of the sysModel( ) routine. This value is extracted from the target<br />

information stored at target server. The entire test should not take more than a few<br />

seconds to run. See bspVal.sh for an explanation of options.<br />

This is the first test run if the -all option is specified for bspVal.<br />

NOTE: This reference entry lists the most likely reason for this test’s failure. However, it<br />

does not list all possible reasons.<br />

The first (and only) test compares the return value of sysModel( ) to the string specified<br />

by T1_MODEL. If this test fails, check that the sysModel( ) routine in sysLib.c returns the<br />

correct target model information.<br />

Barring serious hardware or software limitations (such as an identifiable VxWorks<br />

problem), the target board must pass all tests for the <strong>BSP</strong> to be validated.<br />

CONFIGURATION PARAMETERS<br />

T1_MODEL<br />

Expected result of sysModel( ). (required)<br />

EXAMPLE<br />

SEE ALSO<br />

Output consists of:<br />

<strong>BSP</strong> VALIDATION TEST<br />

-------------------<br />

Target server : t53-160<br />

<strong>BSP</strong><br />

: mv147<br />

Log file<br />

: /tmp/bspValidationLog.5219<br />

Model Test :<br />

sysModel() return value<br />

: PASS<br />

Tests RUN 1<br />

Tests PASSED 1<br />

Tests FAILED 0<br />

Tests SKIPPED 0<br />

bspVal.sh, bspPkCommonProc.tcl, envLib.tcl<br />

384


J<br />

<strong>BSP</strong> Validation Test Suite Reference Entries<br />

network<br />

NAME<br />

SYNOPSIS<br />

DESCRIPTION<br />

network – I/O tests for network<br />

bspVal options network<br />

This test verifies basic network functionality, independent of network media. This script is<br />

written in Tcl and uses some WTX protocol functions. It also uses tclSerial library<br />

functions for accessing the serial port(s). The entire test can take several minutes to run.<br />

See bspVal.sh for an explanation of options.<br />

NOTE: This reference entry lists the most likely reasons for a test’s failure. However, it<br />

does not list all possible reasons.<br />

This test requires two targets. The target being tested is the master. The second target, the<br />

slave, is used to run ping and udpEchoTest. The VxWorks image running on the slave<br />

must be built with the macro INCLUDE_PING defined. Both the targets require a<br />

VxWorks image built with INCLUDE_NET_SHOW defined. If using project facility, add<br />

components INCLUDE_PING and INCLUDE_NET_SHOW to respective VxWorks<br />

images.<br />

The first test uses ping to send approximately 50 ICMP packets (datagrams) to the ICMP<br />

server resident on the master. Each packet contains a request for a response from the<br />

server; the response should be received by the slave. The round-trip time, from sending to<br />

receiving, is displayed for each packet. As long as approximately 50 responses are logged<br />

by the slave, this test passes. If this test fails, check the network connection and make sure<br />

that the target IP address is correct.<br />

The first test requires that ping be present on the slave. A check is done to make sure that<br />

it is in the path. If ping is missing, the test aborts because the UDP test uses the ping<br />

statistics.<br />

The second test spawns the pkUdpEchoTest( ), a pkLib.c routine, on the slave to send a<br />

quantity of UDP packets to a UDP echo daemon running on the master, which is started<br />

by spawning pkUdpEchod( ), also a pkLib.c routine. Each UDP packet is sent by the slave<br />

to the master, echoed, read back in by the slave, then checked for correct size and content.<br />

Sixteen different size packets are sent and received. If pkUdpEchoTest( ) times out<br />

waiting for the echo, the packet is resent once. If the resent packet does not make it, the<br />

test is marked as a failure. The timeout value for individual UDP packets is derived from<br />

the statistics displayed in the ping test. This value depends on the network media being<br />

used. The actual packet round-trip time, however, should be considerably less than the<br />

calculated timeout value used. If this test fails, make sure that a reliable host is being used<br />

and that the network is not being overloaded by other packet traffic.<br />

The UDP/IP networking protocol is used in the second test. UDP/IP makes no guarantees<br />

with regard to packet delivery, thus the host and/or target might occasionally drop<br />

J<br />

385


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

packets. Although several dropped packets does not constitute a failed test, a large<br />

number of dropped packets (greater than one percent of the total sent) could indicate a<br />

problem with any of the following: network configuration, network device, device driver,<br />

networking software.<br />

Barring serious hardware or software limitations (such as an identifiable VxWorks<br />

problem), the target board must pass all tests for the <strong>BSP</strong> to be validated.<br />

A target that continually fails the second test might or might not be functioning properly.<br />

If it can be proven that the host is responsible for dropping the packets (for example, by<br />

running etherfind), then the target cannot be declared to have passed or failed this test.<br />

Hardware and network environment limitations need to be taken into consideration when<br />

evaluating the results of this test.<br />

CONFIGURATION PARAMETERS<br />

T1_BOOT_TN<br />

Master target name (required).<br />

T1_BOOT_E<br />

Master target IP address (required).<br />

T1_BOOT_B<br />

Master target backplane address (required).<br />

T2_BOOT_TN<br />

Slave target name (required).<br />

T2_BOOT_E<br />

Slave target IP address (required).<br />

T2_BOOT_B<br />

Slave target backplane address (required).<br />

T2_UDP_TRANS<br />

Number of packets used in UDP test.<br />

EXAMPLE<br />

Output consists of:<br />

<strong>BSP</strong> VALIDATION TEST<br />

-------------------<br />

Target server : t53-160<br />

<strong>BSP</strong><br />

: mv147<br />

Second target server : t214-2<br />

Second <strong>BSP</strong><br />

: mv147<br />

Log file<br />

: /tmp/bspValidationLog.6425<br />

network :<br />

ping target test<br />

: PASS<br />

UDP packet echo test<br />

: PASS<br />

Tests RUN 2<br />

386


J<br />

<strong>BSP</strong> Validation Test Suite Reference Entries<br />

Tests PASSED 2<br />

Tests FAILED 0<br />

Tests SKIPPED 0<br />

SEE ALSO<br />

bspVal.sh, networkLib.tcl, pkLib.c<br />

nvRam<br />

NAME<br />

SYNOPSIS<br />

DESCRIPTION<br />

nvRam – non-volatile RAM tests<br />

bspVal options nvRam<br />

This test verifies sysNvRamGet( ) and sysNvRamSet( ), the sysLib.c routines that<br />

manipulate non-volatile memory. See bspVal.sh for an explanation of options.<br />

NOTE: This reference entry lists the most likely reasons for a test’s failure. However, it<br />

does not list all possible reasons.<br />

On targets without non-volatile RAM, NV_RAM_SIZE should be set to NONE (-1) in the<br />

<strong>BSP</strong>. On such boards, only parameter checking of sysNvRamSet( ) and sysNvRamGet( )<br />

is performed. If only a portion of NVRAM is writable, or some amount is reserved for<br />

hardware operations, be sure to specify the writable size with the<br />

NV_RAM_SIZE_WRITEABLE macro in config.h.<br />

The execution time of the tests run by this script is dependent on the size of NVRAM<br />

being tested and the CPU speed. The entire test script should not take more than a few<br />

minutes to run to completion.<br />

This script merely calls pkTestNvRam( ) eight times to perform different non-volatile<br />

RAM functionality tests.<br />

The first test verifies the operation of a sysNvRamGet( ) read of NV_RAM_SIZE bytes. If<br />

this test fails, check that NV_RAM_SIZE is set to the size of NVRAM and that<br />

NV_BOOT_OFFSET is defined and used properly. Also check that sysNvRamGet( ) is<br />

copying the entire length requested from NVRAM into the passed-in buffer.<br />

The second test reads, writes, and reads NV_RAM_SIZE bytes of NVRAM to check<br />

sysNvRamSet( ) functionality. If this test fails, check the same problem areas as the first<br />

test. Also check that sysNvRamSet( ) is copying the entire length requested from the<br />

passed-in buffer into NVRAM.<br />

The third test checks the operation of a sysNvRamGet( ) read of zero bytes. If this test<br />

fails, check that reads of zero length are allowed by sysNvRamGet( ). The buffer should<br />

be properly terminated with EOS, and the routine should return OK.<br />

J<br />

387


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

The fourth test performs parameter checking of sysNvRamSet( ). This test checks that the<br />

proper return value is given for erroneous input parameters. If this test fails, check that<br />

error checking is provided by sysNvRamSet( ), which should return ERROR for a<br />

negative offset or a length parameter. Also, the value of the offset plus length parameters<br />

must be less than NV_RAM_SIZE.<br />

The fifth test performs parameter checking of sysNvRamGet( ). This test checks that the<br />

proper return value is given for erroneous input parameters. If this test fails, check that<br />

error checking is provided by sysNvRamGet( ), which should return ERROR for a<br />

negative offset or length parameter. Also, the value of the offset plus length parameters<br />

must be less than NV_RAM_SIZE.<br />

The sixth test writes several bytes of data (0xff), then reads back from the same NVRAM<br />

location. This operation checks that the same data is read back, and that the buffer is<br />

returned with a NULL termination. If this test fails, check that writing 0xff to NVRAM<br />

does not cause a problem and that the passed-in buffer is properly terminated with EOS.<br />

The seventh test writes several bytes of data (0x00), then reads back from the same<br />

NVRAM location. This operation checks that the same data is read back, and that the<br />

buffer is returned with a NULL termination. If this test fails, check that writing 0x00 to<br />

NVRAM does not cause a problem and that the passed-in buffer is properly terminated<br />

with EOS.<br />

The eighth test returns NV_RAM_SIZE bytes of NVRAM back to the values read in the<br />

first test. If this test fails, check that NV_RAM_SIZE bytes of NVRAM can be written and<br />

read with sysNvRamSet( ) and sysNvRamGet( ).<br />

Barring serious hardware or software limitations (such as an identifiable VxWorks<br />

problem), the target board must pass all tests for the <strong>BSP</strong> to be validated.<br />

CONFIGURATION PARAMETERS<br />

None.<br />

EXAMPLE<br />

Output consists of:<br />

<strong>BSP</strong> VALIDATION TEST<br />

-------------------<br />

Target server : t53-160<br />

<strong>BSP</strong><br />

: mv147<br />

Log file<br />

: /tmp/bspValidationLog.5219<br />

Non-Volatile RAM Test :<br />

sysNvRamGet() of boot line<br />

: PASS<br />

sysNvRamSet() and sysNvRamGet() of complemented bootline : PASS<br />

sysNvRamGet() with length zero<br />

: PASS<br />

sysNvRamSet() parameter checking<br />

: PASS<br />

sysNvRamGet() parameter checking<br />

: PASS<br />

sysNvRamSet() and sysNvRamGet() of 0xff data<br />

: PASS<br />

sysNvRamSet() and sysNvRamGet() of 0x00 data<br />

: PASS<br />

388


J<br />

<strong>BSP</strong> Validation Test Suite Reference Entries<br />

sysNvRamSet() and sysNvRamGet() of boot line<br />

Tests RUN 8<br />

Tests PASSED 8<br />

Tests FAILED 0<br />

Tests SKIPPED 0<br />

: PASS<br />

SEE ALSO<br />

bspVal.sh, bspPkCommonProc.tcl, pkLib.c<br />

procNumGet<br />

NAME<br />

SYNOPSIS<br />

DESCRIPTION<br />

procNumGet – sysProcNumGet( ) test<br />

bspVal options procNumGet<br />

This test verifies the return value of the sysProcNumGet( ) routine. The entire test should<br />

not take more than a few seconds to run. See bspVal.sh for an explanation of options.<br />

NOTE: This reference entry lists the most likely reasons for a test’s failure. However, it<br />

does not list all possible reasons.<br />

The first (and only) test compares the return value of sysProcNumGet( ) to the number<br />

specified by T1_BOOT_PROCNUM. If this test fails, check that sysProcNumGet( )<br />

returns the correct target processor number information.<br />

Barring serious hardware or software limitations (such as an identifiable VxWorks<br />

problem), the target board must pass all tests for the <strong>BSP</strong> to be validated.<br />

CONFIGURATION PARAMETERS<br />

T1_BOOT_PROCNUM<br />

Expected result of sysProcNumGet( ). (required)<br />

J<br />

EXAMPLE<br />

Output consists of:<br />

<strong>BSP</strong> VALIDATION TEST<br />

-------------------<br />

Target server : t53-160<br />

<strong>BSP</strong><br />

: mv147<br />

Log file<br />

: /tmp/bspValidationLog.5219<br />

sysProcNumGet Test :<br />

sysProcNumGet() return value<br />

: PASS<br />

Tests RUN 1<br />

Tests PASSED 1<br />

389


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Tests FAILED 0<br />

Tests SKIPPED 0<br />

SEE ALSO<br />

bspVal.sh, bspPkCommonProc.tcl, envLib.tcl<br />

ram<br />

NAME<br />

SYNOPSIS<br />

DESCRIPTION<br />

ram – RAM tests<br />

bspVal options ram<br />

This test verifies RAM read operations. See bspVal.sh for an explanation of options.<br />

NOTE: This reference entry lists the most likely reasons for a test’s failure. However, it<br />

does not list all possible reasons.<br />

The three tests in this script call pkRead( ) to perform read operations of the RAM<br />

locations between LOCAL_MEM_LOCAL_ADRS and sysMemTop( ). The reads are<br />

done using 1-, 2-, and 4-byte accesses, depending on which test is being run. If any of<br />

these tests fail, but the memory hardware is known to be functioning properly, check that<br />

the memory controller is initialized to the correct values. Make sure that<br />

LOCAL_MEM_LOCAL_ADRS and LOCAL_MEM_SIZE are set to the correct values. If<br />

an MMU is present, it might need to be configured so that the entire RAM space is<br />

accessible. Check that sysMemTop( ) returns the correct values.<br />

Barring serious hardware or software limitations (such as an identifiable VxWorks<br />

problem), the target board must pass all tests for the <strong>BSP</strong> to be validated.<br />

CONFIGURATION PARAMETERS<br />

None.<br />

EXAMPLE<br />

Output consists of:<br />

<strong>BSP</strong> VALIDATION TEST<br />

-------------------<br />

Target server : t53-160<br />

<strong>BSP</strong><br />

: mv147<br />

Log file<br />

: /tmp/bspValidationLog.5219<br />

RAM Test :<br />

1-byte read of RAM<br />

: PASS<br />

2-byte read of RAM<br />

: PASS<br />

4-byte read of RAM<br />

: PASS<br />

Tests RUN 3<br />

390


J<br />

<strong>BSP</strong> Validation Test Suite Reference Entries<br />

Tests PASSED 3<br />

Tests FAILED 0<br />

Tests SKIPPED 0<br />

SEE ALSO<br />

bspVal.sh, bspPkCommonProc.tcl, pkLib.c<br />

rlogin<br />

NAME<br />

SYNOPSIS<br />

DESCRIPTION<br />

rlogin – testing rlogin<br />

bspVal options rlogin<br />

This test verifies the ability to rlogin between two VxWorks target boards. The entire test<br />

should not take more than a few minutes to run. See bspVal.h for an explanation of<br />

options.<br />

NOTE: This reference entry lists the most likely reasons for a test’s failure. However, it<br />

does not list all possible reasons.<br />

In order to run this test, the configuration file used to create the VxWorks image must<br />

have defined the following macros:<br />

INCLUDE_SHELL<br />

INCLUDE_RLOGIN<br />

INCLUDE_SHOW_ROUTINES<br />

INCLUDE_NET_SYM_TBL<br />

INCLUDE_LOADER<br />

If the project facility is used to create VxWorks image, add the following components to<br />

VxWorks configuration:<br />

INCLUDE_RLOGIN<br />

INCLUDE_SHELL<br />

INCLUDE_NET_SYM_TBL<br />

INCLUDE_LOADER<br />

INCLUDE_SM_NET_SHOW<br />

INCLUDE_SYM_TBL_SHOW<br />

INCLUDE_SHELL_BANNER<br />

J<br />

391


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

All tests run by this script are concerned with verifying the rlogin process. After issuing<br />

an rlogin to the target on the reference board, the first test verifies that “IN USE” appears<br />

on the console of the target board. The second test confirms the rlogin session by calling<br />

version( ) from the VxWorks shell and attempting to match the address for the target<br />

board. The third test exercises the pty by spawning printLogo( ). The fourth test checks<br />

the operation of logout( ). This process is then repeated for rlogin from the target to the<br />

reference board and the rlogin session is confirmed with tests five through eight. If any of<br />

these tests fail, check that the IP address or backplane address for the target board<br />

(T1_BOOT_E or T1_BOOT_B) and reference board IP or backplane address<br />

(T2_BOOT_E or T2_BOOT_B) are set correctly. Check also that their respective target<br />

names (T1_BOOT_TN and T2_BOOT_TN) are set to their proper values.<br />

Barring serious hardware or software limitations (such as an identifiable VxWorks<br />

problem), the target board must pass all tests for the <strong>BSP</strong> to be validated.<br />

NOTE: This test does not require a backplane. It is enough if there is a network<br />

connection between the two targets. If the boards reside on separate sub-nets, the routing<br />

tables for each must be set up appropriately.<br />

CONFIGURATION PARAMETERS<br />

T1_BOOT_TN<br />

Target name (required).<br />

T1_BOOT_E<br />

Target IP address (required).<br />

T2_BOOT_B<br />

Target backplane address (required if T1_BOOT_E is not set).<br />

T2_BOOT_TN<br />

Reference target name (required).<br />

T2_BOOT_E<br />

Reference target IP address (required if T2_BOOT_B is not set).<br />

T2_BOOT_B<br />

Reference target backplane address (required if T2_BOOT_E is not set). Because the<br />

default is to use the Ethernet, if you set both T2_BOOT_E and T2_BOOT_B, the test<br />

uses the reference target IP address.<br />

EXAMPLE<br />

Output consists of:<br />

<strong>BSP</strong> VALIDATION TEST<br />

-------------------<br />

Target server : t53-160<br />

<strong>BSP</strong><br />

: mv147<br />

Second target server : t214-2<br />

Second <strong>BSP</strong><br />

: mv147<br />

392


J<br />

<strong>BSP</strong> Validation Test Suite Reference Entries<br />

Log file<br />

: /tmp/bspValidationLog.6425<br />

rlogin :<br />

IN USE message when rlogin to t53-160<br />

: PASS<br />

reach shell of t53-160<br />

: PASS<br />

rlogin pty usage on t53-160<br />

: PASS<br />

logout from t53-160<br />

: PASS<br />

IN USE message when rlogin to t214-2<br />

: PASS<br />

reach shell of t214-2<br />

: PASS<br />

rlogin pty usage on t214-2<br />

: PASS<br />

logout from t214-2<br />

: PASS<br />

Tests RUN 8<br />

Tests PASSED 8<br />

Tests FAILED 0<br />

Tests SKIPPED 0<br />

SEE ALSO<br />

bspVal.sh, loginLib.tcl<br />

scsi<br />

NAME<br />

scsi – SCSI test<br />

SYNOPSIS<br />

DESCRIPTION<br />

bspVal options scsi<br />

This test verifies SCSI read and write operations. See bspVal.sh for an explanation of<br />

options.<br />

In order to run this test, the target has to be configured for SCSI support. The target has to<br />

be configured for scsi show routines either by defining INCLUDE_SCSI_SHOW in<br />

config.h of the <strong>BSP</strong> or adding component INCLUDE_SCSI_SHOW, if using project<br />

facility.<br />

WARNING: All data on the SCSI device under test is overwritten.<br />

The execution time of the test run by this script depends on the size and speed of SCSI<br />

device being tested, the CPU speed, and the test buffer size (T1_SCSI_BUFSIZE). A small<br />

buffer slows the test. For particularly slow targets, slow devices, large SCSI devices,<br />

and/or small buffers, it might be necessary to increase the timeout value specified by the<br />

macro T1_TMO_SCSI. The entire script could take more than one hour to complete.<br />

For target boards with limited RAM, it might be necessary to reduce T1_SCSI_BUFSIZE<br />

from its default of 64 kilobytes. The buffer size must be a multiple of the block size of the<br />

device under test.<br />

J<br />

393


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

NOTE: This reference entry lists the most likely reasons for a test’s failure. However, it<br />

does not list all possible reasons.<br />

The first test verifies the return value of scsiShow( ) routine. If this test fails, it is assumed<br />

that SCSI is not configured properly and the next test (for read/write operations on the<br />

device) is skipped.<br />

The second test calls pkTestOneUnit( ) to test the SCSI device specified by T1_SCSI_ID<br />

and T1_SCSI_LUN. A pattern is written to every block of the device, then each block is<br />

read to verify the pattern. If this test fails, check that the SCSI ID and LUN are properly<br />

configured and that the device appears in the output from the scsiShow( ) command.<br />

Barring serious hardware or software limitations (such as an identifiable VxWorks<br />

problem), the target board must pass all tests for the <strong>BSP</strong> to be validated. Of course, if<br />

SCSI is not supported by the target board, then SCSI testing is not a <strong>BSP</strong> validation<br />

requirement.<br />

CONFIGURATION PARAMETERS<br />

T1_SER_DEVICE<br />

Serial device used for target.<br />

T1_SER_BAUD<br />

Serial baud rate used for target.<br />

T1_SCSI_ID<br />

SCSI ID of the device under test.<br />

T1_SCSI_LUN<br />

SCSI LUN of the device under test.<br />

T1_SCSI_BUFSIZE<br />

Buffer size, in bytes (optional).<br />

T1_SCSI_NBBUF<br />

Number of buffers to write (optional).<br />

T1_SCSI_NBLOOP<br />

Number of loops to perform (optional).<br />

T1_TMO_SCSI<br />

Timeout value, in seconds (optional).<br />

EXAMPLE<br />

Output consists of:<br />

<strong>BSP</strong> VALIDATION TEST<br />

-------------------<br />

Target server : t53-160<br />

<strong>BSP</strong><br />

: mv147<br />

Log file<br />

: /tmp/bspValidationLog.5219<br />

SCSI Test :<br />

394


J<br />

<strong>BSP</strong> Validation Test Suite Reference Entries<br />

scsiShow() test<br />

SCSI write/read/verify device<br />

Tests RUN 2<br />

Tests PASSED 2<br />

Tests FAILED 0<br />

Tests SKIPPED 0<br />

: PASS<br />

: PASS<br />

SEE ALSO<br />

bspVal.sh, serLib.tcl, pkLib.c, bspPkCommonProc.tcl, envLib.tcl<br />

serial<br />

NAME<br />

SYNOPSIS<br />

DESCRIPTION<br />

serial – serial I/O tests<br />

bspVal options serial<br />

This test verifies serial driver functionality under adverse conditions. See bspVal.sh for an<br />

explanation of options. The entire test can take several minutes to run.<br />

NOTE: This reference entry lists the most likely reasons for a test’s failure. However, it<br />

does not list all possible reasons.<br />

The first test stresses the serial console port by having a target function repeatedly send<br />

output to the console, tty, while input is coming in from the host. The test checks that the<br />

target does not hang and that all the input sent was received intact by the target. This test<br />

is run at the highest baud rate supported by both host and target. If this test fails, check<br />

the serial connection. The serial driver’s receive and transmit facilities must be stable and<br />

functioning properly. Generally, the driver should handle the receive interrupts before<br />

servicing transmit interrupts if both events are handled by the same ISR.<br />

The second test also stresses the serial console port. The pkConsoleEcho( ) routine puts<br />

the console port in echo mode, where all characters sent by the host are immediately<br />

echoed. The test makes sure that every character sent to the console is received back by<br />

the host in the correct order and quantity. This test is run at the highest baud rate<br />

supported by both host and target. If this test fails, check for any possible interrupt race<br />

conditions in the serial driver.<br />

The next two tests require that all free serial ports (other than the ttys used for the console<br />

and SLIP) be connected to run in loopback mode. This can usually be accomplished by<br />

running a jumper wire from the transmit/output line to the receive/input line. It might<br />

also be necessary to run a jumper from the RTS to the CTS line for ports with hardware<br />

handshaking.<br />

J<br />

395


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

The third test spawns a single pkLoopbackTest( ) task for each serial port connected in<br />

loopback mode. Each port sees a pattern of sequential characters sent and received at the<br />

maximum baud rate. All characters must be received in the order sent. If this test fails,<br />

check that all serial ports under test are set up correctly for loopback mode. Make sure<br />

that the serial driver is handling receive and transmit interrupts properly. Make sure that<br />

all serial channels under test have been configured and initialized to the correct values.<br />

The fourth test spawns several pkLoopbackTest( ) tasks for each serial port connected in<br />

loopback mode. Each task repeatedly sends a particular character to one of the ports.<br />

There are several tasks for each serial port under test. Each port should receive all the<br />

characters that were sent. If this test fails, check the same problem areas suggested for the<br />

third test.<br />

The third and fourth tests spawn one or more pkLoopbackTest( ) tasks for each serial<br />

device connected in loopback mode. These tasks run concurrently, sending and receiving<br />

characters at the highest baud rate supported by both host and target. It is possible that<br />

target boards with slower CPUs and many serial devices might not possess the raw<br />

processing power required to keep up with the tests. If hardware limitations are causing<br />

the loopback tests to fail, the tests can be configured to lighten the processor load. The<br />

serial.tcl tests run at the highest baud specified in the bspVal macro,<br />

<strong>BSP</strong>TEST_HOST_RATES (provided that the rate is supported by both the host and<br />

target).<br />

Modifying <strong>BSP</strong>TEST_HOST_RATES to exclude the higher common baud rates will cause<br />

the tests to run at a lower rate, thus avoiding possible hardware- related problems.<br />

Additionally, the pkLib.c constant PK_LOOP_TASK_NUM can be changed from the<br />

default value of 4 to decrease the number of concurrent tasks running in the fourth test. In<br />

this case, the object code file pkLib.o must be rebuilt from the changed pkLib.c source<br />

file.<br />

Target boards with several serial devices and a small amount of local RAM (1Mbyte or<br />

under) might run out of memory while executing the tests. In this case, either configure<br />

the target to use an external memory card or decrease the number of tasks running as<br />

described above.<br />

If the test script execution ends prematurely, the target board might be left set to a baud<br />

rate other than T1_TIP_BAUD. This situation could leave the board in such a state that a<br />

power cycle reset would be necessary to continue with other tests.<br />

Barring serious hardware or software limitations (such as an identifiable VxWorks<br />

problem), the target board must pass all tests for the <strong>BSP</strong> to be validated.<br />

CONFIGURATION PARAMETERS<br />

<strong>BSP</strong>TEST_HOST_RATES<br />

Baud rates supported on host. (required)<br />

T1_SER_DEVICE<br />

Serial device to be used on host. (required)<br />

396


J<br />

<strong>BSP</strong> Validation Test Suite Reference Entries<br />

T1_SER_BAUD<br />

Default serial baud rate to be used. (required)<br />

EXAMPLE<br />

SEE ALSO<br />

Output consists of:<br />

<strong>BSP</strong> VALIDATION TEST<br />

-------------------<br />

Target server : t53-160<br />

<strong>BSP</strong><br />

: mv147<br />

Log file<br />

: /tmp/bspValidationLog.5219<br />

Serial Test :<br />

console I/O test<br />

: PASS<br />

console echo test<br />

: PASS<br />

sequential loopback test<br />

: PASS<br />

multiple loopback test<br />

: PASS<br />

Tests RUN 4<br />

Tests PASSED 4<br />

Tests FAILED 0<br />

Tests SKIPPED 0<br />

bspVal.sh, bspPkCommonProc.tcl, envLib.tcl, serLib.tcl, pkLib.c<br />

sysClock<br />

NAME<br />

sysClock – system clock tests<br />

SYNOPSIS<br />

DESCRIPTION<br />

bspVal options sysClock<br />

This test verifies the functionality of the <strong>BSP</strong>’s system clock. The entire test takes<br />

approximately 7-10 minutes to run. See bspVal.sh for an explanation of options.<br />

The tests within this script connect a routine to the system clock interrupt handler using<br />

the sysClkConnect( ) routine, which uses the sysClkRoutine function pointer variable.<br />

This call to sysClkConnect( ) for sysClkRoutine disconnects any routine the <strong>BSP</strong> might<br />

have previously connected as the system clock ISR.<br />

NOTE: This reference entry lists the most likely reasons for a test’s failure. However, it<br />

does not list all possible reasons.<br />

Tests one through four check the accuracy of the system clock at several frequencies: an<br />

optional extra rate, minimum, maximum, and the default rate, respectively. To measure<br />

the rate of the system clock, a simple callback routine is connected to the system clock ISR<br />

using sysClkConnect( ). This callback routine increments a counter on every clock tick.<br />

J<br />

397


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

The counter is then cleared, and the system clock is enabled at the rate being tested. The<br />

counter is read after 10 seconds and again after 130 seconds. The counter values are used<br />

to calculate the average interrupt rate of the system clock. Three measurements are taken<br />

to cancel the fixed portion of measurement latency error. The computed clock rate error is<br />

reported with one percent resolution. If the measured clock rate is more than 10 percent<br />

off the value being tested, the test for that rate fails.<br />

If any of these tests fail, check that the timer chip is properly initialized and, if<br />

appropriate, that it is programmed with an appropriate scaling factor. Interrupts should<br />

be enabled in sysClkEnable( ) before the timer is started. Check that the sysClkRoutine is<br />

getting connected by sysClkConnect( ), and that sysClkRoutine( ) is called on every<br />

system clock interrupt.<br />

The fifth test verifies the operation of sysClkDisable( ). This is done by periodically<br />

checking the same counter incremented by the first four tests. After sysClkDisable( ) is<br />

called, this counter should not continue to increment. If this test fails, check that the<br />

sysClkDisable( ) routine is disabling timer interrupts, turning off the timer, and setting<br />

the running flag to FALSE.<br />

The sixth test performs parameter checking of the sysClkRateSet( ) routine. This test<br />

checks that the proper return value is given for erroneous input parameters. If this test<br />

fails, check that sysClkRateSet( ) performs error checking based on the<br />

SYS_CLK_RATE_MIN and SYS_CLK_RATE_MAX macros.<br />

The seventh test checks the return values of the sysClkRateSet( ) and sysClkRateGet( )<br />

routines when first passed valid rates followed by erroneous rates. If this test fails, check<br />

that sysClkRateSet( ) is setting the global rate variable and that sysClkRateGet( ) is<br />

reading the same variable.<br />

Barring serious hardware or software limitations (such as an identifiable VxWorks<br />

problem), the target board must pass all tests for the <strong>BSP</strong> to be validated.<br />

CONFIGURATION PARAMETERS<br />

T1_EXTRA_SYSCLK<br />

Another rate to test (optional).<br />

EXAMPLE<br />

Output consists of:<br />

<strong>BSP</strong> VALIDATION TEST<br />

-------------------<br />

Target server : t53-160<br />

<strong>BSP</strong><br />

: mv147<br />

Log file<br />

: /tmp/bspValidationLog.5219<br />

System Clock Test :<br />

sysClk at 4321 hertz (rate = 4325 error = 0%)<br />

: PASS<br />

sysClk at 3 hertz (rate = 3 error = 0%)<br />

: PASS<br />

sysClk at 5000 hertz (rate = 5002 error = 0%)<br />

: PASS<br />

sysClk at 60 hertz (rate = 60 error = 0%)<br />

: PASS<br />

398


J<br />

<strong>BSP</strong> Validation Test Suite Reference Entries<br />

sysClkDisable() disables sysClk<br />

sysClkRateSet() parameter checking<br />

sysClkRateGet() return value<br />

Tests RUN 7<br />

Tests PASSED 7<br />

Tests FAILED 0<br />

Tests SKIPPED 0<br />

: PASS<br />

: PASS<br />

: PASS<br />

SEE ALSO<br />

bspVal.sh, bspPkCommonProc.tcl, envLib.tcl, clockLib.tcl, pkLib.c<br />

timestamp<br />

NAME<br />

SYNOPSIS<br />

DESCRIPTION<br />

timestamp – tests timestamp timer<br />

bspVal options timestamp<br />

This test verifies the <strong>BSP</strong> timestamp timer functionality. This entire test takes<br />

approximately 5 minutes (default timeout value) to run. See bspVal.sh for an explanation<br />

of options.<br />

In order to run this test, the target has to be configured with timestamp timer. To do this,<br />

add INCLUDE_TIMESTAMP to config.h file of the <strong>BSP</strong> or include the component<br />

INCLUDE_TIMESTAMP, if using project facility.<br />

NOTE: This reference entry lists the most likely reasons for a test’s failure. However, it<br />

does not list all possible reasons.<br />

The script starts by making sure that the timestamp timer is not running. If found<br />

running, the function sysTimestampDisable( ) is called and a verification that the timer<br />

stopped is made.<br />

The first test verifies that sysTimestampEnable( ) works. It calls the function and does a<br />

short term test to check that the timer is incrementing.<br />

The second and third tests verify the long-term timestamp operation using<br />

sysTimestamp( ) or sysTimestampLock( ). At regular intervals, the tests take a number of<br />

readings of the timestamp timer. The value of T1_TMO_TIMESTAMP specifies the<br />

period of time over which the tests take their readings. The T1_TMO_SLICES value<br />

specifies the number of readings. The number of timestamp ticks for each interval is<br />

measured against the calculated number. The test fails if the timer error exceeds 1%.<br />

The fourth test verifies that sysTimestampDisable( ) works. It calls the function and<br />

verifies that the timer stopped incrementing.<br />

J<br />

399


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

The fifth test verifies that the timer can be re-enabled after it was disabled. It calls<br />

sysTimestampEnable( ) and verifies that the timer starts incrementing.<br />

Barring serious hardware or software limitations (such as an identifiable VxWorks<br />

problem), the target board must pass all tests for the <strong>BSP</strong> to be validated.<br />

CONFIGURATION PARAMETERS<br />

T1_BOOT_TN<br />

Target name (required).<br />

T1_TMO_TIMESTAMP<br />

Long-term test duration (optional).<br />

T1_TMO_SLICES<br />

Long-term test time intervals (optional).<br />

EXAMPLE<br />

SEE ALSO<br />

Output consists of:<br />

<strong>BSP</strong> VALIDATION TEST<br />

-------------------<br />

Target server : t53-160<br />

<strong>BSP</strong><br />

: mv147<br />

Second target server : t214-2<br />

Second <strong>BSP</strong><br />

: mv147<br />

Log file<br />

: /tmp/bspValidationLog.6425<br />

enable the timestamp timer<br />

: PASS<br />

sysTimestamp() long-term test<br />

: PASS<br />

sysTimestampLock() long-term test<br />

: PASS<br />

disable the timestamp timer<br />

: PASS<br />

re-enable after disable<br />

: PASS<br />

Tests RUN 5<br />

Tests PASSED 5<br />

Tests FAILED 0<br />

Tests SKIPPED 0<br />

bspVal.sh, timestampLib.tcl, pkLib.c<br />

400


K<br />

<strong>BSP</strong> Validation Checklists<br />

This appendix contains two checklists: the <strong>BSP</strong> Validation Checklist and the VTS<br />

(Validation Test Suite) Checklist. Wind River uses these checklists when testing<br />

and validating a new <strong>BSP</strong>.<br />

Use the <strong>BSP</strong> Validation Checklist as a guide through the verification of all aspects<br />

of the <strong>BSP</strong> product: installation, testing, and package verification. Use the VTS<br />

Checklist to document the <strong>BSP</strong> VTS test results. The VTS Checklist is just one small<br />

element in the overall <strong>BSP</strong> Validation Checklist.<br />

For working copies of these checklists, print the PDF files:<br />

host/src/test/bspVal/validation.cklist.pdf<br />

host/src/test/bspVal/bspVts.cklist.pdf<br />

401


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

<strong>BSP</strong> Validation Checklist<br />

Architecture Product ID:<br />

Architecture Patches:<br />

Optional Product 1:<br />

Optional Product 2:<br />

Optional Product 3:<br />

Functional Test<br />

<strong>BSP</strong> Product ID:<br />

Item Date Status<br />

1. Install all relevant patches to a fresh copy of the architecture<br />

product.<br />

2. Install the <strong>BSP</strong> product.<br />

3. Make a copy of the installed <strong>BSP</strong> directory. Make a copy of the<br />

installed project directory for this <strong>BSP</strong>. The project for each <strong>BSP</strong><br />

is named <strong>BSP</strong>_toolchain and can be found in the target/proj<br />

directory.<br />

4. Test all installed images (a simple test of basic functionality).<br />

This includes all images installed in the project directory.<br />

5. Rebuild the <strong>BSP</strong> components. Make sure all images build<br />

correctly. Compare the new and old images for any size<br />

differences.<br />

vxWorks ................................................................................... ................................. .........................<br />

vxWorks.st ............................................................................... ................................. .........................<br />

vxWorks_rom .......................................................................... ................................. .........................<br />

vxWorks.st_rom ....................................................................... ................................. .........................<br />

vxWorks.res_rom ..................................................................... ................................. .........................<br />

vxWorks.res_rom_res_low ...................................................... ................................. .........................<br />

bootrom ................................................................................... ................................. .........................<br />

bootrom_uncmp ...................................................................... ................................. .........................<br />

bootrom_res ............................................................................. ................................. .........................<br />

6. Rebuild all the project facility images for this <strong>BSP</strong>. Make sure all<br />

images build correctly for both GNU and Diab toolchains.<br />

Compare the new and old images for any size differences.<br />

GNU<br />

vxWorks ................................................................................... ................................. .........................<br />

vxWorks_rom .......................................................................... ................................. .........................<br />

vxWorks_romCopy .................................................................. ................................. .........................<br />

402


K<br />

<strong>BSP</strong> Validation Checklists<br />

<strong>BSP</strong> Validation Checklist<br />

vxWorks_romResident ............................................................ ................................ .........................<br />

Diab<br />

vxWorks .................................................................................... ................................ .........................<br />

vxWorks_romCopy .................................................................. ................................ .........................<br />

vxWorks_romCopy .................................................................. ................................ .........................<br />

vxWorks_romResident ............................................................ ................................ .........................<br />

Build Test<br />

Item Date Status<br />

1. Build and test any standard images not previously built and<br />

tested. Verify that any images that fail to build or run are noted<br />

in target.nr under the SPECIAL CONSIDERATIONS heading.<br />

vxWorks ................................................................................... ................................ .........................<br />

vxWorks.st ............................................................................... ................................ .........................<br />

vxWorks_rom ........................................................................... ................................ .........................<br />

vxWorks.st_rom ....................................................................... ................................ .........................<br />

vxWorks.res_rom ..................................................................... ................................ .........................<br />

vxWorks.res_rom_nosym ........................................................ ................................ .........................<br />

vxWorks.res_rom_res_low ...................................................... ................................ .........................<br />

vxWorks.res_rom_nosym_res_low .......................................... ................................ .........................<br />

bootrom .................................................................................... ................................ .........................<br />

bootrom_uncmp ...................................................................... ................................ .........................<br />

bootrom_res ............................................................................. ................................ .........................<br />

bootrom_res_high .................................................................... ................................ .........................<br />

2. Build and test the following images for the GNU toolchain<br />

from the project facility. Verify that any images that fail to build<br />

or run are noted in target.nr under the SPECIAL<br />

CONSIDERATIONS heading.<br />

vxWorks ................................................................................... ................................ .........................<br />

vxWorks_rom ........................................................................... ................................ .........................<br />

vxWorks_romCopy .................................................................. ................................ .........................<br />

vxWorks_romResident ............................................................ ................................ .........................<br />

K<br />

403


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

3. Build and test the following images for the Diab toolchain from<br />

the project facility. Verify that any images that fail to build or<br />

run are noted in target.nr under the SPECIAL<br />

CONSIDERATIONS heading.<br />

vxWorks ................................................................................... ................................. .........................<br />

vxWorks_rom .......................................................................... ................................. .........................<br />

vxWorks_romCopy .................................................................. ................................. .........................<br />

vxWorks_romResident ............................................................ ................................. .........................<br />

4. Check for the inline assembly macro __asm__ in all C files of<br />

the <strong>BSP</strong>. All files that use this macro should use the new macro,<br />

_WRS_ASM. Please see the <strong>BSP</strong> Developer’s <strong>Guide</strong>: Portable C<br />

Coding Standard for more details.<br />

Product Packaging Test<br />

<strong>BSP</strong> Validation Checklist<br />

1. Generate a list of all files installed by the <strong>BSP</strong> product.<br />

Item Date Status<br />

2. Verify that the <strong>BSP</strong> does not deliver any WRS generic driver<br />

header files, source files, or object modules.<br />

3. Verify that the dependency file depend.bspname is not part of<br />

the list of files installed by the <strong>BSP</strong> product.<br />

4. (Optional) Verify that the <strong>BSP</strong> does not deliver any<br />

unnecessary deliverables such as object files (all .o files), ctdt.c,<br />

or symTbl.c in either the <strong>BSP</strong> or project directories.<br />

5. Check for the correct version of the <strong>BSP</strong>. The valid <strong>BSP</strong> version<br />

numbers are<br />

VxWorks 5.2 <strong>BSP</strong> or earlier version - 1.0/x<br />

Tornado 1.0 and 1.0.1 <strong>BSP</strong> version - 1.1/x<br />

Tornado 2.X <strong>BSP</strong> version - 1.2/x<br />

where x is the <strong>BSP</strong> revision number.<br />

Verify that the README file in the <strong>BSP</strong> directory has the<br />

correct version number. Verify that the macros <strong>BSP</strong>_VERSION<br />

and <strong>BSP</strong>_REV in config.h also reflect the same <strong>BSP</strong> version.<br />

6. Verify that there are no third-party files in target/h,<br />

target/src/drv/, target/config/all, or target/src/config.<br />

404


K<br />

<strong>BSP</strong> Validation Checklists<br />

7. Verify that any special drivers unique to the <strong>BSP</strong> are part of<br />

MACH_EXTRA or sysLib.c (either literally or pulled in by a<br />

#include statement).<br />

8. Verify that the <strong>BSP</strong> contains no copyrighted files or any files<br />

derived from restricted Wind River sources. Wind River does<br />

not release the source code for Ethernet or SCSI drivers to<br />

users.<br />

Configuration Test<br />

Item Date Status<br />

1. Test each boot method supported by the default <strong>BSP</strong><br />

configuration. Install and boot the boot ROM and check that it<br />

can download an image using each boot method.<br />

Also for each boot method, attempt to download an invalid<br />

VxWorks image (a nonexistent image or one in an improper<br />

format) and then verify that the boot ROM can still download<br />

and execute a valid image after a failed attempt. Attach a<br />

separate sheet with details on the boot methods tested and the<br />

results.<br />

2. Based on the target.nr information, build and boot different<br />

configurations of the <strong>BSP</strong> that include support for features not<br />

included in the delivered <strong>BSP</strong> configuration. Attach a separate<br />

sheet with details on the different configurations tested, what<br />

features were covered, what features were not covered, and the<br />

results of testing. Test each boot method as in step 1.<br />

<strong>BSP</strong> Validation Test Suite<br />

<strong>BSP</strong> Validation Checklist<br />

Item Date Status<br />

1. Verify that all applicable tests are successful.<br />

Attach a printout of the VTS checklist.<br />

2. If a test does not run successfully for this <strong>BSP</strong>, verify that the<br />

fact is noted in target.nr.<br />

K<br />

405


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Optional Product Test<br />

Item Date Status<br />

1. If the <strong>BSP</strong> has support for USB, test USB support for this <strong>BSP</strong>.<br />

To do this, follow the steps below, using the project facility to<br />

configure USB. For further information on USB, please see the<br />

USB documentation.<br />

Project Facility Configuration:<br />

- Select the USB host stack component.<br />

- Select at least one host controller, OHCI or UHCI depending on<br />

the <strong>BSP</strong> support.<br />

- Include either mouse or keyboard peripheral components if the<br />

hardware is available.<br />

NOTE: Do not include any initialization components.<br />

If you intend to use the target shell for testing, make sure a symbol<br />

table is available on the target.<br />

USB Testing:<br />

- Boot the target with USB support.<br />

- From either the target or the host shell, invoke the USB tool by<br />

calling the usbTool( ) command. This produces the usb tool<br />

prompt. Run the following commands from the usb tool prompt:<br />

usb> usbi (initialize stack)<br />

usb> attach ohci (or uhci depending on your configuration)<br />

This ensures that USB is configured properly on the target.<br />

If a keyboard or mouse USB peripheral is available, test them as<br />

follows:<br />

Mouse Testing:<br />

- Attach the mouse device at one of the ports.<br />

- Ensure that the device has been detected by enumerating the<br />

bus. Call the usbenum command from the usb tool.<br />

- Run the mouse test by calling the mousete command from the<br />

usb tool. The coordinates of the mouse should be displayed as<br />

the mouse is moved.<br />

Keyboard Testing:<br />

<strong>BSP</strong> Validation Checklist<br />

- Attach the keyboard device and initialize the keyboard by<br />

invoking kbdi from the usb tool.<br />

- Run the keyboard test by calling the kbdpo command from the<br />

usb tool. Keys pressed on the keyboard are displayed at the<br />

shell.<br />

406


K<br />

<strong>BSP</strong> Validation Checklists<br />

2. If the <strong>BSP</strong> has support for TrueFFS, test TrueFFS support for<br />

this <strong>BSP</strong>. To do this, follow the steps below. For further<br />

information on TrueFFS, please see the TrueFFS<br />

documentation. You can use either a command-line build or<br />

the project facility to test TrueFFS.<br />

Command-Line Configuration:<br />

- Define INCLUDE_TFFS in config.h.<br />

- Define appropriate media and translation layers by defining the<br />

MTD and TL macros in sysTffs.c.<br />

- Define INCLUDE_SHOW_ROUTINES if you need TrueFFS<br />

show routines.<br />

Project Facility Configuration:<br />

- Configure the INCLUDE_TFFS component.<br />

- Select appropriate media and translation layers with the MTD<br />

and TL components.<br />

- Select the TFFS_SHOW component if you need TrueFFS show<br />

routines.<br />

Testing TrueFFS:<br />

<strong>BSP</strong> Validation Checklist<br />

- Boot the target with the TrueFFS configuration.<br />

- Run sysTffsFormat( ) (if one exists in sysTffs.c) or<br />

tffsDevFormat( ) from either the target shell or the host shell.<br />

- Run usrTffsConfig( ).<br />

- Copy files from the host to the Flash device you have created, and<br />

check that the copy operation was successful.<br />

3. Configure the WDB agent with serial communication and a<br />

target server to use the serial backend. Set up the target<br />

appropriately with correct serial connections and test the WDB<br />

connection by opening a windsh shell and trying a few shell<br />

commands such as i and version.<br />

K<br />

407


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Target Information Worksheet<br />

<strong>BSP</strong> Validation Checklist<br />

Item Date Status<br />

1. Print and attach the <strong>BSP</strong> Target Information Worksheet to this<br />

checklist. Typically, this worksheet is provided in target.nr,<br />

although some developers might supply it in a different file.<br />

See <strong>BSP</strong> Developer’s <strong>Guide</strong>: Target Information Reference Page:<br />

target.nr.<br />

2. Generate the documentation for the <strong>BSP</strong>. Verify that your<br />

documents are complete and conform to the Wind River<br />

documentation standards. Attach a printout of the<br />

documentation.<br />

3. Verify that the attached documentation for this <strong>BSP</strong> contains<br />

marketing, engineering, and support contact points<br />

(both e-mail and voice).<br />

4. Add any comments that help to explain the nature and severity<br />

of any deviations noted during the testing.<br />

<strong>BSP</strong> Validation: PASS: FAIL: Checklist Completed:<br />

Engineer:<br />

Date:<br />

Signature:<br />

408


K<br />

<strong>BSP</strong> Validation Checklists<br />

Validation Test Suite Checklist<br />

VxWorks Version:<br />

<strong>BSP</strong> Version:<br />

Manufacturer:<br />

Model:<br />

Part Number:<br />

Serial Number:<br />

Revision: Bar Code Tag #:<br />

PROMS used for testing<br />

PROMS Socket ID Checksum<br />

0<br />

1<br />

2<br />

3<br />

Notes:<br />

K<br />

Engineer:<br />

Signature:<br />

Date:<br />

409


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Manufacturer:<br />

Validation Test Suite Checklist<br />

Model:<br />

Test Date Checked<br />

1. auxClock.tcl<br />

auxClock at extra-test frequency<br />

auxClock at min-test frequency<br />

auxClock at max-test frequency<br />

auxClock at default-test frequency<br />

sysAuxClkDisable( ) test<br />

sysAuxClkRateSet( ) parameter checking<br />

sysAuxClkRateGet( ) return value<br />

2. baudConsole.tcl<br />

Console at 150 baud<br />

Console at 300 baud<br />

Console at 600 baud<br />

Console at 1200 baud<br />

Console at 1800 baud<br />

Console at 2400 baud<br />

Console at 4800 baud<br />

Console at 9600 baud<br />

Console at 19200 baud<br />

Console at 38400 baud<br />

3. bootline.tcl<br />

Control/X test<br />

Bus error test for local error address<br />

Bus error test for off-board error address<br />

Boot commands test<br />

4. busTas.tcl slave:<br />

Short-term TAS test<br />

Long-term TAS test<br />

410


K<br />

<strong>BSP</strong> Validation Checklists<br />

Manufacturer:<br />

Validation Test Suite Checklist<br />

Model:<br />

Test Date Checked<br />

5. eprom.tcl<br />

1-byte read of eprom<br />

2-byte read of eprom<br />

4-byte read of eprom<br />

6. error1.tcl<br />

Bus-error test for local address<br />

Bus-error test for offboard address<br />

Divide-by-zero test<br />

7. error2.tcl<br />

Catastrophic error test<br />

Reboot with interrupts<br />

8. model.tcl<br />

sysModel( ) return value<br />

9. network.tcl slave:<br />

Ping target test<br />

UDP packet echo test<br />

10. nvRam.tcl<br />

sysNvRamGet( ) of boot line<br />

sysNvRamSet( ) and sysNvRamGet( )<br />

of complemented boot line<br />

sysNvRamGet( ) with length zero<br />

sysNvRamSet( ) parameter checking<br />

sysNvRamGet( ) parameter checking<br />

sysNvRamSet( ) and sysNvRamGet( ) of 0xff data<br />

sysNvRamSet( ) and sysNvRamGet( ) of 0x00 data<br />

sysNvRamSet( ) and sysNvRamGet( ) of boot line<br />

11. procNumGet.tcl<br />

sysProcNumGet( ) return value<br />

K<br />

411


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

Manufacturer:<br />

Validation Test Suite Checklist<br />

Model:<br />

Test Date Checked<br />

12. ram.tcl<br />

1-byte read of RAM<br />

2-byte read of RAM<br />

4-byte read of RAM<br />

13. rlogin.tcl slave:<br />

IN USE message when rlogin to target0<br />

Reach shell of target0<br />

rlogin pty usage on target0<br />

logout from target0<br />

IN USE message when rlogin to target1<br />

Reach shell of target1<br />

rlogin pty usage on target1<br />

logout from target1<br />

14. scsi.tcl<br />

scsiShow( ) test<br />

SCSI write/read/verify device<br />

15. serial.tcl<br />

Console I/O test<br />

Console echo test<br />

Sequential loopback test<br />

Multiple loopback test<br />

16. sysClock.tcl<br />

sysClk at extra-freq hertz<br />

sysClk at min-freq hertz<br />

sysClk at max-freq hertz<br />

sysClk at default-freq hertz<br />

sysClkDisable( ) disables sysClk<br />

sysClkRateSet( ) parameter checking<br />

sysClkRateGet( ) return value<br />

412


K<br />

<strong>BSP</strong> Validation Checklists<br />

Manufacturer:<br />

Validation Test Suite Checklist<br />

Model:<br />

Test Date Checked<br />

17. timestamp.tcl<br />

Enable the timestamp timer<br />

sysTimestamp( ) long-term test<br />

sysTimestampLock( ) long-term test<br />

Disable the timestamp timer<br />

Re-enable after disable<br />

18. Identify backplane modes tested:<br />

Polling<br />

Bus interrupt<br />

Mailboxes<br />

COMMENTS (refer to the item number above):<br />

K<br />

413


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

414


L<br />

Refgen<br />

NOTE: In Tornado 1.0.1 and earlier releases, UNIX-style man pages were<br />

generated from source code using two awk scripts, mg and mangen. As of Tornado<br />

2.0, UNIX-style man pages are no longer distributed. They have been replaced by<br />

HTML files generated by a new Tcl script called refgen, which, like its<br />

predecessors, is run by make as part of the build process. For more information,<br />

see 9. Documentation <strong>Guide</strong>lines.<br />

NAME<br />

SYNOPSIS<br />

DESCRIPTION<br />

refgen – Tornado reference documentation generator<br />

refgen [-book bookName] [-chapter chapterName] [-config configFile]<br />

[-cpp] [-expath pathList] [-exbase basedir] [-h] [-int]<br />

[-l logFile] [-mg] [-out outDir] [-verbose] fileList<br />

This tool implements a table-driven process for the extraction of documentation from<br />

source. Input tables define a “meta-syntax” that specifies the details of how<br />

documentation is embedded in source files for a particular programming language.<br />

Similarly, output tables define the markup details of the documentation output.<br />

OVERALL CONVENTIONS<br />

Some conventions about how documentation is embedded in source code do not depend<br />

on the source language, and can therefore not be changed from the configuration tables.<br />

Overall Input Conventions<br />

Routines are organized into libraries, and each library begins with a DESCRIPTION<br />

section. If a DESCRIPTION heading is not present, the description section is taken to be<br />

the first comment block after the modification history. Some input languages (such as<br />

shellscript) may begin instead with a section headed SYNOPSIS.<br />

415


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

The first line in a library source file is a one-line title in the following format:<br />

sourceFileName - simple description<br />

That is, the line begins (after whatever start-of-comment character is required) with the<br />

name of the file containing it, separated by a space, a hyphen, and another space from a<br />

simple description of the library.<br />

The first line in a routine’s description (after the source-language-dependent routine<br />

delimiter) is a one-line title in the same format.<br />

Routine descriptions are taken to begin after the routine-title line, whether or not a<br />

DESCRIPTION tag is present explicitly.<br />

Section headings are specified by all-caps strings beginning at a newline and ending with<br />

either a newline or a colon.<br />

Italics, notably including text variables—that is, words in the documentation that are not<br />

typed literally, but are instead meant to be replaced by some value specific to each<br />

instance of use—-are marked in the source by paired angle brackets. Thus, to produce the<br />

output textVar, type .<br />

Boldface words are obtained as follows: General mechanism: surround a word with<br />

single quotes in the source. For example, ‘sysIntIdtType’ produces sysIntIdtType. Special<br />

words: words ending in “Lib” or in a recognized filename suffix are automatically<br />

rendered in bold. For example, fileName.c, object.o, and myStuff.tcl all appear in<br />

boldface.<br />

Simple lists can be constructed by indenting lines in the source from the margin (or from<br />

the comment-continuation character, if one is required in a particular source language).<br />

For example:<br />

line one<br />

line two<br />

Overall Output Conventions<br />

Library descriptions are automatically prefaced by a synopsis of the routines in that<br />

library, constructed from the title lines of all routines.<br />

For some input languages, a SYNOPSIS section is supplied automatically for each routine<br />

as well, extracted from the routine definition in a language-dependent manner specified<br />

in the input meta-syntax tables. Input languages that do not support this have empty<br />

strings for $SYNTAX(declDelim); in such languages, the SYNOPSIS section must be<br />

explicitly present as part of the subroutine comments. For example, both Assembly and<br />

Tcl require an explicit SYNOPSIS section following the DESCRIPTION. The following<br />

example shows the correct markup for Assembly:<br />

416


L<br />

Refgen<br />

* SYNOPSIS<br />

* \cs<br />

* void xxxMemoryInit(void)<br />

* \ce<br />

For some languages, the routine definition is also used to create a PARAMETERS section<br />

automatically.<br />

The online form of documentation is assumed to fit into a structure involving a parent file<br />

(which includes a list of libraries) and a routine index. Several of the procedures in this<br />

library require names or labels for these files, in order to include links to them in the<br />

output. The parent file and routine index need not actually exist at the time that<br />

procedures in this library execute.<br />

DESCRIPTION tags are supplied automatically for all description sections, whether or<br />

not the tag is present in the source file.<br />

SEE ALSO sections are always present in the output for routine descriptions, whether or<br />

not they are present in the source. SEE ALSO sections for routine descriptions<br />

automatically include a reference to the containing library.<br />

OUTPUT DIRECTIVES<br />

The following keywords, always spelled in all capital letters and appearing at the start of<br />

a line, alter the text that is considered for output. Some directives accept an argument in a<br />

specific format, on the same line.<br />

NOROUTINES<br />

Indicates that subroutine documentation should not be generated (must appear in the<br />

library section).<br />

NOMANUAL<br />

Suppresses the section where it appears: either an entire routine’s documentation, or<br />

the library documentation. Routine documentation can also be suppressed in<br />

language-specific ways, specified by matching a regular expression in the<br />

meta-syntactic list LOCALdecls. See refDocGen for a command-line option that<br />

overrides this.<br />

INTERNAL<br />

Suppresses a section (that is, all text from the directive until the next heading, if any).<br />

See refDocGen for a command-line option that overrides this.<br />

APPEND filename<br />

Includes documentation from filename in the output, as if its source were appended to<br />

the file containing the APPEND keyword.<br />

L<br />

EXPLICIT MARKUP<br />

The refgen utility supports a simple markup language that is meant to be inconspicuous<br />

in source files, while supporting most common output needs.<br />

417


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

The following table summarizes refgen explicit markup (numbered notes appear below<br />

the table):<br />

Note Markup Description<br />

\" text to end of line Comment in documentation.<br />

’text ...’ or ‘text ...’ Boldface text.<br />

Italicized text.<br />

[1] \\ or \/ The character \.<br />

[2] \< \> \& \‘ \’ The characters < > & ‘ ’.<br />

\| The character | within a table.<br />

[3] \ss ... \se Preformatted text.<br />

\cs ... \ce<br />

Literal text (code).<br />

\bs ... \be<br />

Literal text, with smaller display.<br />

[4] \is \i ... \i ... \ie Itemized list.<br />

[5] \ml \m ... \m ... \me Marker list.<br />

[6] \ts ... \te A table.<br />

\sh text<br />

A subheading.<br />

\tb reference A reference followed by newline.<br />

Notes on Markup [1] The escape sequence \\ is easier to remember for backslash, but \⁄ is sometimes<br />

required if the literal backslash is to appear among other text that might be confused<br />

with escape sequences. \⁄ is always safe.<br />

[2] < and > must be escaped to distinguish from embedded HTML tags. The & must be<br />

escaped to distinguish from HTML character entities. Single quotes must be escaped<br />

to distinguish from the refgen automatic bolding convention.<br />

[3] Newlines and whitespace are preserved between \ss and \se, but formatting is not<br />

otherwise disabled. These are useful for including references to text variables in<br />

examples.<br />

[4] \is and \ie mark the beginning and end of a list of items. \i is only supported<br />

between \ıs and \ıe. It marks the start of an item: that is, it forces a paragraph break,<br />

and exempts the remainder of the line where it appears from an increased<br />

indentation otherwise applied to paragraphs between \is and \ie.<br />

Thus, the following:<br />

\is<br />

\i Boojum<br />

A boojum is a rare<br />

tree found in Baja<br />

California.<br />

\i Snark<br />

A snark is a different<br />

matter altogether.<br />

\ie<br />

418


L<br />

Refgen<br />

Yields output approximately like the following:<br />

Boojum<br />

A boojum is a rare tree found in Baja California.<br />

Snark<br />

A snark is a different matter altogether.<br />

[5] \ml and \me delimit marker lists; they differ from itemized lists in the output<br />

format—the marker beside \m appears on the same line as the start of the following<br />

paragraph, rather than above.<br />

[6] Between \ts and \te, a whole region of special syntax reigns, though it is somewhat<br />

simplified from the original mangen table syntax.<br />

Three conventions are central:<br />

(a) Tables have a heading section and a body section; these are delimited by a line<br />

containing only the characters - (hyphen), + (plus) and | (stile or bar), and horizontal<br />

whitespace.<br />

(b) Cells in a table, whether in the heading or the body, are delimited by the |<br />

character. \| may be used to represent the | character.<br />

(c) Newline marks the end of a row in either heading or body.<br />

Thus, for example, the following specifies a three-column table with a single heading<br />

row:<br />

\ts<br />

Key | Name | Meaning<br />

----|------------|------------<br />

\& | ampersand | bitwise AND<br />

\| | stile | bitwise OR<br />

# | octothorpe | bitwise NAND<br />

\te<br />

The cells need not align in the source, though it is easier to read it (and easier to avoid<br />

errors while editing) if they do.<br />

The above input yields the following:<br />

L<br />

Key Name Meaning<br />

& ampersand bitwise AND<br />

| stile bitwise OR<br />

# octothorpe bitwise NAND<br />

PARAMETERS<br />

-book<br />

This option allows you to define which book the documented routine or library<br />

belongs to. The default value is “Wind River Systems Reference Manual.”<br />

419


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

-chapter<br />

Related to the -book option, this option allows you to set the documented routine or<br />

library chapter. The default value is set to “Wind River Systems Reference Libraries.”<br />

-category<br />

Related to the -book option, this option allows you to set the documented routine or<br />

library category. It can be used, for example, to differentiate routines available for<br />

different host platforms.<br />

-config configname<br />

Reads configuration information from the file configname if this optional parameter is<br />

present; the default configuration is C2html.<br />

-cpp<br />

This option specifies that the list of given files is to be treated as C++ files. Special<br />

processing is then performed to recover all the class members.<br />

-expath pathList<br />

Preempts EXPANDPATH settings recorded within files with the explicitly-supplied<br />

colon-delimited path list.<br />

-exbase basedir<br />

To simplify working under incomplete trees, this option uses basedir rather than<br />

WIND_BASE as the root for expand-file searching.<br />

-int<br />

If this optional parameter is present, it formats all available documentation, even if<br />

marked INTERNAL or NOMANUAL, and even for local routines.<br />

-l logFile<br />

Specifies that logFile is to be used to log refgen errors. If the -l option is not specified,<br />

standard output is used.<br />

-mg<br />

Converts from mangen markup “on the fly” (in memory, without saving the<br />

converted source file).<br />

-out outputDirectoryName<br />

Saves the output documentation file in outputDirectoryName.<br />

-verbose<br />

Prints reassuring messages to indicate that something is happening.<br />

sourceFileList<br />

Any other parameters are taken as names of source files from which to extract and<br />

format documentation.<br />

420


L<br />

Refgen<br />

EXAMPLE<br />

INCLUDES<br />

SEE ALSO<br />

Generate HTML reference pages for a <strong>BSP</strong> sysLib.c file:<br />

% cd $WIND_BASE/target/config/myBsp<br />

% refgen -mg -book <strong>BSP</strong>_Reference -chapter myBsp -category myBsp \<br />

-out $WIND_BASE/vxworks/bsp/myBsp sysLib.c<br />

refLib.tcl<br />

VxWorks Programmer’s <strong>Guide</strong>: C Coding Conventions, htmlLink, htmlBook, windHelpLib<br />

L<br />

421


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

422


M<br />

<strong>BSP</strong> Product Contents<br />

When you are finished with your <strong>BSP</strong>, the contents of your product should be<br />

similar to the contents shown in this appendix. The <strong>BSP</strong> contains files relevant only<br />

to the particular board type. This list is a sample only and is not expected to be a<br />

final list of required or excluded files.<br />

The traditional <strong>BSP</strong> directory contents follows:<br />

target/config/bspname/Makefile<br />

target/config/bspname/README<br />

target/config/bspname/bootrom<br />

target/config/bspname/config.h<br />

target/config/bspname/bspname.h<br />

target/config/bspname/romInit.s<br />

target/config/bspname/sysALib.s<br />

target/config/bspname/sysScsi.c<br />

target/config/bspname/sysLib.c<br />

target/config/bspname/sysSerial.c<br />

target/config/bspname/target.nr<br />

target/config/bspname/vxWorks<br />

target/config/bspname/vxWorks.st<br />

target/config/bspname/vxWorks.sym<br />

Include any <strong>BSP</strong>-specific drivers in the appropriate format: source, object, or<br />

library. Do not include source for Wind River restricted network or SCSI drivers:<br />

target/config/bspname/specialDrvr.c<br />

target/config/bspname/specialDrvr.obj<br />

target/config/bspname/specialLib.a<br />

423


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

The following files are the new HTML documentation pages:<br />

docs/vxworks/bsp/bspname/*.html<br />

docs/vxworks/bsp/bspname/*.lib<br />

docs/vxworks/bsp/bspname/*.rtn<br />

The following files represent the default projects for a <strong>BSP</strong>:<br />

target/proj/bspname_gnu/Makefile<br />

target/proj/bspname_gnu/linkSyms.c<br />

target/proj/bspname_gnu/prjObjs.lst<br />

target/proj/bspname_gnu/bspname_gnu.wpj<br />

target/proj/bspname_gnu/prjComps.h<br />

target/proj/bspname_gnu/prjParams.h<br />

target/proj/bspname_gnu/prjConfig.c<br />

target/proj/bspname_diab/usrAppInit.c<br />

target/proj/bspname_diab/Makefile<br />

target/proj/bspname_diab/linkSyms.c<br />

target/proj/bspname_diab/prjObjs.lst<br />

target/proj/bspname_diab/bspname_diab.wpj<br />

target/proj/bspname_diab/prjComps.h<br />

target/proj/bspname_diab/prjParams.h<br />

target/proj/bspname_diab/prjConfig.c<br />

target/proj/bspname_diab/usrAppInit.c<br />

The following files represent the default build output of the project:<br />

target/proj/bspname_gnu/default/vxWorks<br />

target/proj/bspname_gnu/default_rom/vxWorks_rom<br />

target/proj/bspname_gnu/default_romCompressed/vxWorks_romCompressed<br />

target/proj/bspname_gnu/default_romResident/vxWorks_romResident<br />

target/proj/bspname_diab/default/vxWorks<br />

target/proj/bspname_diab/default_rom/vxWorks_rom<br />

target/proj/bspname_diab/default_romCompressed/vxWorks_romCompressed<br />

target/proj/bspname_diab/default_romResident/vxWorks_romResident<br />

424


M<br />

<strong>BSP</strong> Product Contents<br />

Do not include any of the following in a <strong>BSP</strong> product:<br />

target/config/bspname/depend.bspname<br />

target/config/all/anything<br />

target/config/comps/anything<br />

target/h/anything<br />

target/src/anything<br />

target/lib/objARCHgnuvx/anything<br />

With Tornado 2.2, Wind River no longer includes any intermediate object files in a<br />

normal <strong>BSP</strong> product. This change was introduced simply to reduce the size of<br />

distributed <strong>BSP</strong>s. Third parties may continue to deliver intermediate object files<br />

(*.o) as part of their <strong>BSP</strong> distributions.<br />

M<br />

425


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

426


Index<br />

A<br />

abort button 82<br />

addressing<br />

memory 69<br />

VMEbus 70<br />

architecture-specific development 64–67<br />

ARCHIVE property (component object) 121<br />

dummy component, creating a 133<br />

using 129<br />

AUX_CLK_RATE_MAX 252<br />

AUX_CLK_RATE_MIN 252<br />

auxiliary clocks 79<br />

adding 58<br />

generic timer driver, in 252<br />

validation testing 155<br />

B<br />

bash shells (Windows) 153<br />

BLK_DEV data structure 320<br />

BOARD 15<br />

makefile, creating a 45<br />

board support packages (<strong>BSP</strong>) 11–39<br />

architecture-specific development 64–67<br />

boot ROMs, using 60<br />

building VxWorks 49<br />

contents 423–425<br />

creating 41–61<br />

cleaning up 58<br />

debugging initialization code 50–53<br />

files, writing 44–49<br />

timers, adding 58<br />

WDB agent before kernel, starting 53<br />

default configuration 196<br />

directories<br />

packaging 195–200<br />

driver templates 100<br />

interrupt controllers 254<br />

NVRAM 252<br />

serial 248<br />

timers 251<br />

END drivers, writing 267–311<br />

files 423–425<br />

#include 16–23<br />

excluded 197–198<br />

hardware-dependent 15<br />

included 197<br />

packaging 195–200<br />

project, <strong>BSP</strong> 30<br />

shared 199<br />

source 12–28<br />

hardware considerations 63–87<br />

kernel, using a minimal 55<br />

media, distribution 200<br />

memory considerations 67–76<br />

network stack, upgrading for VxWorks 221<br />

networking 58<br />

427


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

NVRAM storage, adding 58<br />

packaging 195–201<br />

revision ID number 16<br />

SCSI-2 drivers, writing 317–364<br />

target.nr 27<br />

testing, validation 139–158<br />

Tornado 2.0, upgrading to 203–209<br />

user LEDs 82<br />

Validation Test Suite 139–158<br />

version number 16<br />

boot ROMs 60<br />

entry point 23<br />

initializing 13<br />

BOOT_COLD 23<br />

BOOT_EXTRA<br />

using 24<br />

BOOT_LINE_SIZE 21<br />

generic drivers, in 253<br />

bootConfig.c 13<br />

booting<br />

sequence of events, VxWorks 32–38<br />

command line, from 223–230<br />

project facility, from 238–246<br />

variations 32<br />

bootInit.c 13<br />

debugging initialization 50<br />

bootInit.o 28<br />

bootInit_res.o 28<br />

bootInit_uncmp.o 28<br />

bootline parameters, default 21<br />

bootrom 29<br />

differences from vxWorks image 60<br />

bootrom.hex 29<br />

bootrom.Z.o 29<br />

bootrom.Z.s 29<br />

<strong>BSP</strong> 121<br />

<strong>BSP</strong> Validation Checklist 402<br />

<strong>BSP</strong> VTS, see Validation Test Suite<br />

<strong>BSP</strong>, see board support packages<br />

<strong>BSP</strong>_STUBS property (component object) 121<br />

<strong>BSP</strong>_VERSION 17<br />

bspname.h 26<br />

clocks, system and auxiliary 26<br />

creating <strong>BSP</strong>s 46<br />

device register bits 26<br />

interrupt vectors and levels 26<br />

I/O addresses 26<br />

troubleshooting 39<br />

bspVal script 365<br />

bss segment 35<br />

busTas test 147<br />

special configuration 149<br />

byte order 67<br />

C<br />

cache 65<br />

see also cacheLib(1)<br />

coherency issues 65<br />

driver considerations 103–106<br />

SCSI support 364<br />

configuring 18<br />

drivers, working with 101–110<br />

flush and invalidate macros, using 107–110<br />

initializing 35<br />

memory regions, sharing 104<br />

MMUs, working with 102<br />

snooping 65<br />

write pipelining 66<br />

CACHE_DMA_FLUSH 108<br />

CACHE_DMA_INVALIDATE 108<br />

CACHE_DMA_IS_WRITE_COHERENT 109<br />

CACHE_DMA_PHYS_TO_VIRT 110<br />

CACHE_DMA_VIRT_TO_PHYS 110<br />

CACHE_DRV_FLUSH 109<br />

CACHE_DRV_INVALIDATE 109<br />

CACHE_PIPE_FLUSH 107<br />

CACHE_USER_FLUSH 108<br />

CACHE_USER_INVALIDATE 109<br />

cacheDmaMalloc( ) 103<br />

cache coherency issues 102<br />

SHARED_POINTERS attribute, and the 110<br />

CFG_PARAMS property (component object) 121<br />

CHILDREN property<br />

folder object 117<br />

selection object 119<br />

_CHILDREN property (component object)<br />

using 132<br />

clBlk structures 276<br />

428


Index<br />

clocks<br />

see also individual clock types<br />

auxiliary 79<br />

setting rates 26<br />

system 79<br />

timestamp 79<br />

code examples<br />

SCSI-2 drivers<br />

advanced controller 337<br />

advanced I/O processor 351<br />

basic controller 327<br />

sysScsiInit( ) template 357<br />

virtual memory support 84<br />

commonCmdsTest( ) 362<br />

component description files (CDF)<br />

binding new CDFs to existing objects 135<br />

conventions 126<br />

directories<br />

configlettes 14<br />

VxWorks kernel 14<br />

paths, assigning 127<br />

precedence 126<br />

Component Description Language (CDL) 113–125<br />

conventions 126<br />

object types 115<br />

syntax 231–236<br />

component object<br />

contents 120<br />

header files, specifying 129<br />

naming 128<br />

object code, specifying 128<br />

parameters. declaring 132<br />

source code, specifying 129<br />

synopsis, providing a 128<br />

syntax 232<br />

components 111<br />

archives, working with 133<br />

backwards compatibility 136<br />

creating 127–134<br />

dependencies<br />

object module, analyzing 128<br />

setting, explicitly 131<br />

group membership, defining 132<br />

IDs 136<br />

initialization routine, specifying an 130<br />

initialization sequence, setting 238–246<br />

properties, using CDL object 130<br />

modifying 134<br />

packaging (in directories) 200<br />

parameters, defining 132<br />

reference entries, linking 131<br />

releasing 135<br />

testing 136<br />

config.h 16–23<br />

bootline parameters, default 21<br />

bspname.h 23<br />

bus addresses 23<br />

cache, configuring 18<br />

configAll.h 17<br />

interrupt vectors 23<br />

MMU, configuring 18<br />

non-volatile memory 20<br />

PCI macros 22<br />

RAM addresses 19<br />

RAM size 19<br />

revision ID number 16<br />

ROM addresses 20<br />

ROM size 20<br />

shared-memory network drivers,<br />

configuring 18<br />

timestamp support 21<br />

troubleshooting 39<br />

using in <strong>BSP</strong> 46<br />

version number 16<br />

virtual memory, enabling 85<br />

VMEbus mapping 21<br />

configAll.h 17<br />

CONFIGLETTES property (component<br />

object) 121<br />

initialization routine, specifying an 130<br />

using 129<br />

configNet.h<br />

network stack, upgrading <strong>BSP</strong>s for the 221<br />

configuring<br />

<strong>BSP</strong>, default 196<br />

cache 18<br />

END 274<br />

MMU 18<br />

MUX 274<br />

Validation Test Suite (<strong>BSP</strong> VTS) 143–153<br />

IX<br />

429


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

CONSOLE_BAUD_RATE 37<br />

CONSOLE_TTY 37<br />

generic serial driver, in 249<br />

conventions<br />

documentation 7–9<br />

reference entries 183–194<br />

writing 173–183<br />

COUNT property (selection object) 119<br />

CPU 15<br />

creating <strong>BSP</strong>s 45<br />

ctdt.o 29<br />

D<br />

daemons<br />

network tNetTask 271<br />

root tUsrRoot 271<br />

data link layer 268<br />

network protocol layer, link to 268<br />

dataSegPad.o 29<br />

dataSegPad.s 14<br />

debugging<br />

initialization code 50–53<br />

SCSI-2 drivers 364<br />

DEFAULT property (parameter object) 124<br />

DEFAULT_BOOT_LINE 21<br />

DEFAULTS property<br />

folder object 117<br />

selection object 119<br />

_DEFAULTS property (component object) 122<br />

#define statements<br />

drivers to a target, adding 273–274<br />

depend.bspname<br />

delivering 198<br />

depend.bspname file 15<br />

depend.cputool 49<br />

dependency files 49<br />

delivering 198<br />

dependency, component<br />

object modules, analyzing 128<br />

setting, explicitly 131<br />

derived files 28<br />

<strong>BSP</strong> project files 30<br />

default build output 30<br />

make man help files 30<br />

DEV_OBJ 285<br />

development environment<br />

setting up 43<br />

device drivers, see drivers<br />

DEVICE_WRITES_ASYNCHRONOUSLY 106<br />

SHARED_CACHE_LINES, using with 109<br />

devices, hardware 76–83<br />

see also drivers and individual hardware devices<br />

DIP switches 82<br />

directCmdsTest( ) 362<br />

directRwTest( ) 362<br />

DMA devices 82<br />

support for 254<br />

do_protocol( ) 262<br />

do_protocol_with_type( ) 258<br />

documentation guidelines 173–194<br />

conventions 7–9<br />

online reference entries 8<br />

reference entries 183–194<br />

written style 173–183<br />

downloading code 43<br />

testing 43<br />

drivers 89–110<br />

attributes 105–110<br />

auxiliary clock 79<br />

generic 251<br />

buffers<br />

swapping between driver and<br />

protocol 280<br />

vehicle for 288<br />

cache, working with 101–110<br />

designing 100–101<br />

buses, working with 94<br />

code, writing 101<br />

compile-time flexibility 90<br />

data structures, using 97<br />

documenting 96<br />

goals 90–92<br />

interrupt controllers 94<br />

interrupt service routines, defining 97<br />

I/O-mapped chips, working with 93<br />

macros, using access 98<br />

memory-mapped chips, working with 92<br />

multi-function chips, working with 93<br />

430


Index<br />

naming conventions 95<br />

performance issues 90<br />

portability 90<br />

problems 92–94<br />

re-entrancy 91<br />

routines, declaring 100–101<br />

templates, using 100<br />

testing 101<br />

DMA support 254<br />

Enhanced Network Driver (END) 282–298<br />

entry points, required 289–298<br />

Ethernet controllers 80<br />

flash 252<br />

generic 247–255<br />

END template 267<br />

interrupt controller template 254<br />

NVRAM template 252<br />

serial template 248<br />

timer template 251<br />

timers 251<br />

initializing 25<br />

installing 36<br />

interrupt controllers 254<br />

avoiding design problems 94<br />

interrupt handlers, registering 271<br />

launching 270–274<br />

multi-function (ASIC chips) 254<br />

multi-mode serial, generic and template 249<br />

network 58<br />

4.3 BSD, structure of 258<br />

4.4 BSD, porting 4.3 BSD to 260–264<br />

loading 271<br />

MUX, upgrading 4.3 BSD to 257<br />

non-volatile RAM (NVRAM) 252<br />

packets, receiving 275–280<br />

PCI bus 255<br />

required 56<br />

scatter-gather, supporting 280<br />

SCSI support 81<br />

writing a driver 317–364<br />

serial 56<br />

generic and template 248<br />

system clock 79<br />

generic 251<br />

minimal kernels, using 56<br />

E<br />

target system, adding to a 273–274<br />

template versions 100<br />

timestamp 79<br />

troubleshooting<br />

improperly delivered 38<br />

printf( ) 102<br />

VMEbus 253<br />

END_LOAD_FUNC 274<br />

END_LOAD_STRING 274<br />

END_OBJ 283–285<br />

members 283–285<br />

END_OVERRIDE 274<br />

endFormAddresst( ) 299<br />

endIoctl( ) 292<br />

endLoad( )<br />

END_OBJ structures, and 283<br />

entry point, specifying the 274<br />

endMCastAddrAdd( ) 296<br />

endMCastAddrDel( ) 297–298<br />

endMCastAddrGet( ) 298<br />

endPacketDatarGet( ) 299<br />

endPollReceive( ) 296<br />

endPollSend( ) 295<br />

endSend( ) 293<br />

endStart( ) 294<br />

interrupt handlers, registering driver 271<br />

endStop( ) 294<br />

endTbl table 274<br />

endUnload( ) 291<br />

Enhanced Network Driver (END) 282–298<br />

buffered data, vehicle for 288<br />

configuring 274<br />

control structures, tracking device 285<br />

entry points, required 289–298<br />

errors, indicating 280<br />

network devices, manipulating 283–285<br />

porting 4.3 BSD drivers to 264–266<br />

entry points, required 264–266<br />

IX<br />

431


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

structures, required 283–289<br />

DEV_OBJ 285<br />

END_OBJ 283–285<br />

LL_HDR_INFO 287<br />

mBlk structures 288<br />

NET_FUNCS 286–287<br />

table of entry points 286–287<br />

entry points, driver 289–298<br />

see also specific entry points<br />

4.3 BSD upgrades, for 264–266<br />

forming an address into a packet 299<br />

getting actual data 299<br />

multicast addresses<br />

adding 296<br />

deleting 297–298<br />

table of, getting 298<br />

polling receives, handling 296<br />

polling sends, handling 295<br />

sending data 293<br />

starting loaded drivers 294<br />

state of drivers, controlling the 292<br />

stopping drivers without unloading 294<br />

unloading devices 291<br />

ether_attach( ) 260<br />

ether_output( ) 261<br />

etherHook 259<br />

etherInputHook( ) 259<br />

Ethernet 268<br />

controllers 80<br />

polled-mode 257<br />

RAM 68<br />

etherOutputHook( ) 260<br />

excInit( ) 37<br />

EXCLUDES property (component object) 122<br />

using 131<br />

excVecInit( ) 35<br />

F<br />

files, see dependency files; derived files; include files;<br />

source files<br />

floating point support 66<br />

folder object 116<br />

syntax 235<br />

folders (project facility)<br />

component hierarchy 236<br />

H<br />

hardware 63–87<br />

devices 76–83<br />

initializing system 35<br />

HDR_FILES property (component object) 121<br />

help<br />

make man HTML files 30<br />

HELP property (component object) 122<br />

using 131<br />

HEX_FLAGS<br />

creating <strong>BSP</strong>s 46<br />

I<br />

i960 development<br />

boot sequence 32<br />

IACK, see interrupt acknowledgment<br />

ifnet structure 258<br />

In-Circuit emulator 76<br />

INCLUDE 149<br />

include files 16–23<br />

INCLUDE_END 274<br />

INCLUDE_IO_SYSTEM 37<br />

INCLUDE_LOADER 148<br />

INCLUDE_MMU_BASIC 85<br />

INCLUDE_NET_SYM_TBL 148<br />

INCLUDE_NETWORK 145<br />

INCLUDE_PING 148<br />

INCLUDE_RLOGIN 148<br />

INCLUDE_SCSI 149<br />

INCLUDE_SHELL 148<br />

INCLUDE_SHOW_ROUTINES 148<br />

INCLUDE_SM_NET 149<br />

INCLUDE_SM_NET_SHOW 149<br />

INCLUDE_SM_NET_SHOW 149<br />

INCLUDE_SM_SEQ_ADDR 149<br />

INCLUDE_TIMESTAMP 21<br />

INCLUDE_TTY_DEV 37<br />

432


Index<br />

INCLUDE_USR_APPL 38<br />

INCLUDE_VME 21<br />

INCLUDE_WDB 145<br />

defining 37<br />

INCLUDE_WHEN property (component<br />

object) 122<br />

using 131<br />

INIT_AFTER property (component object)<br />

using 130<br />

INIT_BEFORE property (component object) 122<br />

using 130<br />

INIT_ORDER property (initGroup object) 125<br />

_INIT_ORDER property (component object) 122<br />

using 130<br />

INIT_RTN property<br />

component object 122<br />

using 130<br />

initGroup object 125<br />

initGroups, see initialization group object<br />

initialization group object 124<br />

order, setting 238–246<br />

syntax 236<br />

initialization routine<br />

specifying 130<br />

initialization sequence<br />

see also booting<br />

setting with CDL object properties 130<br />

VxWorks image<br />

RAM-based 51<br />

ROM-based 50<br />

initializing<br />

boot ROMs 13<br />

cache 35<br />

drivers 25<br />

hardware, system 35<br />

interrupt vectors 35<br />

I/O system 36<br />

SCSI-2 in <strong>BSP</strong> 357–359<br />

subsystem 14<br />

VxWorks images 14<br />

installing<br />

drivers 36<br />

Validation Test Suite (<strong>BSP</strong> VTS) 145<br />

intConnect( )<br />

sysHwInit( ), not using with 102<br />

interrupt acknowledgment (IACK) 64<br />

VMEbus 73<br />

interrupt controllers 77<br />

avoiding design problems 94<br />

drivers, generic 254<br />

interrupt service routines (ISR)<br />

drivers, designing into 97<br />

minimal kernels, using with 55<br />

work, queuing 272–273<br />

interrupts 77–78<br />

architecture-specific handling 64<br />

latency 64<br />

levels 78<br />

mailbox 73<br />

vectored 64<br />

initializing 35<br />

VMEbus 73<br />

intLock( ), troubleshooting 39<br />

intLockLevelSet( ) 36<br />

intVecBaseSet( ) 35<br />

I/O system<br />

addresses 26<br />

initializing 36<br />

iosInit( ) 37<br />

IP (Internet Protocol) 268<br />

K<br />

kernelInit( ) 36<br />

generic initialization 52<br />

kernels<br />

execution, start of 34<br />

minimal size 55<br />

WDB agent before, starting 53<br />

L<br />

LEDs, using 82<br />

libcputoolvx.a 36<br />

LINK_SYMS property (component object) 122<br />

using 130<br />

LL_HDR_INFO 287<br />

IX<br />

433


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

LOCAL_MEM_AUTOSIZE 20<br />

LOCAL_MEM_LOCAL_ADRS 19<br />

troubleshooting 38<br />

LOCAL_MEM_SIZE 19<br />

location monitors, see mailbox interrupts<br />

M<br />

MACH_EXTRA<br />

creating <strong>BSP</strong>s 46<br />

mailbox interrupts 73<br />

make man 30<br />

make utility 15<br />

Makefile<br />

contents 15<br />

generating reference pages 189<br />

writing 45<br />

mark-up commands 190–193<br />

mBlk structures 288<br />

loaning buffers 276<br />

MC68040<br />

boot sequence 33<br />

MC683xx<br />

boot sequence 33<br />

media, distribution 200<br />

memory 67–76<br />

see also non-volatile memory<br />

address maps 69<br />

cache, working with 104<br />

parity checking 69<br />

MMU<br />

architecture considerations 66<br />

cache control issues 102<br />

configuring 18<br />

MMU_TAGGING 105<br />

working with 108<br />

MODULES property (component object) 121<br />

using 128<br />

Multibus II 74–76<br />

multicasting 257<br />

multi-mode serial drivers, see serial drivers<br />

MUX interface 267–311<br />

4.3 BSD upgrades<br />

drivers, porting 257<br />

buffers, swapping between driver and<br />

protocol 280<br />

configuring 274<br />

data structures 306<br />

driver-protocol interaction 268–270<br />

memory management utilities, alternative 280<br />

memory pool, creating a 276<br />

network driver, loading the 271<br />

routines 305–310<br />

error messages to protocols, passing 308<br />

packets to protocols, passing 307<br />

restarting protocols 310<br />

shutting down protocols 309<br />

writing protocols 301–311<br />

attaching to the MUX 302<br />

receiving data 303<br />

restarting 304<br />

scatter-gather, supporting 304<br />

seeing protocols 302–303<br />

sending data 303<br />

shutting down 305<br />

starting up 302–303<br />

muxBind( ) 302<br />

restarting a protocol 310<br />

shutting down a protocol 309<br />

muxBufReceive( ) 280<br />

muxDevLoad( ) 271<br />

initialization string, specifying the 274<br />

muxDevStart( ) 271<br />

muxReceive( ) 303<br />

N<br />

NAME property<br />

component object 121<br />

folder object 117<br />

initGroup object 125<br />

parameter object 123<br />

selection object 119<br />

NET_FUNCS 286–287<br />

NET_PROTOCOL 306<br />

netBufLib 276<br />

netJobAdd( ) 272–273<br />

NetROM emulator 76<br />

434


Index<br />

network drivers 58<br />

network interface devices (sysNet.c) 26<br />

network protocol layer 268<br />

data link layer, link to 268<br />

network test 147<br />

special configuration 148<br />

networks<br />

work, queuing 272–273<br />

NMI 67<br />

non-maskable interrupts (NMI) 67<br />

troubleshooting 39<br />

non-volatile memory (NVRAM) 69<br />

adding 58<br />

boards without, for 21<br />

config.h, in 20<br />

drivers, generic and template 252<br />

nroff/troff<br />

macros 190–192<br />

working with 190–193<br />

NUM_TTY 37<br />

generic serial driver 248<br />

NV_BOOT_OFFSET 21<br />

generic drivers, in 253<br />

NV_RAM_SIZE 21<br />

generic drivers, in 253<br />

NVRAM, see non-volatile memory<br />

O<br />

object code, specifying 128<br />

archive, from an 129<br />

online documentation<br />

reference entries 8<br />

P<br />

packaging 195–201<br />

components 200<br />

projects 201<br />

packet reception 275–280<br />

4.3 BSD network drivers 258<br />

etherHooks, using 259<br />

packet transmission 258<br />

etherHooks, using 260<br />

parallel ports (unsupported) 83<br />

parameter object 123<br />

syntax 234<br />

working with 132<br />

parity checking 69<br />

PCI bus 76<br />

chaining compatibility 94<br />

libraries, driver 255<br />

PCI macros 22<br />

PCI_MSTR_MEMIO 23<br />

precedence, component description file 126<br />

printf( )<br />

drivers, not using with 102<br />

prjConfig.c 125<br />

files, generating 134<br />

initialization order, component 240<br />

projects 111<br />

see also component objects<br />

files, generating 134<br />

initialization order 238–246<br />

packaging 201<br />

protocols<br />

IP (Internet Protocol) 268<br />

MUX-based, writing 301<br />

attaching to the MUX 302<br />

receiving data 303<br />

restarting 304<br />

scatter-gather, supporting 304<br />

seeing protocols 302–303<br />

sending data 303<br />

shutting down 305<br />

starting up 302–303<br />

R<br />

RAM 68<br />

addresses 19<br />

Ethernet 68<br />

size 19<br />

IX<br />

435


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

RAM_HIGH_ADRS<br />

config.h 20<br />

creating <strong>BSP</strong>s 45<br />

Makefile 16<br />

RAM_LOW_ADRS 16<br />

writing <strong>BSP</strong>s 45<br />

README file 15<br />

reference entries 173<br />

developing 183–194<br />

linking to a component 131<br />

online 8<br />

Validation Test Suite (<strong>BSP</strong> VTS) 365–400<br />

refgen tool (Wind River)<br />

reference entry 415–421<br />

REQUIRES property (component object) 122<br />

using 131<br />

reset button 82<br />

revision numbers 204<br />

rlogin test 147<br />

special configuration 148<br />

ROM 68<br />

addresses 20<br />

size 20<br />

ROM_ADRS 24<br />

ROM_BASE_ADRS 20<br />

ROM_LINK_ADRS 20<br />

ROM_SIZE 45<br />

config.h 20<br />

Makefile 16<br />

ROM_TEXT_ADRS 15<br />

config.h, in 20<br />

creating <strong>BSP</strong>s 45<br />

ROM_WARM_ADRS 20<br />

creating <strong>BSP</strong>s 45<br />

romInit( ) 23<br />

debugging initialization 50<br />

second-stage initialization 13<br />

romInit.o 29<br />

romInit.s 23<br />

creating <strong>BSP</strong>s 47<br />

debugging initialization 50<br />

troubleshooting 38<br />

romStart( ) 23<br />

debugging initialization 50<br />

second-stage initialization 13<br />

routines<br />

optional 31<br />

required 30<br />

target-specific, system-dependent<br />

assembler source (sysALib.s) 24<br />

C source (sysLib.c) 25<br />

S<br />

SCSI support 61<br />

commands<br />

common 324<br />

direct access 324<br />

forming 321<br />

sequential access 324<br />

controller library 324<br />

controllers 81<br />

data structures 319<br />

drivers, SCSI-2 317–364<br />

advanced controller 334–351<br />

code example 337<br />

advanced I/O processor<br />

code example 351<br />

basic controller 325–334<br />

code example 327<br />

developing 359<br />

programming interface 325–356<br />

termination issues 364<br />

testing 360–363<br />

files 25<br />

initializing in <strong>BSP</strong> 357–359<br />

libraries 321–325<br />

manager, SCSI 322<br />

modules 318<br />

objects 319<br />

troubleshooting 364<br />

validation testing 149<br />

scsi test<br />

special configuration 149<br />

SCSI_CTRL data structure 319<br />

SCSI_PHYS_DEV data structure 320<br />

SCSI_THREAD data structure 319<br />

SCSI_TRANSACTION data structure 319<br />

scsiCommonLib 324<br />

436


Index<br />

scsiCtrlLib 324<br />

scsiDirectLib 324<br />

scsiDiskTest( ) 361<br />

scsiDiskThruputTest( ) 360<br />

scsiMgrLib 322<br />

scsiSeqLib 324<br />

scsiSpeedTest( ) 362<br />

scsiTransact( ) 321<br />

selection object 118<br />

count, setting the 133<br />

syntax 235<br />

SEQ_DEV data structure 320<br />

serial drivers 56<br />

files 25<br />

generic and template 248<br />

multi-mode<br />

generic and template 249<br />

serial ports 79<br />

SETUP utility 195<br />

SHARED_CACHE_LINES 106<br />

working with 109<br />

SHARED_POINTERS 106<br />

cacheDmaMalloc( ), and 110<br />

shared-memory networks<br />

drivers, configuring 18<br />

interrupt types 19<br />

SIO drivers, see serial drivers<br />

SIO_CHAN structure 249<br />

SIO_DRV_FUNCS structure 249<br />

SM_ANCHOR_ADRS 18<br />

SM_INT_TYPE 19<br />

SM_MEM_ADRS 18<br />

SM_MEM_SIZE 19<br />

SNOOPED 106<br />

working with 108<br />

snooping 65<br />

source files 12–28<br />

see also derived files; include files<br />

target/config/all 13<br />

bootConfig.c 13<br />

bootInit.c 13<br />

dataSegPad.s 14<br />

usrConfig.c 14<br />

target/config/bspname 15<br />

bspname.h 26<br />

config.h 16–23<br />

depend.bspname file 15<br />

Makefile<br />

contents 15<br />

README 15<br />

romInit.s 23<br />

sysALib.s 24<br />

sysLib.c 25<br />

sysNet.c 26<br />

sysScsi.c 25<br />

sysSerial.c 25<br />

target.nr 27<br />

target/config/comps/src 14<br />

target/config/comps/vxWorks 14<br />

SPARC/SPARClite development<br />

virtual memory 85<br />

stackError( ) 308<br />

stackRcvRtn( ) 307<br />

passing buffers to the MUX 280<br />

stackShutdownRtn( ) 309<br />

stackTxRestartRtn( ) 310<br />

STANDALONE_NET 145<br />

symTbl.o 29<br />

SYNOPSIS property<br />

component object 121<br />

folder object 117<br />

initGroup object 125<br />

selection object 119<br />

SYS_CLK_RATE_MAX 252<br />

SYS_CLK_RATE_MIN 251<br />

sysAbortInt( ) 31<br />

sysALib.o 29<br />

sysALib.s 24<br />

creating <strong>BSP</strong>s 48<br />

initialization, RAM 51<br />

troubleshooting 38<br />

sysAuxClkConnect( ) 31<br />

single timer, using a 251<br />

sysAuxClkDisable( ) 31<br />

sysAuxClkEnable( ) 31<br />

sysAuxClkInt( ) 31<br />

sysAuxClkRateGet( ) 31<br />

sysAuxClkRateSet( ) 31<br />

IX<br />

437


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

sysBspRev( ) 30<br />

sysBusIntAck( ) 31<br />

sysBusIntGen( ) 31<br />

sysBusTas( ) 31<br />

sysBusTasClear( ) 31<br />

sysBusToLocalAdrs( ) 31<br />

sysClkConnect( ) 30<br />

sysClkDisable( ) 30<br />

sysClkEnable( ) 30<br />

sysClkInt( ) 30<br />

sysClkRateGet( ) 30<br />

sysClkRateSet( ) 30<br />

sysHwInit( ) 35<br />

generic initialization 52<br />

initialization load, easing 24<br />

required 30<br />

system crashes, and 102<br />

sysHwInit2( ) 30<br />

sysInit( ) 51<br />

sysIntConnect( ) 271<br />

sysIntDisable( ) 31<br />

sysIntEnable( ) 31<br />

sysLib.c 25<br />

creating <strong>BSP</strong>s 46<br />

generic initialization 52<br />

virtual memory, enabling 83<br />

sysLib.o 29<br />

routines, required 30<br />

sysLocalToBusAdrs( ) 31<br />

sysMailboxConnect( ) 32<br />

sysMailboxEnable( ) 32<br />

sysMailboxInt( ) 32<br />

sysMemTop( ) 30<br />

sysModel( ) 30<br />

sysNanoDelay( ) 32<br />

sysNet.c 26<br />

sysNvRamGet( ) 30<br />

generic drivers, in 252<br />

sysNvRamSet( ) 30<br />

generic drivers, in 252<br />

sysPhysMemDesc[ ] 102<br />

sysPhysMemTop( ) 31<br />

sysProcNumGet( ) 31<br />

sysProcNumSet( ) 31<br />

sysScsi.c 25<br />

sysScsiConfig( ) 357<br />

sysScsiInit( ) 357<br />

code example, template 357<br />

sysSerialChanGet( ) 31<br />

sysSerialHwInit( ) 31<br />

sysSerialHwInit2( ) 31<br />

system clock 79<br />

generic timer driver, in 251<br />

minimal kernels, using 56<br />

system images 49–53<br />

see also individual images<br />

bootrom 60<br />

initializing 14<br />

vxWorks 49<br />

vxWorks.st 58<br />

vxWorks_resrom_nosym 49<br />

vxWorks_rom 49<br />

sysToMonitor( ) 31<br />

T<br />

T1_SER_BAUD 150<br />

T1_SER_DEVICE 150<br />

T1_TMO_BOOT 150<br />

T2_SER_BAUD 150<br />

T2_SER_DEVICE 150<br />

T2_TMO_BOOT 150<br />

tapeFsTest( ) 363<br />

target boot parameters 151<br />

target directory tree 13<br />

target.nr 27<br />

TARGET_DIR 15<br />

creating <strong>BSP</strong>s 45<br />

tasks<br />

see also daemons<br />

network (tNetTask) 271<br />

root (tUsrRoot) 271<br />

Tcl (tool command language)<br />

Validation Test Suite (<strong>BSP</strong> VTS),<br />

writing the 146<br />

tclserial library 146<br />

test-and-set (TAS) instruction 67<br />

validation testing 147<br />

438


Index<br />

testing, validation 139–158<br />

see also Validation Test Suite<br />

TGT_DIR<br />

creating <strong>BSP</strong>s 45<br />

timeout 150<br />

target boot parameters 151<br />

timers<br />

adding 58<br />

generic 251<br />

timestamp 79<br />

config.h support 21<br />

timestamp test<br />

special configuration 148<br />

tNetTask task 271<br />

TOOL 15<br />

creating <strong>BSP</strong>s 45<br />

Tornado 1.0.1<br />

Tornado 2.0, upgrading <strong>BSP</strong>s to 203–209<br />

Tornado 2.0<br />

upgrading <strong>BSP</strong>s to 203–209<br />

troff/nroff<br />

macros 190–192<br />

working with 190–193<br />

troubleshooting<br />

<strong>BSP</strong>s, writing 38–39<br />

drivers 102<br />

SCSI-2 drivers 364<br />

True Flash File System (TFFS)<br />

drivers for, writing 252<br />

ttyDevCreate( ) 37<br />

ttyDrv( ) 37<br />

tUsrRoot task 271<br />

TY_CO_DEV 248<br />

TYPE property (parameter object) 123<br />

U<br />

upgrading <strong>BSP</strong>s 203–209<br />

USER_APPL_INIT 38<br />

USER_D_CACHE_MOD 18<br />

USER_DATA_UNKNOWN 105<br />

cache coherency, maintaining 108<br />

USER_I_CACHE_MODE 18<br />

USER_RESERVED_MEM 20<br />

usrConfig.c 14<br />

creating <strong>BSP</strong>s 48<br />

initialization 52<br />

usrInit( ) 52<br />

terminating 36<br />

usrRoot( ) 52<br />

V<br />

Validation Test Suite (<strong>BSP</strong> VTS) 139–158<br />

see also individual tests<br />

architecture<br />

multiple-target 142<br />

single-target 141<br />

bash shell, using a (Windows) 153<br />

bspVal script 365<br />

busTas test 147<br />

checklists 401–413<br />

configuring 143–153<br />

bspVal directory 149<br />

bus-full setup 143<br />

host system 147<br />

serial connections 150<br />

standalone setup 144<br />

target hardware 147<br />

timeout 150<br />

VxWorks 148<br />

design goals 140<br />

example test 155<br />

installing 145<br />

monitoring 155<br />

network test 147<br />

parameters, configuration 149<br />

target booting 151<br />

target-specific 151<br />

reference entries 365–400<br />

rlogin test 147<br />

scsi test 149<br />

starting 153<br />

test results, tracking 409<br />

tests 365–400<br />

timestamp test 148<br />

verifying the product 402<br />

Validation Test Suite Checklist 409<br />

IX<br />

439


VxWorks 5.5<br />

<strong>BSP</strong> Developer’s <strong>Guide</strong><br />

variables, uninitialized 35<br />

VENDOR 15<br />

creating <strong>BSP</strong>s 45<br />

versions numbers 204<br />

virtual memory 83–85<br />

see also vmBaseLib(1); vmLib(1)<br />

architecture considerations 66<br />

code example 84<br />

config.h, modifying 85<br />

SCSI troubleshooting 364<br />

SPARC, for 85<br />

sysLib.c, modifying 83<br />

VMEbus 70–74<br />

access windows 70<br />

addressing 70<br />

arbitration 72<br />

drivers 253<br />

dual-porting 71<br />

extractors 74<br />

interrupt acknowledgment 73<br />

interrupts 73<br />

mailbox interrupts 73<br />

mapping 21<br />

power usage 74<br />

read-modify-write (RMW) 71<br />

system controller 72<br />

VLSI chips 74<br />

VxVMI (option) 83<br />

see also virtual memory; vmBaseLib(1);<br />

vmLib(1)<br />

text segment protection 14<br />

VxWorks<br />

boot sequence 32–38<br />

command line, from 223–230<br />

project facility, from 238–246<br />

downloading images 49<br />

entry points<br />

RAM-based 48<br />

ROM-based 23<br />

system images 49<br />

vxWorks 29, 30<br />

creating <strong>BSP</strong>s 49<br />

vxWorks.st 30<br />

creating <strong>BSP</strong>s 58<br />

vxWorks.sym 29, 30<br />

vxWorks_resrom_nosym 49<br />

initialization sequence 50<br />

vxWorks_rom 49<br />

initialization sequence 50<br />

W<br />

WDB agent 41<br />

starting before kernel 53<br />

wdbConfig( ) 37<br />

Wind Debug target agent, see WDB agent<br />

write pipelining 105<br />

hardware consideration 66<br />

working with 107<br />

WRITE_PIPING 105<br />

working with 107<br />

Z<br />

zero-copy TCP 257<br />

440

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!