white.gif (35 bytes)

white.gif (35 bytes)

white.gif (35 bytes)

white.gif (35 bytes)

Arrow

Vx/IP-OctalSerial 8-channel Async Serial VxWorks Device Driver Package

sales@compware.com

 

 

 

Part Number

Price

Description

Vx/IPOctalSerial-S

2495.00

Development/Source license for sig2698 8-channel Async Serial VxWorks Driver

Vx/IPOctalSerial-RTU

145.00

Right-To-Use license for (1) IP-OctalSerial[232|422|485] (MVIP-302/303)

Vx/IPOctalSerial-S-Maint

995.00

12-months Software Maintenance

 

VX/IP-2698 DEVICE SUPPORT PACKAGE SUMMARY AND SAMPLE APPLICATION PROGRAMS

copyright (c) 1996 Compware Corp.

2698B Octal Driver tyOctSerDrv

tyOctSerDrv is a vxWorks device driver supporting multiple asynchronous serial communications ports provided by the IP-Octal 2698B UART Industry Pack (IP). Each IP-Octal implements 8 serial ports when installed in Greenspring 310 or 610 VMEbus carrier boards or the Motorola MVME162. Each IP is identified to the driver by supplying a base VMEbus address, interrupt levels, and interrupt vector. Once initialized, each port is then available for device creation where a device name and buffer parameters are assigned for subsequent tyLib service calls.

tyOctSerDrv takes full advantage of the vxWorks tyLib functions. This provides the capability to accept application program calls that are not device specific increasing the portability of vxWorks serial communications applications.

Driver Startup and Entry Points

The binary tyOctSerDrv.o can either be linked to the vxWorks kernel or downloaded (linked) dynamically. Addressing and configuration of Octal IP's is performed through calls to driver entry points at runtime or through command line calls. The following entry points are provided:

tyOctSerDrv() for starting the driver

tyOctSerPack( address, vector, level1, level2) to allocate driver memory and to initialize hardware for an Industry Pack

tyOctSerDevCreate( name, channel, readBufSize, writeBufSize) to make a port available for tyLib access

Driver startup is performed by calling tyOctSerDrv with no arguments. This call installs the driver as part of the vxWorks I/O subsystem. This function returns OK if succesful otherwise ERROR.

Device Initialization

Each IP installed as part of the serial I/O system must be initialized. A call to tyOctSerPack identifies those parameters necessary to uniquely identify the hardware to the driver. Table memory that maintains configuration and status information is allocated at this time. tyOctSerPack also resets the hardware for each port on the pack and installs handlers for transmit and receive interrupts. During initialization, the address passed is probed for existence of the hardware registers and the ID PROM is checked for compatibility. The function prototype of the initialization call is shown below:

STATUS tyOctSerPack( int baseVmeAddress, int interruptVector, int interruptLevel1, int interruptLevel2 );

Where: baseVmeAddress, is the physical address in short I/O of the IP interruptVector, is the vector number assigned for this IP (0-255) interruptLevel1,2, are the 2 levels assigned (jumpered) to this IP (1-7)

NOTE: If using default PALS with Greenspring's VIPC 310/610 for interrupt allocation, two interrupt levels are necessary to fully support all 8 ports of the IP. These are normally set by the location of jumpers on the carrier board and must be identified to the driver for proper operation. Refer to the VME carrier board documentation for more details on jumper configuration.

Returned status is OK or ERROR.

Device Creation

A serial device is created by calling tyOctSerDevCreate. This call will create a device "file", add the device to tyLib, initialize the port to a default state of 9600 baud, 8 bits/character, 1 stop bit, no parity, and create a channel/port assignment in the driver. This call must be made prior to any 'open' calls by an application.

The function prototype for the device creation call is shown below:

STATUS tyOctSerDevCreate(char *name, int channel, int readBufSize, int writeBufSize );

Where:

name, is the filename associated with this device (ex. /tyCo/portA)

channel, is the channel assignment for this device and is used internally by the driver and for showing stats on devices

read & writeBufSize, allocate ring buffer sizes in tyLib. It is recommended that the read buffer be at least twice the write buffer size and that the write buffer be at least large enough to hold 2 of the largest communications packets.

Returned status is OK or ERROR.

Application Interface

Applications access the serial ports of the Octal IP indirectly via tyLib routines for open, read, write, and ioctl. Each of these are documented in the vxWorks Reference Guide and shown in the sample programs below.

The application designer should be aware of the 2 ways to read from a serial port. There is the normal 'read' call for non-blocking access to the contents of the ring buffer. This call would be used as part of a known protocol perhaps where block sizes vary. The other call is 'fioRead' which includes an argument for the size of the buffer to read which causes vxWorks to perform multiple 'reads' to satisfy that size request.

Device and IP information is displayed to stdio through the following calls:

tyOctSerShow()

to see configuration parameters and registers for all channels that have been added to the I/O system. This is primarily a dump of the device structure maintained for each port and contains the following information: Industry Packs available device tables allocated channels active (created) For each channel: channel number created flag (indicates that a device has been created for this channel) port A flag (TRUE if this is the "a" port of the pair) interrupt vector interrupt level number of data bits number of stop bits contents of all readable registers

tyOctSerShowChan( int channel )

to see information about a channel Address of channel struct created flag (indicates that a device has been created for this channel) port A flag (TRUE if this is the "a" port of the pair) interrupt vector interrupt level number of data bits number of stop bits block hardware address interrupt mask register contents pointer (since the IMR is a READONLY register, a copy is saved in memory for each block of the device) IMR value used during initialization IMR value to use when enabling the transmitter IMR value to use when resetting the interrupts ACR reset value used during reset address of Ip struct associated with this port index that indicates which block of 4 this port resides in

tyOctSerShowReg( int channel )

to see the mode and status registers associated with a particular channel address and contents of both mode registers address and contents of status register address and contents of IMR mask memory location address of receive hold register address and contents of interrupt vector register

These calls were developed for driver debug and evaluation. End-user adaptation is possible to support application requirements. IOCTL's Several ioctl's are provided with the driver for control of the 2698B Octal IP in addition to those ioctl's supported by tyLib.

Ioctl's are invoked using the following syntax: ioctl( fd, operation, argument );

TYCO_2698B_MODE

This allows the application opportunity to set or clear mode register bits under program control. Knowledge of the operation of both mode registers is required to ensure proper operation of the 2698B, particularly interrupt servicing. Care must be taken to avoid clearing bits that are already set in the mode registers. Refer to the product specification for the SCC2698B for a detailed description of the contents of mode registers 1 and 2. The include file scc2698.h contains bit mask definitions for each function in the mode registers and are OR'ed together to form the argument to the ioctl call. Mode register 1 uses the lower 8 bits of argument while mode register 2 uses the upper 8 bits of argument.

For example, to setup the port for local loopback, 1 stop bit, no parity, and 8-bit characters, the following code fragment could be used:

int modepair;

/* setup port for local loopback */

modepair = ( CHAN_MODE_LL | STOP_BITS_1 ) << 8; modepair |= ( PAR_MODE_NO | BITS_CHAR_8 );

if( ioctl( f, TYCO_2698B_MODE, modepair ) |= OK ) { printf("\nERROR setting mode registers\n"); exit(-1); }

TYCO_COMMAND

Allows applications to send commands to the command register for a channel. This provides the full set of commands as documented in the SCC2698B product specification. All commands are #define'd in scc2698.h. The lower 8-bits of argument contains the command byte to be placed in the command register by the driver.

TYCO_ASSERT_RTSN

Asserts the RTS output. Can be used to enable the transmitter for an RS485 application. A NULL 'argument' value is required.

TYCO_NEGATE_RTSN

Negates the RTS output. Enables the receiver for an RS485 application. A NULL 'argument' value is required.

TYCO_ENABLE_CTS

Enables CTS/RTS control by setting bits MR1[7] receiver request to send control and MR2[4] clear to send control. Receiver request to send control causes RTSN to be automatically negated upon receipt of a valid start bit if the receiver FIFO is full. RTSN is reasserted when an empty FIFO position is available. This can be used to prevent overrun when the RTSN signal of the receiver controls the CTS input of the transmitter. Clear to send control affects transmitter operation. When CTSN is asserted, the transmitter is allowed to send a character. When CTSN is negated, the transmitter is not allowed to send.

The argument value to TYCO_ENABLE_CTS is NULL.

FIOBAUDRATE

Selects a baud rate from the list of possible rates supported by the 2698B. The rates that are available include: 75,110,150,300,600,1200,1800,2000,2400,4800,9600,19200,38400

Interrupt Processing

It is important to note here that there are some considerations for the application designer using this IP-OctalSerial and driver. Due to the hardware design, it is necessary that an interrupt service routine for this board respond to an interrupt by polling all 8 ports of the interrupting IP for status. This is because the IP provides a single interrupt vector used for both interrupt levels. Since this is not enough information for the ISR to determine which serial port has requested service, each interrupt status register must be queried to determine the state of all 8 ports before releasing the interrupt.

An ISR time of 10 microseconds or less is generally considered optimal for a realtime system. This ISR can take considerably longer than that to poll all 8 ports and service those that are needed. Since this time is potentially large for some realtime applications and may impact some other applications or drivers installed along with this one, it must be considered when assigning interrupt levels and priorities.

For installations that will install multiple Octal IP's on a VIPC610/616 carrier board, the application engineer must be aware that the carrier allows only 7 of the 8 interrupt levels needed to support a fully populated carrier. The interrupt assignments discussed above must then be modified with a revised carrier board PAL. A PAL can be programmed for specific applications that map interrupts differently. This may also necessitate modifications to the driver, however, in order to implement proper interrupt servicing.

RS485 Application Notes

For those applications that use this driver and RS485 Octal IP's, there are certain considerations to keep in mind when designing the application. RS485 differs from RS232 and RS422 in that there can be up to 32 RS485 "drops" connected to a single pair of wires. This same pair of wires is also shared by the transmitter/receiver so that there is in effect only half duplex communications. This forces the introduction of a protocol by the application layer to decide who is the transmitter with all other "drops" defaulting to receive.

This topology and protocol requirement also introduces a need to select either transmit or receive mode in the Octal UART. Thus, the introduction of the pair of ioctl's for TYCO_ASSERT_RTS and TYCO_NEGATE_RTS.

TYCO_ASSERT_RTS asserts a hardware line to the transmit driver enabling the UART to transmit.

TYCO_NEGATE_RTS drops this line allowing the UART to receive.

It turns out that the hardware design introduces another need for control when the UART is transmitting. This is the need to disable the receiver. If the receiver is not disabled during transmit, it generates a receiver interrupt for each transmitted character. Since the application is typically not expecting to receive its own data, the ring buffer is being filled with unwanted characters. The solution to avoid receiver interrupts is to use the TYCO_COMMAND ioctl with the argument set to RX_DISABLE and then RX_ENABLE when transmission is complete. For some protocol applications however, it may actually be desired to receive the characters that are being transmitted so there is not a potential ring buffer overflow condition introduced.

Test and Sample Programs

The following test and sample programs/scripts are included as a guide to usage of the various features described above.

file: tstCall.s

#--- Load the driver

ld < server_name:/serial/tyOctSerDrv.o

#--- Start the driver

tyOctSerDrv

#--- Initialize an Industry Pack

tyOctSerPack 512,200,5,6

#--- Create devices for all 8 ports

tyOctSerDevCreate "/tyCo/octC0",0,512,512

tyOctSerDevCreate "/tyCo/octC1",1,512,512

tyOctSerDevCreate "/tyCo/octC2",2,512,512

tyOctSerDevCreate "/tyCo/octC3",3,512,512

tyOctSerDevCreate "/tyCo/octC4",4,512,512

tyOctSerDevCreate "/tyCo/octC5",5,512,512

tyOctSerDevCreate "/tyCo/octC6",6,512,512

tyOctSerDevCreate "/tyCo/octC7",7,512,512

#--- Load the test program

ld < server_name:/serial/tyLoopGeneric.o

#--- Setup vxWorks in round robin schedule

kernelTimeSlice(5)

#--- spawn a task for each port to test multiple interrupts

sp tyLoop,"/tyCo/octC0",0

sp tyLoop,"/tyCo/octC1",1

sp tyLoop,"/tyCo/octC2",2

sp tyLoop,"/tyCo/octC3",3

sp tyLoop,"/tyCo/octC4",4

sp tyLoop,"/tyCo/octC5",5

sp tyLoop,"/tyCo/octC6",6

sp tyLoop,"/tyCo/octC7",7

file: tstBC.s

# Test script to exercise IP's in the B and C slots of a 610 carrier

#--- Load the driver

ld < server-name:/serial/tyOctSerDrv.o

#--- Start the driver

tyOctSerDrv

#--- Initialize both IP's

tyOctSerPack 256,200,3,4

tyOctSerPack 512,201,5,6

#--- Create devices on both IP's

tyOctSerDevCreate "/tyCo/octB0",0,512,512

tyOctSerDevCreate "/tyCo/octB1",1,512,512

tyOctSerDevCreate "/tyCo/octB2",3,512,512

tyOctSerDevCreate "/tyCo/octB3",3,512,512

tyOctSerDevCreate "/tyCo/octB4",4,512,512

tyOctSerDevCreate "/tyCo/octB5",5,512,512

tyOctSerDevCreate "/tyCo/octB6",6,512,512

tyOctSerDevCreate "/tyCo/octB7",7,512,512

tyOctSerDevCreate "/tyCo/octC0",8,512,512

tyOctSerDevCreate "/tyCo/octC1",9,512,512

tyOctSerDevCreate "/tyCo/octC2",10,512,512

tyOctSerDevCreate "/tyCo/octC3",11,512,512

tyOctSerDevCreate "/tyCo/octC4",12,512,512

tyOctSerDevCreate "/tyCo/octC5",13,512,512

tyOctSerDevCreate "/tyCo/octC6",14,512,512

tyOctSerDevCreate "/tyCo/octC7",15,512,512

# #--- Load the generic test routine

ld < server_name:/serial/tyLoopGeneric.o

#--- Setup vxWorks in round robin schedule

kernelTimeSlice(5)

#--- Spawn a task for each port

sp tyLoop,"Hello World! 1","/tyCo/octB0",0,1

sp tyLoop,"Hello World! 2","/tyCo/octB1",1,1

sp tyLoop,"Hello World! 3","/tyCo/octB2",2,1

sp tyLoop,"Hello World! 4","/tyCo/octB3",3,1

sp tyLoop,"Hello World! 5","/tyCo/octB4",4,1

sp tyLoop,"Hello World! 6","/tyCo/octB5",5,1

sp tyLoop,"Hello World! 7","/tyCo/octB6",6,1

sp tyLoop,"Hello World! 8","/tyCo/octB7",7,1

sp tyLoop,"Goodbye World! 1","/tyCo/octC0",8,1

sp tyLoop,"Goodbye World! 2","/tyCo/octC1",9,1

sp tyLoop,"Goodbye World! 3","/tyCo/octC2",10,1

sp tyLoop,"Goodbye World! 4","/tyCo/octC3",11,1

sp tyLoop,"Goodbye World! 5","/tyCo/octC4",12,1

sp tyLoop,"Goodbye World! 6","/tyCo/octC5",13,1

sp tyLoop,"Goodbye World! 7","/tyCo/octC6",14,1

sp tyLoop,"Goodbye World! 8","/tyCo/octC7",15,1

file: tyLoopGeneric.c

/* file: tyLoopGeneric.c description:

Tests a serial port in local loopback mode by transmitting a string of characters provided as a argument and comparing the string received date: 6/6/94 author: jet

*/

#include "vxWorks.h"

#include "iv.h"

#include "ioLib.h"

#include "iosLib.h"

#include "tyLib.h"

#include "vme.h"

#include "stdio.h"

#include "string.h"

#include "scc2698.h"

#define NUMBAUDS 13

int bauds[NUMBAUDS] = { 75,110,150,300,600,1200,1800,2000, 2400,4800,9600,19200,38400 };

void tyLoop(char*,char*,int,int);

void tyLoop( char *echoString, char *deviceName , int channel, int printOn)

{

int f;

int loopCounter;

int nbytes,rBytes;

char inString[256];

int n,modepair;

int baudIndex;

bfill( inString, sizeof(inString), 0x00 );

baudIndex = loopCounter = 0;

f = open(deviceName,2,0644);

if( f == NULL )

{

printf("\nError opening device... %s\n",deviceName);

printf("\n");

exit(-1);

}

/* setup port for local loopback */

modepair = ( CHAN_MODE_LL | STOP_BITS_1 ) << 8;

modepair |= ( PAR_MODE_NO | BITS_CHAR_8 );

if( ioctl( f, TYCO_2698B_MODE, modepair ) |= OK )

{

printf("\nERROR setting mode registers\n");

exit(-1);

}

/* setup initial baud rate */

if( ioctl( f, FIOBAUDRATE, bauds[baudIndex] ) |= OK )

{

printf("\nERROR setting baud rate\n");

exit(-1);

}

for(;;)

{

nbytes = write( f, echoString, strlen(echoString) );

if( nbytes != strlen(echoString) )

{

printf("Error writing, numbytes=%d\n",nbytes);

exit(-1);

}

nbytes = fioRead( f, inString, strlen(echoString) );

if( nbytes < strlen(echoString) )

{

printf("Error reading inString, numbytes=%d\n",nbytes);

exit(-1);

}

else

{

if( strncmp(&inString[0], echoString, strlen(echoString)) != 0 )

{

printf(",ERR%d,%s",channel,inString);

}

else

{

if( printOn )printf(",%d",channel);

} }

loopCounter++;

bfill( inString, sizeof(inString), 0x00 );

printf("\n->%d",loopCounter);

/* increment baud rate */

baudIndex++;

if( baudIndex > NUMBAUDS ) baudIndex = 0;

printf("\nSetting baud rate to -> %d", bauds[baudIndex] );

if( ioctl( f, FIOBAUDRATE, bauds[baudIndex] ) |= OK )

{ printf("\nERROR setting baud rate\n");

exit(-1);

} } }

file: tstTest.s

ld < server_name:/serial/tyOctSerDrv.o

tyOctSerDrv

tyOctSerPack 256,200,3,4

tyOctSerPack 000,201,1,2

#

tyOctSerDevCreate "/tyCo/octB0",0,8192,8192

tyOctSerDevCreate "/tyCo/octB1",1,8192,8192

tyOctSerDevCreate "/tyCo/octB2",2,8192,8192

tyOctSerDevCreate "/tyCo/octB3",3,8192,8192

tyOctSerDevCreate "/tyCo/octB4",4,8192,8192

tyOctSerDevCreate "/tyCo/octB5",5,8192,8192

tyOctSerDevCreate "/tyCo/octB6",6,8192,8192

tyOctSerDevCreate "/tyCo/octB7",7,8192,8192

#

tyOctSerDevCreate "/tyCo/octA0",8,8192,8192

tyOctSerDevCreate "/tyCo/octA1",9,8192,8192

tyOctSerDevCreate "/tyCo/octA2",10,8192,8192

tyOctSerDevCreate "/tyCo/octA3",11,8192,8192

tyOctSerDevCreate "/tyCo/octA4",12,8192,8192

tyOctSerDevCreate "/tyCo/octA5",13,8192,8192

tyOctSerDevCreate "/tyCo/octA6",14,8192,8192

tyOctSerDevCreate "/tyCo/octA7",15,8192,8192

#

ld < server_name:/serial/tyTestGeneric.o ld < server_name:/serial/tyTestMonitor.o kernelTimeSlice(1)

# spawn the READER task(s)

tyloop( devicename, channelnum, baud, printflag, read/writeflag )

sp tyLoop,"/tyCo/octA0",8,9600,0,1

sp tyLoop,"/tyCo/octA1",9,9600,0,1

sp tyLoop,"/tyCo/octA2",10,9600,0,1

sp tyLoop,"/tyCo/octA3",11,9600,0,1

sp tyLoop,"/tyCo/octA4",12,9600,0,1

sp tyLoop,"/tyCo/octA5",13,9600,0,1

sp tyLoop,"/tyCo/octA6",14,9600,0,1

sp tyLoop,"/tyCo/octA7",15,9600,0,1

# spawn the WRITER task(s)

sp tyLoop,"/tyCo/octB0",0,9600,0,0

sp tyLoop,"/tyCo/octB1",1,9600,0,0

sp tyLoop,"/tyCo/octB2",2,9600,0,0

sp tyLoop,"/tyCo/octB3",3,9600,0,0

sp tyLoop,"/tyCo/octB4",4,9600,0,0

sp tyLoop,"/tyCo/octB5",5,9600,0,0

sp tyLoop,"/tyCo/octB6",6,9600,0,0

sp tyLoop,"/tyCo/octB7",7,9600,0,0

sp tyMonitor,1000

#

file: tyTestGeneric.c

/* file: tyTestGeneric.c

description: Tests serial ports by being either a transmitter or receiver. This test routine is for use when performing an external wrap test with a ribbon cable wrapped from one 50-pin connector to another.

date: 6/9/94

author: jet

*/

#include "vxWorks.h"

#include "iv.h"

#include "ioLib.h"

#include "iosLib.h"

#include "tyLib.h"

#include "vme.h"

#include "stdio.h"

#include "string.h"

#include "scc2698.h"

#include "tyOctSer.h"

#define EXTERN

#include "tyTest.h"

#define TESTBAUDS 11

#define NUMBAUDS 13

int bauds[NUMBAUDS] = { 75,110,150,300,600,1200,1800,2000, 2400,4800,9600,19200,38400 };

void tyLoop(char*,int,int,int,int);

int multiRead( int, unsigned char*, int, int);

void tyLoop( char *deviceName , int channel, int baud, int printOn, int RWflag)

{

int f;

int loopCounter;

int nbytes,rBytes;

unsigned charBuffer[256];

int n,modepair;

int baudIndex;

monitorType*Monitor;

if( RWflag == Reader )

{

bfill( (char*)Buffer, sizeof(Buffer), 0x00 );

}

else

{

for(n=0;n<sizeof(Buffer);n++) Buffer[n]=n;

/* bfill( (char*)Buffer, sizeof(Buffer), 0x55 ); */

}

baudIndex = 8;

loopCounter = 0;

Monitor = &monTable[ channel ];

Monitor->loopCount=

Monitor->baudRate=

Monitor->errorCount=

Monitor->readByteCounter=

Monitor->writeByteCounter=

Monitor->numRW=0;

if( RWflag == Reader )

{ Monitor->type = READER; }

else { Monitor->type = WRITER; }

f = open(deviceName,2,0644);

if( f == NULL )

{

printf("\nError opening device... %s\n",deviceName);

printf("\n");

exit(-1);

}

/* setup port for local loopback */

modepair = ( CHAN_MODE_NORM | STOP_BITS_1 ) << 8;

modepair |= ( PAR_MODE_NO | BITS_CHAR_8 );

if( ioctl( f, TYCO_2698B_MODE, modepair ) != OK )

{

printf("\nERROR setting mode registers\n");

exit(-1);

}

/* setup initial baud rate */

if( ioctl( f, FIOBAUDRATE, baud ) != OK )

{

printf("\nERROR setting baud rate\n");

exit(-1);

}

Monitor->baudRate = baud;

for(;;)

{

if( RWflag == Writer )

{

/* disable receiver otherwise each transmit causes a receive interrupt */

if( ioctl( f, TYCO_COMMAND, RX_DISABLE ) != OK )

{

if( printOn) { printf("\nERROR disabling Rx\n");}

Monitor->errorCount++;

}

if( ioctl( f, TYCO_ASSERT_RTSN, NULL ) != OK )

{

if( printOn) { printf("\nERROR Asserting RTS\n");}

Monitor->errorCount++;

}

nbytes = write( f, (char*)Buffer, sizeof(Buffer) );

if( nbytes != sizeof(Buffer) )

{

if( printOn) {printf("Error writing, numbytes=%d\n",nbytes);}

Monitor->errorCount++; }

else{ Monitor->numRW++; }

Monitor->writeByteCounter += nbytes;

taskDelay(50);

}

else

{ /* READER */

if( ioctl( f, TYCO_NEGATE_RTSN, NULL ) != OK )

{ if( printOn) {printf("\nERROR Negating RTS\n");}

Monitor->errorCount++;

}

if( printOn ) {printf("\njetRead");}

nbytes = jetRead( f, Buffer, sizeof(Buffer), printOn );

if( nbytes < sizeof(Buffer) )

{ if( printOn)

{printf("Error reading Buffer, numbytes=%d\n", nbytes);}

Monitor->errorCount++;

}

else

{

Monitor->numRW++;

/* check data */

for(n=0;n<sizeof(Buffer);n++)

{

if( Buffer[n] != n ) Monitor->errorCount++;

} }

Monitor->readByteCounter += nbytes;

bfill( (char*)Buffer, sizeof(Buffer), 0x00 );

}/*end if RWflag*/

Monitor->loopCount = ++loopCounter;

if( printOn ) printf("\n->%d",loopCounter);

}/*end for*/

}

int multiRead( int f, unsigned char *Buffer, int length, int printOn )

{

int nbytes,totalBytes;

unsigned chargetmore;

char inPut[256],*I;

int timesTried,timesAllowed;

getmore = TRUE;

totalBytes = timesTried = 0;

timesAllowed = 10000;

I = inPut;

while( getmore )

{

nbytes = read(f,I,length);

totalBytes += nbytes;

if( printOn )printf("\nnBytes read->%d",nbytes);

if( totalBytes >= length )

{

getmore = FALSE;

}

else

{

I += nbytes;

timesTried++;

if( timesTried >= timesAllowed )

{

getmore = FALSE;

} } }

bcopy( inPut, (char*)Buffer, length );

return( totalBytes );

}

1Sep96

 

black.gif (35 bytes)