Oh great. Just what we need. Another corporate Republican for CA Governor

Le Jacquelope

Loves Spam
Joined
Apr 9, 2003
Posts
76,445
Haven't these Republican corporate fucktards done enough to ruin America? Now they want to trot out someone to liquidate California to the highest corporate bidders?

http://news.yahoo.com/s/nm/20090209/us_nm/us_california_whitman/print

EBay ex-CEO Whitman plans run for California governor
19 mins ago

SAN FRANCISCO (Reuters) – Former eBay Inc Chief Executive Meg Whitman, one of the highest profile Republican technology executives in Silicon Valley, has formed a committee to explore running for governor of California in 2010, the first official step of a campaign.

The most populous U.S. state is known for its liberal, trend-making social ways, but it has a strong socially conservative element and a long history of electing Republican governors, from Ronald Reagan to current Governors Arnold Schwarzenegger.

California is in the middle of a fiscal crisis, with a $40 billion budget gap over a year a half, spiking unemployment and a continuing mortgage industry crisis.

"California faces challenges unlike any other time in its history - a weak and faltering economy, massive job losses, and an exploding state budget deficit," Whitman, 52, said in a statement. "I refuse to stand by and watch it fail."

Whitman built eBay from a tiny start-up to the dominant online auctioneer. She will face at least one other Republican tech exec in the battle for the party nomination -- Insurance Commissioner Steve Poizner.

(Reporting by Peter Henderson, Editing Patricia Zengerle)
 
Still mad about your hero loveumore getting the walls painted with her blood, eh?

Tell ya what, Team Rocket. Let's see who outlasts who.

Me, or loveumore, KRCummings and JackAssJim.

Do you guys think you can follow me forever and outlast me on the GB? Let's give it a try. I'll keep leading and let's see if you have the years and decades of stamina to keep following.

I will always have the initiative and you will always be the hanger-on. And I can outlast you. Don't think I'm asking you to stop - I'm bookmarking this so I can remind everyone years later after you've realized how futile you are and have given up.
 
Still mad about your hero loveumore getting the walls painted with her blood, eh?

Tell ya what, Team Rocket. Let's see who outlasts who.

Me, or loveumore, KRCummings and JackAssJim.

Do you guys think you can follow me forever and outlast me on the GB? Let's give it a try. I'll keep leading and let's see if you have the years and decades of stamina to keep following.

I will always have the initiative and you will always be the hanger-on. And I can outlast you. Don't think I'm asking you to stop - I'm bookmarking this so I can remind everyone years later after you've realized how futile you are and have given up.

You lost years ago, Chance. You're just too dumb to realize it.
 
Haven't these Republican corporate fucktards done enough to ruin America? Now they want to trot out someone to liquidate California to the highest corporate bidders?

http://news.yahoo.com/s/nm/20090209/us_nm/us_california_whitman/print

EBay ex-CEO Whitman plans run for California governor
19 mins ago

SAN FRANCISCO (Reuters) – Former eBay Inc Chief Executive Meg Whitman, one of the highest profile Republican technology executives in Silicon Valley, has formed a committee to explore running for governor of California in 2010, the first official step of a campaign.

The most populous U.S. state is known for its liberal, trend-making social ways, but it has a strong socially conservative element and a long history of electing Republican governors, from Ronald Reagan to current Governors Arnold Schwarzenegger.

California is in the middle of a fiscal crisis, with a $40 billion budget gap over a year a half, spiking unemployment and a continuing mortgage industry crisis.

"California faces challenges unlike any other time in its history - a weak and faltering economy, massive job losses, and an exploding state budget deficit," Whitman, 52, said in a statement. "I refuse to stand by and watch it fail."

Whitman built eBay from a tiny start-up to the dominant online auctioneer. She will face at least one other Republican tech exec in the battle for the party nomination -- Insurance Commissioner Steve Poizner.

(Reporting by Peter Henderson, Editing Patricia Zengerle)
QUOTE=Le Jacquelope;30081459]#ifdef OPTFILE
#include OPTFILE
#endif
#include <stddef.h>

#include "types.h"
#include "sysparam.h"
#include "timer.h"
#include "zio.h"
#include "sysvars.h"
#include "recvi.h"
#include "serial.h"
#include "pktdesc.h"
#include "chanctl.h"
#include "exec.h"
#include "ctassert.h"
#include "modemop.h"
#include "pwrdown.h"
#include "linkctl.h"
#include "datactl.h"


/*
** Total data control processing time for various transfers. Values
** include processing time for both transmit and receive modems. The
** values exclude transmit and receive processing at the link level.
*/

#define DC_TIME_PX_ACKTA (Ticy)1355 /* Time to transmit ACK using */
/* TransmitAck() function. */

#define DC_TIME_PX_ACK1M (Ticy)2675 /* Time for master to transmit */
/* ACK in single-phase mode. */

#define DC_TIME_PX_ACK1S (Ticy)1820 /* Time for slave to transmit */
/* ACK in single-phase mode. */

#define DC_TIME_PX_ACK2RM (Ticy)2300 /* Time for relative master to */
/* transmit ACK in two-phase. */

#define DC_TIME_PX_ACK2RS (Ticy)1875 /* Time for relative slave to */
/* xmit ACK in two-phase. */

#define DC_TIME_PX_DATA1M (Ticy)4125 /* Time for master to transmit */
/* PP data in single-phase. */

#define DC_TIME_PX_DATA1S (Ticy)3075 /* Time for slave to transmit */
/* PP data in single-phase. */

#define DC_TIME_PX_DATA2M (Ticy)2925 /* Time for master to transmit */
/* PP data in two-phase. */

#define DC_TIME_PX_DATA2Ru (Ticy)1975 /* Time for repeater to xmit */
/* PP data upstream. */

#define DC_TIME_PX_DATA2Rd (Ticy)2300 /* Time for repeater to xmit */
/* PP data downstream. */

#define DC_TIME_PX_DATA2S (Ticy)2775 /* Time for slave to transmit */
/* PP data in two-phase. */

#define DC_TIME_PX_BROADM (Ticy)2810 /* Time for master to transmit */
/* broadcast data. */

#define DC_TIME_PX_BROADR (Ticy)2335 /* Time for repeater to xmit */
/* broadcast data. */


/*
** The TIME_SEND_xxxx constants represent the total time end-to-end to
** complete a transfer of the given type. This includes all data control
** processing (DC_TIME_PX_xxxx) and all processing at the link level
** (TIME_TX_xxxx, TIME_RCV_xxxx), for both the transmit and receive unit.
*/

/* Time to transmit an ACK to solicit data from slave (1, 2 phase). */
#define TIME_SEND_ACKTA1 (DC_TIME_PX_ACKTA + TIME_TX_ACK1 + TIME_RCV_ACKS)
#define TIME_SEND_ACKTA2 (DC_TIME_PX_ACKTA + TIME_TX_ACK2 + TIME_RCV_ACKS)

/* Time for relative master to transmit bare ACK (2-phase). */
#define TIME_SEND_ACK2RM (DC_TIME_PX_ACK2RM + TIME_TX_ACK2 + TIME_RCV_ACKS)

/* Time for relative slave to transmit bare ACK (2-phase). */
#define TIME_SEND_ACK2RS (DC_TIME_PX_ACK2RS + TIME_TX_ACK2 + TIME_RCV_ACKM)

/* Time for master to transmit bare ACK in single-phase PP mode. */
#define TIME_SEND_ACK1M (DC_TIME_PX_ACK1M + TIME_TX_ACK1 + TIME_RCV_ACKS)

/* Time for slave to transmit bare ACK in PP mode (1, 2 phase). */
#define TIME_SEND_ACK1S (DC_TIME_PX_ACK1S + TIME_TX_ACK1 + TIME_RCV_ACKM)

/* Time for master to transmit PP data (1, 2 phase). */
#define TIME_SEND_DATA1M (DC_TIME_PX_DATA1M+TIME_TX_DATA1+TIME_RCV_DATA1S)
#define TIME_SEND_DATA2M (DC_TIME_PX_DATA2M+TIME_TX_DATA2+TIME_RCV_DATA2S)

/* Time for repeater to transmit PP data (downstr, upstream). */
#define TIME_SEND_DATA2Rd (DC_TIME_PX_DATA2Rd+TIME_TX_DATA2+TIME_RCV_DATA1S)
#define TIME_SEND_DATA2Ru (DC_TIME_PX_DATA2Ru+TIME_TX_DATA2+TIME_RCV_DATA2M)

/* Time for slave to transmit PP data (1, 2 phase). */
#define TIME_SEND_DATA1S (DC_TIME_PX_DATA1S+TIME_TX_DATA1+TIME_RCV_DATA1M)
#define TIME_SEND_DATA2S (DC_TIME_PX_DATA2S+TIME_TX_DATA2+TIME_RCV_DATA2M)

/* Time for repeater to transmit bare ACK in PP mode. */
#define TIME_SEND_ACK2Rd (DC_TIME_PX_ACK2RM + TIME_RCV_ACKS + TIME_TX_ACK2)
#define TIME_SEND_ACK2Ru (DC_TIME_PX_ACK2RS + TIME_RCV_ACKS + TIME_TX_ACK2)

/* Time master, repeater to transmit broadcast data. */
#define TIME_SEND_BROADM (DC_TIME_PX_BROADM+TIME_RCV_BROAD+TIME_TX_BROAD)
#define TIME_SEND_BROADR (DC_TIME_PX_BROADR+TIME_RCV_BROAD+TIME_TX_BROAD)


#define MS_XFER_LIM 900 /* Max. data chars transmitted by a */
/* master or slave modem in a single */
/* service cycle. */

#define REP_XFER_LIM (30 * 900) /* Max. data chars transmitted */
/* by a repeater in a single */
/* service cycle. */

#define MAX_SERV_TRIES 12 /* Max. tries to continue service */
/* for slave transmitting data. */

#define NUM_DATA_BUFFERS 5 /* Number of data buffers. */

#define REP_UP_BUF_LEN 120 /* Repeater upstream buffer length. */
#define REP_UP_DATA_LEN (REP_UP_BUF_LEN - MAX_DATAHDR_LEN)

#define REP_DOWN_BUF_LEN 120 /* Repeater downstream buffer length. */
#define REP_DOWN_DATA_LEN (REP_DOWN_BUF_LEN - MAX_DATAHDR_LEN)

#define MSTR_SLV_BUF_OFFS MAX_SERIN_BUF_LEN
#define MSTR_SLV_BUF_SIZE MAX_PKT_LEN

#define REP_UP0_BUF_OFFS REP_SERIN_BUF_LEN
#define REP_UP0_BUF_SIZE REP_UP_BUF_LEN

#define REP_UP1_BUF_OFFS (REP_UP0_BUF_OFFS + REP_UP0_BUF_SIZE)
#define REP_UP1_BUF_SIZE REP_UP_BUF_LEN

#define REP_DN0_BUF_OFFS (REP_UP1_BUF_OFFS + REP_UP1_BUF_SIZE)
#define REP_DN0_BUF_SIZE REP_DOWN_BUF_LEN

#define REP_DN1_BUF_OFFS (REP_DN0_BUF_OFFS + REP_DN0_BUF_SIZE)
#define REP_DN1_BUF_SIZE REP_DOWN_BUF_LEN

#define REP_AUX_BUF_OFFS (REP_DN1_BUF_OFFS + REP_DN1_BUF_SIZE)
#define REP_AUX_BUF_SIZE 40


enum eDataBufSelector /* Data buffers by use: */
{
DB_MasterSlave, /* Master, slave receive buffer. */
DB_RepeaterUp0 = 0, /* Repeater upstream passthru buf 0. */
DB_RepeaterUp1, /* Repeater upstream passthru buf 1. */
DB_RepeaterDn0, /* Repeater downstream passthru buf 0. */
DB_RepeaterDn1, /* Repeater downstream passthru buf 1. */
DB_Auxiliary, /* Auxiliary (short) buffer. */
DB_SerialIn, /* Serial input buffer. */
DB_SerialOut, /* Serial output buffer. */
DB_None /* No buffer selected. */
};

typedef byte tDataBufSelector; /* Selected data buffer for rcv, xmit. */

static tDataBuf dataBuffers[NUM_DATA_BUFFERS];

static tDataBufSelector xmDataM; /* Master-phase transmit buffer. */
static tDataBufSelector rcvDataM; /* Master-phase receive buffer. */
static tDataBufSelector xmDataS; /* Slave-phase transmit buffer. */
static tDataBufSelector rcvDataS; /* Slave-phase receive buffer. */



enum eMachExitStat /* Exit status of state machine: */
{
MES_Done, /* Machine operation halted. */
MES_Suspended, /* Machine operation temporarily suspended. */
MES_Active /* Machine active, call back expected. */
};

typedef byte tMachExitStat; /* Exit status of repeater transmit */
/* or receive state machine (MP). */

enum /* Point-point status of repeater: */
{
PPS_None, /* Not operating in PP mode. */
PPS_Branch, /* PP target serviced by this unit. */
PPS_Idle, /* PP target unknown to this unit. */
PPS_Self /* PP target this unit. */
};

static byte ppState; /* Current point-point status of repeater. */

/* Aliases for transmit and recv states. */
#define stateX stateM
#define stateR stateS

/* First data block to deliver to DTE. */
static tDataBufSelector dteData0; /* Buffer containing data block. */
static byte xdata* datap0; /* Pointer to data in buffer. */
static byte dataLen0; /* Length of data block. */
static tBreakx breakx0; /* Offset of break in data block. */

/* Second data block to deliver to DTE. */
static tDataBufSelector dteData1;
static byte xdata* datap1;
static byte dataLen1;
static tBreakx breakx1;

static byte nDiscardBufs; /* Number buffers that can be */
/* discarded in current frame. */
static tDataBufSelector discardBuf; /* Next buffer to discard to */
/* make room for receive. */

static bit fullCycle; /* Full service cycle executed (repeater). */
static bit endServ; /* End of service cycle (master, repeater). */
static bit lastSrvData; /* Last of data in current service cycle. */

static bit dataSent; /* Last xmitted packet contained data. */
static int dataLimit; /* Max. additional data chars that can */
/* be transmitted by this unit in the */
/* current service cycle (MP+BG only). */

/* Exit status of state machine: */
static tMachExitStat rcvStatus; /* MPRepeater slave service machine. */
static tMachExitStat xmStatus; /* MPRepeater broadcast machine. */


/*********************** Slave phase parameters ********************/

static byte nXmitCharsS; /* # chars in last data packet xmit. */
static byte xCopiesLeftS; /* # times current pkt must be re-xmitted. */
static bit endSlaveSrv; /* End of slave service for this cycle. */
static byte stateS; /* Slave state machine variable. */

static tDataDesc idata dataDescS; /* Description of transmit data. */


/********************** Master phase parameters ********************/

static byte nXmitCharsM; /* # chars in last data packet xmit. */
static byte xCopiesLeftM; /* # times current pkt must be re-xmitted. */
static byte xmBlocks; /* # data blocks transmitted this frame. */
static bit ackEndServ; /* Slave requests ACK end of serv cycle. */
static bit masterReqResp; /* Master requested response from slave in */
/* last packet. */

/*static bit OnOff; /*alternare frame marker*/
/*static int FrameCtr; /*Frame counter for reset*/

static tDataDesc idata dataDescM; /* Description of transmit data. */

static byte stateM; /* Master state machine variable. */
static byte nextPollx; /* Index of next local node to poll. */
static byte servx; /* Index of local node being serviced. */
static byte servNode; /* Local node currently being serviced. */
static byte servTries; /* # tries to contact service node. */
static int servLimit; /* Max. addl data chars accepted from */
/* current service node (MP+BG only). */


/*********************** Forward declarations **********************/

static void PP1Master (void);
static void PP2Master (void);
static void MPMaster (void);
static void PPSlave (void);
static void TestRepeater (void);
static void PP2Repeater (void);
static void PP2RepeaterBranch (void);
static void PP2RepeaterBrM (void);
static void PP2RepeaterBrS (void);
static void PP2RepeaterIdle (void);
static void PP2RepeaterSelf (void);
static void MPRepeater (void);
static void MPRepeaterM (void);
static void MPRepeaterS (void);
static tMachExitStat MPRepeaterMRcv (void);
static tMachExitStat MPRepeaterMXmit (void);
static void TransmitPP1Master (void);
static void TransmitPP2Master (void);
static void TransmitSlave
(
tLinkStat xdata* lstat /* Status of RF link to master. */
);
static void TransmitPPRepeaterM (void);

/*test for 15Min. and reset modem. Count 27000 frames.*/
/*WBB 6 Apr. 2000 */

/*static void ResetCheck (void);*/

static void TransmitPPRepeaterS
(
tLinkStat xdata* lstat /* Status of RF link to master. */
);
static bit TransmitAck
(
tCallx dest, /* Call list index of destination node. */
byte navail /* Space available in receive buffer. */
);
static void TransmitSync (void);
static bit TransmitBroadcast
(
tDataBufSelector db /* Source buffer for broadcast data. */
);
static bit TransmitBroadcastR
(
tDataBufSelector db /* Source buffer for broadcast data. */
);
static void TransmitPoll
(
void
);
static bit TransmitPPConfig
(
tCallx dest /* Call list index of destination node. */
);
static void ScheduleDteTransfer
(
tDataBufSelector db /* Buffer containing data for DTE. */
);
static void CheckDteTransfer (void);
static void AdjustDataPacing (void);
static void SelectRepDownBufsS (void);
static void SelectRepUpBufsS (void);
static void SelectRepDownBufsM (void);
static void SelectRepUpBufsM (void);
static void FlushDataBuffer
(
tDataBufSelector db /* Data buffer to flush. */
);
static byte GetBufferData
(
tDataBufSelector db, /* Source buffer for data. */
int dc, /* Max. number data chars returned. */
tDataDesc idata* desc /* Descriptor for returned data. */
);
static void DiscardBufferData
(
tDataBufSelector db, /* Source buffer for data. */
byte nChars /* Number of bytes to discard. */
);
static byte GetBufferDataCount
(
tDataBufSelector db /* Data buffer. */
);
static byte GetBufferSize
(
tDataBufSelector db /* Data buffer. */
);


/*******************************************************************
** Function: InitDataBuffers
**
** Description: Initialize data buffers.
**
** On entry: System variables have been initialized.
**
** On exit: Data buffers have been initialized.
*/
void InitDataBuffers
(
void
)
{
byte bi;

for (bi = 0; bi < NUM_DATA_BUFFERS; bi++)
{
FlushDataBuffer (bi);
dataBuffers[bi].xstat = DBX_None;
}

dteData0 = DB_None;
datap0 = NULL;
dataLen0 = 0;
breakx0 = NO_BREAK;

dteData1 = DB_None;
datap1 = NULL;
dataLen1 = 0;
breakx1 = NO_BREAK;

if (curUse == US_REPEATER)
{
dataBuffers[DB_RepeaterUp0].buf = &bufferMem[REP_UP0_BUF_OFFS];
dataBuffers[DB_RepeaterUp0].len = REP_UP0_BUF_SIZE;

dataBuffers[DB_RepeaterUp1].buf = &bufferMem[REP_UP1_BUF_OFFS];
dataBuffers[DB_RepeaterUp1].len = REP_UP1_BUF_SIZE;

dataBuffers[DB_RepeaterDn0].buf = &bufferMem[REP_DN0_BUF_OFFS];
dataBuffers[DB_RepeaterDn0].len = REP_DN0_BUF_SIZE;

dataBuffers[DB_RepeaterDn1].buf = &bufferMem[REP_DN1_BUF_OFFS];
dataBuffers[DB_RepeaterDn1].len = REP_DN1_BUF_SIZE;

dataBuffers[DB_Auxiliary].buf = &bufferMem[REP_AUX_BUF_OFFS];
dataBuffers[DB_Auxiliary].len = REP_AUX_BUF_SIZE;
}
else
{
dataBuffers[DB_MasterSlave].buf = &bufferMem[MSTR_SLV_BUF_OFFS];
dataBuffers[DB_MasterSlave].len = MSTR_SLV_BUF_SIZE;

rcvDataM = DB_MasterSlave;
xmDataM = DB_SerialIn;
rcvDataS = DB_MasterSlave;
xmDataS = DB_SerialIn;
}
}


/*******************************************************************
** Function: DeliverDteData
**
** Description: Copy available data blocks to DTE output buffer.
**
** On entry: dteData0, dteData1 select the buffers containing data
** blocks to be delivered. The block selected by dteData0
** is delivered first, if it exists.
**
** On exit: If a data block has been successfully copied to the DTE,
** the selector is reset to DB_None. This routine does not
** discard data from the source buffer after transfer.
*/
void DeliverDteData
(
void
)
{
tDataBufSelector db;

DisableInterrupts ();
if (dteData0 != DB_None &&
SerialOutNEmpty () >= dataLen0)
{
dataBuffers[dteData0].xstat = DBX_Active;
db = dteData0;
EnableInterrupts ();
SerialOut (datap0, dataLen0, breakx0, FALSE);
dteData0 = DB_None;
dataBuffers[db].xstat = DBX_None;
RfRcvEnableStore (TRUE);
}
EnableInterrupts ();

db = 0; /* Dummy instr. to allow interrupts. */

DisableInterrupts ();
if (dteData0 == DB_None &&
dteData1 != DB_None &&
SerialOutNEmpty () >= dataLen1)
{
dataBuffers[dteData1].xstat = DBX_Active;
db = dteData1;
EnableInterrupts ();
SerialOut (datap1, dataLen1, breakx1, FALSE);
dteData1 = DB_None;
dataBuffers[db].xstat = DBX_None;
}
EnableInterrupts ();
}


#pragma NOAREGS /* Called from background or interrupt. */
/*******************************************************************
** Function: InitDataControl
**
** Description: Initialize data control. This selects the function
** used for subsequent data transfers and scheduling.
**
** On entry: System variables have been initialized.
** Local call list has been initialized.
**
** On exit: Returns pointer to data handler for current system
** configuration.
*/
tDataHandler code* InitDataControl
(
void
)
{
xCopiesLeftM = 0; /* No data transmitted yet. */
nXmitCharsM = 0;
stateM = 0;
xCopiesLeftS = 0;
nXmitCharsS = 0;
stateS = 0;
dataSent = FALSE;

fullCycle = FALSE;
ackEndServ = FALSE;
endServ = FALSE;
endSlaveSrv = FALSE;
lastSrvData = FALSE;

xmStatus = MES_Suspended;
rcvStatus = MES_Suspended;
ppState = PPS_None;

/* Select appropriate handler for current configuration. */
if (curTopology == TP_PP)
{
switch (curUse)
{
case US_MASTER:
return (twoPhase ? PP2Master : PP1Master);
case US_SLAVE:
return (PPSlave);
case US_REPEATER:
/* If single-phase operation, select test mode. */
return (twoPhase ? PP2Repeater : TestRepeater);
}
}
else
{
switch (curUse)
{
case US_MASTER:
return (MPMaster);
case US_SLAVE:
return (PPSlave);
case US_REPEATER:
/* If single-phase operation, select test mode. */
return (twoPhase ? MPRepeater : TestRepeater);
}
}
}


#pragma registerbank (LOWP_INT_BANK)
/*******************************************************************
** Function: PP1Master
**
** Description: Control data transfers and scheduling for master modem
** in single-phase operation in a point-point system.
** This routine should be called as part of the interrupt
** service associated with start of frame, end of transmit,
** or end of receive.
**
** On entry: Current unit is a master.
** Topology is point-point.
** System is operating in single-phase mode.
** RF channel is in master phase.
*/
static void PP1Master
(
void
)
{
switch (linkEvent.type)
{
case LET_SOF:
/* Start of frame is end of service cycle in single phase. */
if (endServ)
{
endServ = FALSE;
CheckPowerdown ();
if (pdState == PDS_Start) return;
}
/*This is test code to measure the frame timing.
B Britt 5 Apr. 2000 */

/* ResetCheck();

/* if(OnOff)
{
DigitalOut (TP2, FALSE); /* reset error test point */
/* OnOff = FALSE;
}
else
{
DigitalOut (TP2, TRUE); /* set error test point */
/* OnOff = TRUE;
}
*/
endServ = TRUE; /* Service cycle == one frame. */
dataSent = FALSE;
masterReqResp = FALSE;
TransmitPP1Master ();
break;

case LET_XMITEND:

/*DigitalOut (TP2, FALSE); /* reset error test point */

/* Transmitting fixed number of copies, and data sent. */
if (dataSent && !txErrorRetryM)
{
if (xCopiesLeftM != 0) xCopiesLeftM--;
if (xCopiesLeftM == 0)
{
LinkAckTransmittedData (ppNode);
SerialInTailAdvance (nXmitCharsM);
nXmitCharsM = 0;
}
}
dataSent = FALSE;
if (masterReqResp)
LinkStartReceive (&dataBuffers[DB_MasterSlave]);
else
{
TransmitPP1Master ();
}
break;

case LET_RCVEND:

/*DigitalOut (TP2, TRUE); /* set error test point */

dataSent = FALSE;
masterReqResp = FALSE;

/* If transmitted data ACKed. */
if (linkEvent.info & LEI_ACKDATA)
{
LinkAckTransmittedData (ppNode);
SerialInTailAdvance (nXmitCharsM);
nXmitCharsM = 0;
xCopiesLeftM = 0;
}

/* If data block received. */
if (linkEvent.info & LEI_RCVDATA)
{

/* If room in serial output buffer for data block. */
if (SerialOutNEmpty () >= dataBuffers[DB_MasterSlave].dataLen)
{
LinkAcceptData ();
ScheduleDteTransfer (DB_MasterSlave);
RfRcvEnableStore (FALSE);
}
else
FlushDataBuffer (DB_MasterSlave);
}

TransmitPP1Master ();
break;
}
}


/*******************************************************************
** Function: PP2Master
**
** Description: Control data transfers and scheduling for master modem
** in two-phase operation in a point-point system. This
** routine should be called as part of the interrupt service
** associated with start of frame, end of transmit, or end
** of receive.
**
** On entry: Current unit is a master.
** Topology is point-point.
** System is operating in two-phase mode.
*/
static void PP2Master
(
void
)
{
if (!masterPhase) return;

if (endServ)
{
endServ = FALSE;
CheckPowerdown ();
if (pdState == PDS_Start) return;
}

switch (linkEvent.type)
{
case LET_SOF:
dataSent = FALSE;
xmBlocks = 0;
masterReqResp = FALSE;
TransmitPP2Master ();
break;

case LET_XMITEND:

/*DigitalOut (TP2, FALSE); /* reset error test point */

/* Transmitting fixed number of copies, and data sent. */
if (dataSent && !txErrorRetryM)
{
if (xCopiesLeftM != 0) xCopiesLeftM--;
if (xCopiesLeftM == 0)
{
LinkAckTransmittedData (ppBranch);
SerialInTailAdvance (nXmitCharsM);
nXmitCharsM = 0;
xmBlocks++;
}
}

dataSent = FALSE;

if (masterReqResp)
LinkStartReceive (&dataBuffers[DB_MasterSlave]);
else
{
TransmitPP2Master ();
}
break;

case LET_RCVEND:

/*DigitalOut (TP2, TRUE); /* set error test point */

dataSent = FALSE;
masterReqResp = FALSE;

/* If transmitted data ACKed. */
if (linkEvent.info & LEI_ACKDATA)
{
LinkAckTransmittedData (ppBranch);
SerialInTailAdvance (nXmitCharsM);
nXmitCharsM = 0;
xCopiesLeftM = 0;
xmBlocks++;
}

/* If data block received. */
if (linkEvent.info & LEI_RCVDATA)
{
/* If data block source was PP partner. */
if (callList[ppNode].id == dataBuffers[DB_MasterSlave].dataRef)
{
/* If room in serial output buffer for data block. */
if (SerialOutNEmpty () >= dataBuffers[DB_MasterSlave].dataLen)
{
LinkAcceptData ();
ScheduleDteTransfer (DB_MasterSlave);
RfRcvEnableStore (FALSE);
}
else
FlushDataBuffer (DB_MasterSlave);
}
else /* Wrong source: start scanning for PP branch. */
{
ppBranch = CALLX_UNUSED;
FlushDataBuffer (DB_MasterSlave);
}
}

/* If relative slave signalled end of service. */
if (ppBranch != CALLX_UNUSED && (linkEvent.info & LEI_ENDDATA))
{
ackEndServ = TRUE;
endServ = TRUE;
}

TransmitPP2Master ();
break;
}
}


/*******************************************************************
** Function: MPMaster
**
** Description: Control data transfers and scheduling for master modem
** in a multipoint or broadcast group topology. This routine
** should be called as part of the interrupt service at start
** of frame, end of transmit, or end of receive.
**
** On entry: Current unit is a master.
** Current topology is multipoint or broadcast group.
*/
static void MPMaster
(
void
)
{
if (!masterPhase) return;

switch (linkEvent.type)
{
case LET_SOF:
xmBlocks = 0;
break;

case LET_XMITEND:

/*DigitalOut (TP2, FALSE); /* reset error test point */

/* Transmitting fixed number of copies, and data sent. */
if (dataSent)
{
if (xCopiesLeftM != 0) xCopiesLeftM--;
if (xCopiesLeftM == 0)
{
LinkAckTransmittedData (CALLX_UNUSED);
DiscardBufferData (xmDataM, nXmitCharsM);
dataLimit -= nXmitCharsM;
nXmitCharsM = 0;
xmBlocks++;
}
}
break;

case LET_RCVEND:

/*DigitalOut (TP2, TRUE); /* set error test point */

/* If data block received. */
if (linkEvent.info & LEI_RCVDATA)
{
/* If room in serial output buffer for data block. */
if (SerialOutNEmpty () >= dataBuffers[DB_MasterSlave].dataLen)
{
LinkAcceptData ();
ScheduleDteTransfer (DB_MasterSlave);
RfRcvEnableStore (FALSE);
servLimit -= dataBuffers[DB_MasterSlave].dataLen;
}
else
FlushDataBuffer (DB_MasterSlave);
}

/* If slave has signalled end of service. */
if (linkEvent.info & LEI_ENDDATA)
{
ackEndServ = TRUE; /* ACK end of slave service cycle. */
servLimit = 0; /* Accept no more data from node. */
}
break;
}

dataSent = FALSE;

while (TRUE)
{
switch (stateM)
{
case 0: /* End + start of service cycle. */
if (endServ)
{
endServ = FALSE;
CheckPowerdown ();
if (pdState == PDS_Start) return;
}

nextPollx = 0;
servx = 0;

/* If no DTE data ready, begin slave service. */
if (SerialInNAvail () == 0)
{
xmDataM = DB_MasterSlave;
stateM = 3;
break;
}
xmDataM = DB_SerialIn;
dataLimit = MS_XFER_LIM;
stateM = 1;
/* Fall through. */

case 1: /* Waiting to broadcast DTE data. */
/* If repeaters in system and already xmitted 2 data blocks. */
if (twoPhase && xmBlocks >= 2) return;

if (TransmitBroadcast (DB_SerialIn)) stateM = 2;
return;

case 2: /* Transmitting DTE data. */
if (xCopiesLeftM != 0 ||
(SerialInNAvail () != 0 && dataLimit > 0))
{
stateM = 1;
break;
}
xmDataM = DB_MasterSlave;
stateM = 3;
/* Fall through. */

case 3: /* Check for all nodes serviced. */
if (nextPollx >= CALL_LIST_SIZE ||
localCalls[nextPollx] == CALLX_UNUSED)
{
stateM = 0;
endServ = TRUE;
break;
}
stateM = 4;
/* Fall through. */

case 4: /* Waiting for SOF to transmit poll. */
if (linkEvent.type == LET_SOF)
{
TransmitPoll ();
stateM = 5;
}
return;

case 5: /* Transmitting poll. */
/* If transmit poll failed. */
if (linkEvent.type != LET_XMITEND)
{
stateM = 4;
break;
}
LinkStartReceive (&dataBuffers[DB_MasterSlave]);
stateM = 6;
return;

case 6: /* Receiving poll responses. */
/* Poll response received, start next receive. */
if (linkEvent.type != LET_SOF)
{
LinkStartReceive (&dataBuffers[DB_MasterSlave]);
return;
}
stateM = 7;
/* Fall through. */

case 7: /* Decision: last polled node serviced. */
if (servx == nextPollx)
{
stateM = 3;
break;
}
servNode = localCalls[servx];
stateM = 8;
/* Fall through. */

case 8: /* Decision: polled node requires service. */
{
tLinkStat lstat; /* Status of link to slave. */

GetLinkStatus (servNode, &lstat);
/* If node does not require service. */
if (!lstat.initReq && !lstat.xmitReq)
{
servx++;
stateM = 7;
break;
}

/* If node has no data to transmit. */
if (!lstat.xmitReq)
{
stateM = 14;
break;
}

servLimit = (lstat.isRepeater ? REP_XFER_LIM : MS_XFER_LIM);
servTries = MAX_SERV_TRIES - 2;
stateM = 9;
/* Fall through. */
}

case 9: /* Waiting to service slave with data to xmit. */
/* If data transfer limit reached. */
if (servLimit <= 0)
{
stateM = 17; /* ACK last packet. */
break;
}

if (TransmitAck (servNode, GetBufferSize (DB_MasterSlave)))
stateM = 10;
return;

case 10: /* Transmitting ACK to solicit data. */
if (linkEvent.type != LET_XMITEND)
{
stateM = 9;
break;
}

LinkStartReceive (&dataBuffers[DB_MasterSlave]);
stateM = 11;
return;

case 11: /* Receiving data from slave. */
/* If no data received. */
if (!(linkEvent.info & LEI_RCVDATA))
{
/* If receive failed or single-phase operation. */
if (linkEvent.type != LET_RCVEND || !twoPhase)
servTries++;

if (servTries >= MAX_SERV_TRIES)
{
servx++;
stateM = 7;
}
else
stateM = 9;
break;
}

servTries = 0;

/* If point-multipoint system. */
if (curTopology == TP_MP)
{
stateM = 9;
break;
}
stateM = 12;
/* Fall through. */

case 12: /* Waiting to re-xmit slave data (broadcast group). */
/* If repeaters in system and already xmitted 2 data blocks. */
if (twoPhase && xmBlocks >= 2) return;

if (TransmitBroadcast (DB_MasterSlave))
stateM = 13;
return;

case 13: /* Re-transmitting slave data. */
stateM = (xCopiesLeftM == 0 ? 9 : 12);
break;

case 14: /* Waiting to initialize slave node. */
if (TransmitAck (servNode, 0)) stateM = 15;
return;

case 15: /* Transmitting ACK. */
if (linkEvent.type != LET_XMITEND)
{
stateM = 14;
break;
}
LinkStartReceive (&dataBuffers[DB_MasterSlave]);
stateM = 16;
return;

case 16: /* End of service for node. */
servx++;
stateM = 7;
break;

case 17: /* Waiting to complete slave service. */
if (TransmitAck (servNode, 0)) stateM = 16;
return;
}
}
}


/*******************************************************************
** Function: PPSlave
**
** Description: Control data transfers and scheduling for slave modem.
** A slave modem always operates in point-point mode.
** This routine should be called as part of the interrupt
** service associated with start of frame, end of transmit,
** or end of receive.
**
** On entry: Current unit is a slave.
*/
static void PPSlave
(
void
)
{
tLinkStat lstat; /* Status of link to master. */

if (masterPhase) return;

switch (linkEvent.type)
{
case LET_SOF:
dataSent = FALSE;
LinkStartReceive (&dataBuffers[DB_MasterSlave]);
break;

case LET_XMITEND:

/*DigitalOut (TP2, FALSE); /* reset error test point */

/* Transmitting fixed number of copies, and data sent. */
if (dataSent && !txErrorRetryS)
{
if (xCopiesLeftS != 0) xCopiesLeftS--;
if (xCopiesLeftS == 0)
{
LinkAckTransmittedData (masterNode);
SerialInTailAdvance (nXmitCharsS);
nXmitCharsS = 0;
}
}
dataSent = FALSE;
LinkStartReceive (&dataBuffers[DB_MasterSlave]);
break;

case LET_RCVEND:

/*DigitalOut (TP2, TRUE); /* set error test point */
dataSent = FALSE;

/* If transmitted data ACKed. */
if (linkEvent.info & LEI_ACKDATA)
{
LinkAckTransmittedData (masterNode);
SerialInTailAdvance (nXmitCharsS);
nXmitCharsS = 0;
xCopiesLeftS = 0;
}

/* If data block received. */
if (linkEvent.info & LEI_RCVDATA)
{
/* If multipoint topology and data source is this modem. */
if (curTopology != TP_PP &&
dataBuffers[DB_MasterSlave].dataRef == thisId)
{
LinkAcceptData ();
FlushDataBuffer (DB_MasterSlave);
}
/* If room in serial output buffer for data block. */
else if (SerialOutNEmpty() >= dataBuffers[DB_MasterSlave].dataLen)
{
LinkAcceptData ();
ScheduleDteTransfer (DB_MasterSlave);
RfRcvEnableStore (FALSE);
}
else
FlushDataBuffer (DB_MasterSlave);
}

/* Poll causes exit! Process other blocks before poll. */
if (linkEvent.info & LEI_POLL)
{
LinkSchedulePollResp (SerialInNAvail () != 0);
return;
}

GetLinkStatus (masterNode, &lstat);

/* If current unit has transmit permission. */
if (lstat.xmitPerm)
TransmitSlave (&lstat);
else
LinkStartReceive (&dataBuffers[DB_MasterSlave]);
break;
}
}


/*******************************************************************
** Function: TestRepeater
**
** Description: Receive user test data from relative master.
**
** On entry: Current unit is a repeater.
** System is in single-phase mode.
*/
static void TestRepeater
(
void
)
{
if (ppState != PPS_None)
ppState = PPS_None;
LinkStartReceive (&dataBuffers[DB_RepeaterDn0]);
}


/*******************************************************************
** Function: PP2Repeater
**
** Description: Control data transfers for repeater in point-point
** topology operating in two-phase mode. This routine
** should be called as part of the interrupt service at
** start of frame, end of transmit, or end of receive.
**
** On entry: Current unit is a repeater.
** System is in two-phase operation.
** Topology is point-point.
*/
static void PP2Repeater
(
void
)
{
/* If PP partner is among units serviced by this unit. */
if (ppNode != CALLX_UNUSED)
{
/* If not configured for point-point branch operation. */
if (ppState != PPS_Branch)
{
/* Flush data from other sources. */
FlushDataBuffer (DB_RepeaterUp0);
FlushDataBuffer (DB_RepeaterUp1);
nXmitCharsS = 0;
xCopiesLeftS = 0;
xmDataS = DB_RepeaterUp0;

SelectRepDownBufsS ();
SelectRepUpBufsS ();

/* Start of service cycle. */
fullCycle = TRUE;
endServ = FALSE;
endSlaveSrv = FALSE;
lastSrvData = FALSE;
ppState = PPS_Branch;
}
PP2RepeaterBranch ();
}

/* Else if this unit is the point-point partner. */
else if (ppBranch == 0)
{
if (ppState != PPS_Self)
{
FlushDataBuffer (DB_RepeaterUp0);
FlushDataBuffer (DB_RepeaterUp1);
nXmitCharsS = 0;
xCopiesLeftS = 0;
xmDataS = DB_SerialIn;

SelectRepDownBufsS ();
SelectRepUpBufsS ();

fullCycle = TRUE;
endServ = FALSE;
lastSrvData = TRUE;
ppState = PPS_Self;
}
PP2RepeaterSelf ();
}

/* Else point-point partner unknown to this unit. */
else
{
if (ppState != PPS_Idle)
{
FlushDataBuffer (DB_RepeaterUp0);
FlushDataBuffer (DB_RepeaterUp1);
nXmitCharsS = 0;
xCopiesLeftS = 0;

SelectRepDownBufsS ();
SelectRepUpBufsS ();

ppState = PPS_Idle;
}
PP2RepeaterIdle ();
}
}


/*******************************************************************
** Function: PP2RepeaterBranch
**
** Description: Control data transfers and scheduling for repeater
** servicing point-point partner.
**
** On entry: Current unit is a repeater.
** Topology is point-point.
** System is operating in two-phase mode.
** PP partner is in call list.
** Receive and transmit buffer selectors have been initialized.
*/
static void PP2RepeaterBranch
(
void
)
{
if (masterPhase)
PP2RepeaterBrM ();
else
PP2RepeaterBrS ();
}


/*******************************************************************
** Function: PP2RepeaterBrM
**
** Description: Control data transfers and scheduling for repeater
** servicing point-point partner, in master phase.
**
** On entry: Current unit is a repeater.
** Topology is point-point.
** RF channel is in master phase.
** PP partner is in call list.
*/
static void PP2RepeaterBrM
(
void
)
{
if (pdState == PDS_Sync) return;

switch (linkEvent.type)
{
case LET_SOF:
dataSent = FALSE;
xmBlocks = 0;
masterReqResp = FALSE;

SelectRepDownBufsM ();
SelectRepUpBufsM ();

AdjustDataPacing ();
TransmitPPRepeaterM ();
break;

case LET_XMITEND:
/* If transmitting a fixed number of copies and data sent. */
if (dataSent && !txErrorRetryM)
{
if (xCopiesLeftM != 0) xCopiesLeftM--;
if (xCopiesLeftM == 0)
{
LinkAckTransmittedData (ppBranch);
DiscardBufferData (xmDataM, nXmitCharsM);
nXmitCharsM = 0;
xmBlocks++;
SelectRepDownBufsM ();
}
}

dataSent = FALSE;

if (masterReqResp)
LinkStartReceive (&dataBuffers[rcvDataM]);
else
{
AdjustDataPacing ();
TransmitPPRepeaterM ();
}
break;

case LET_RCVEND:
dataSent = FALSE;
masterReqResp = FALSE;

/* If transmitted data ACKed. */
if (linkEvent.info & LEI_ACKDATA)
{
LinkAckTransmittedData (ppBranch);
DiscardBufferData (xmDataM, nXmitCharsM);
nXmitCharsM = 0;
xCopiesLeftM = 0;
xmBlocks++;
SelectRepDownBufsM ();
}

/* If data block received. */
if ((linkEvent.info & LEI_RCVDATA) && rcvDataM != DB_Auxiliary)
{
/* If data from point-point partner. */
if (callList[ppNode].id == dataBuffers[rcvDataM].dataRef)
{
LinkAcceptData ();
SelectRepUpBufsM ();
}
else
{
ppBranch = CALLX_UNUSED;
FlushDataBuffer (rcvDataM);
}
}

/* If relative slave has signalled end of service. */
if (ppBranch != CALLX_UNUSED && (linkEvent.info & LEI_ENDDATA))
{
endSlaveSrv = TRUE;
ackEndServ = TRUE;
}

AdjustDataPacing ();
TransmitPPRepeaterM ();
break;
}
}


/*******************************************************************
** Function: PP2RepeaterBrS
**
** Description: Control data transfers and scheduling for repeater
** servicing point-point partner, in slave phase.
**
** On entry: Current unit is a repeater.
** Topology is point-point.
** RF channel is in slave phase.
** PP partner is in call list.
*/
static void PP2RepeaterBrS
(
void
)
{
tLinkStat lstat; /* Status of RF link with master. */

switch (linkEvent.type)
{
case LET_SOF:
/* If powerdown sync point restart service cycle. */
if (pdState == PDS_Sync)
{
endServ = FALSE;
endSlaveSrv = FALSE;
lastSrvData = FALSE;
}
dataSent = FALSE;

SelectRepDownBufsS ();
SelectRepUpBufsS ();

LinkStartReceive (&dataBuffers[rcvDataS]);
break;

case LET_XMITEND:
/* If transmitting a fixed number of copies and data sent. */
if (dataSent && !txErrorRetryS)
{
if (xCopiesLeftS != 0) xCopiesLeftS--;
if (xCopiesLeftS == 0)
{
LinkAckTransmittedData (masterNode);
DiscardBufferData (xmDataS, nXmitCharsS);
nXmitCharsS = 0;
SelectRepUpBufsS ();
}
}

/* If end of slave service. */
if (endSlaveSrv)
{
bit empty0 = (dataBuffers[DB_RepeaterUp0].dataLen == 0);
bit empty1 = (dataBuffers[DB_RepeaterUp1].dataLen == 0);

endServ = empty0 && empty1;
lastSrvData = empty0 || empty1;
}

dataSent = FALSE;
LinkStartReceive (&dataBuffers[rcvDataS]);
break;

case LET_RCVEND:
dataSent = FALSE;

if (linkEvent.info & LEI_ACKDATA)
{
LinkAckTransmittedData (masterNode);
DiscardBufferData (xmDataS, nXmitCharsS);
nXmitCharsS = 0;
xCopiesLeftS = 0;
SelectRepUpBufsS ();
}

/* If end of slave service. */
if (endSlaveSrv)
{
bit empty0 = (dataBuffers[DB_RepeaterUp0].dataLen == 0);
bit empty1 = (dataBuffers[DB_RepeaterUp1].dataLen == 0);

endServ = empty0 && empty1;
lastSrvData = empty0 || empty1;
}

/* If data block received. */
if ((linkEvent.info & LEI_RCVDATA) && rcvDataS != DB_Auxiliary)
{
LinkAcceptData ();
SelectRepDownBufsS ();
}

/* If master acknowledged end of service. */
if (linkEvent.info & LEI_ENDDATA)
{
endServ = FALSE;
endSlaveSrv = FALSE;
lastSrvData = FALSE;
}

/* If point-point branch poll received. */
if (linkEvent.info & LEI_BRPOLL)
{
/* Flush data from other sources. */
FlushDataBuffer (DB_RepeaterUp0);
FlushDataBuffer (DB_RepeaterUp1);
nXmitCharsS = 0;
xCopiesLeftS = 0;

SelectRepUpBufsS ();

/* Identify unit as PP branch. */
TransmitPPConfig (masterNode);

return;
}

GetLinkStatus (masterNode, &lstat);

/* If current unit has permission to transmit. */
if (lstat.xmitPerm)
TransmitPPRepeaterS (&lstat);
else
LinkStartReceive (&dataBuffers[rcvDataS]);
break;
}
}


/*******************************************************************
** Function: PP2RepeaterIdle
**
** Description: Control data transfers and scheduling for repeater in
** point-point topology which is not part of the PP link.
** Maintains contact/sync with relative master; transmits
** sync to relative slaves.
**
** On entry: Current unit is a repeater.
** Topology is point-point.
** System is operating in two-phase mode.
** Receive and transmit buffer selectors have been initialized.
** PP partner is not this unit, or any unit serviced by
** this unit.
*/
static void PP2RepeaterIdle
(
void
)
{
if (masterPhase)
{
if (pdState == PDS_Sync) return;

/* Transmit sync + current point-point configuration. */
if (linkEvent.type == LET_SOF)
TransmitPPConfig (masterNode);

CheckDteTransfer ();
}
else
{
FlushDataBuffer (DB_RepeaterDn0);

/* If point-point branch poll received. */
if (linkEvent.info & LEI_BRPOLL)
{
/* Notify master: wrong branch. */
TransmitPPConfig (masterNode);
return;
}

LinkStartReceive (&dataBuffers[DB_RepeaterDn0]);
}
}


/*******************************************************************
** Function: PP2RepeaterSelf
**
** Description: Control data transfers and scheduling for repeater in
** point-point topology which is the PP partner.
**
** On entry: Current unit is a repeater.
** Topology is point-point.
** System is operating in two-phase mode.
** PP partner is this unit.
** Receive and transmit buffer selectors have been initialized.
*/
static void PP2RepeaterSelf
(
void
)
{
tLinkStat lstat; /* Status of link to master. */

if (masterPhase)
{
if (pdState == PDS_Sync) return;

/* Transmit sync + current point-point configuration. */
if (linkEvent.type == LET_SOF)
TransmitPPConfig (masterNode);
}
else /* Slave phase. */
{
switch (linkEvent.type)
{
case LET_SOF:
dataSent = FALSE;
CheckDteTransfer ();
SelectRepDownBufsS ();
LinkStartReceive (&dataBuffers[rcvDataS]);
break;

case LET_XMITEND:
/* Transmitting fixed number of copies, and data sent. */
if (dataSent && !txErrorRetryS)
{
if (xCopiesLeftS != 0) xCopiesLeftS--;
if (xCopiesLeftS == 0)
{
LinkAckTransmittedData (masterNode);
DiscardBufferData (xmDataS, nXmitCharsS);
nXmitCharsS = 0;
}
}
dataSent = FALSE;
CheckDteTransfer ();
SelectRepDownBufsS ();
LinkStartReceive (&dataBuffers[rcvDataS]);
break;

case LET_RCVEND:
dataSent = FALSE;

/* If point-point branch poll received. */
if (linkEvent.info & LEI_BRPOLL)
{
/* Flush data from other sources. */
FlushDataBuffer (DB_RepeaterUp0);
FlushDataBuffer (DB_RepeaterUp1);
nXmitCharsS = 0;
xCopiesLeftS = 0;

SelectRepUpBufsS ();

/* Identify unit as PP branch. */
TransmitPPConfig (masterNode);

return;
}

/* If transmitted data block ACKed. */
if (linkEvent.info & LEI_ACKDATA)
{
LinkAckTransmittedData (masterNode);
DiscardBufferData (xmDataS, nXmitCharsS);
nXmitCharsS = 0;
xCopiesLeftS = 0;
}

if ((linkEvent.info & LEI_RCVDATA) && rcvDataS != DB_Auxiliary)
{
LinkAcceptData ();
ScheduleDteTransfer (rcvDataS);
}

CheckDteTransfer ();
SelectRepDownBufsS ();
GetLinkStatus (masterNode, &lstat);

/* If current unit has transmit permission. */
if (lstat.xmitPerm)
TransmitPPRepeaterS (&lstat);
else
LinkStartReceive (&dataBuffers[rcvDataS]);
break;
}
}
}


/*******************************************************************
** Function: MPRepeater
**
** Description: Control data transfers and scheduling for repeater in
** multipoint topology. This routine should be called as
** part of the interrupt service associated with start of
** frame, end of transmit, or end of receive.
**
** On entry: Current topology is point-multipoint or broadcast group.
** Current unit is a repeater.
** System is in two-phase operation.
*/
static void MPRepeater
(
void
)
{
/* If necessary, initialize for multipoint mode. */
if (ppState != PPS_None)
{
SelectRepDownBufsS ();
SelectRepUpBufsS ();

/* Start of service cycle. */
xmDataS = DB_SerialIn;
fullCycle = TRUE;
endServ = FALSE;
endSlaveSrv = FALSE;
lastSrvData = FALSE;
ppState = PPS_None;
}

if (masterPhase)
MPRepeaterM ();
else
MPRepeaterS ();
}


/*******************************************************************
** Function: MPRepeaterM
**
** Description: Control master-phase data transfers and scheduling for
** repeater in multipoint topology. This routine should
** be called as part of the interrupt service associated
** with start of frame, end of transmit, or end of receive.
**
** On entry: Current topology is point-multipoint or broadcast group.
** Current unit is a repeater.
** Channel is in master phase.
*/
static void MPRepeaterM
(
void
)
{
if (pdState == PDS_Sync) return;

/* If start of frame, reset status. */
if (linkEvent.type == LET_SOF)
{
if (rcvStatus == MES_Done) rcvStatus = MES_Suspended;
if (xmStatus == MES_Done) xmStatus = MES_Suspended;
}

while (rcvStatus != MES_Done || xmStatus != MES_Done)
{
if (rcvStatus != MES_Active && xmStatus != MES_Done)
xmStatus = MPRepeaterMXmit ();

if (xmStatus == MES_Active) return;

if (rcvStatus != MES_Done)
rcvStatus = MPRepeaterMRcv ();

if (rcvStatus == MES_Active) return;
}

/* If no transmit yet, send sync. */
if (linkEvent.type == LET_SOF) TransmitSync ();
}


/*******************************************************************
** Function: MPRepeaterS
**
** Description: Control slave-phase data transfers for repeater in
** multipoint topology. This routine should be called
** as part of the interrupt service associated with start
** of frame, end of transmit, or end of receive.
**
** On entry: Current topology is point-multipoint or broadcast group.
** Current unit is a repeater.
** RF channel is in slave phase.
*/
static void MPRepeaterS
(
void
)
{
tLinkStat lstat; /* Status of link with relative master. */
static bit pdServDone; /* Powerdown service cycle initiated. */

switch (linkEvent.type)
{
case LET_SOF:
/* If powerdown sync point, complete full service cycle. */
if (pdState == PDS_Sync)
{
fullCycle = (xmDataS == DB_SerialIn);
pdServDone = FALSE;
}

dataSent = FALSE;
SelectRepDownBufsS ();
SelectRepUpBufsS ();
LinkStartReceive (&dataBuffers[rcvDataS]);
break;

case LET_XMITEND:
/* Transmitting fixed number of copies, and data sent. */
if (dataSent && !txErrorRetryS)
{
if (xCopiesLeftS != 0) xCopiesLeftS--;
if (xCopiesLeftS == 0)
{
LinkAckTransmittedData (masterNode);
DiscardBufferData (xmDataS, nXmitCharsS);
dataLimit -= nXmitCharsS;
nXmitCharsS = 0;
SelectRepUpBufsS ();
}
}

/* If end of slave service. */
if (endSlaveSrv)
{
bit empty0 = (dataBuffers[DB_RepeaterUp0].dataLen == 0);
bit empty1 = (dataBuffers[DB_RepeaterUp1].dataLen == 0);

endServ = empty0 && empty1;
lastSrvData = empty0 || empty1;
}

/* If end of data from DTE, update source. */
if (xmDataS == DB_SerialIn && xCopiesLeftS == 0)
{
if (dataLimit <= 0 || GetBufferDataCount (DB_SerialIn) == 0)
{
xmDataS = DB_RepeaterUp0;
SelectRepUpBufsS ();
}
}

dataSent = FALSE;
LinkStartReceive (&dataBuffers[rcvDataS]);
break;

case LET_RCVEND:
dataSent = FALSE;

/* If transmitted data block ACKed. */
if (linkEvent.info & LEI_ACKDATA)
{
LinkAckTransmittedData (masterNode);
DiscardBufferData (xmDataS, nXmitCharsS);
dataLimit -= nXmitCharsS;
nXmitCharsS = 0;
xCopiesLeftS = 0;

SelectRepUpBufsS ();
}

/* If end of slave service. */
if (endSlaveSrv)
{
bit empty0 = (dataBuffers[DB_RepeaterUp0].dataLen == 0);
bit empty1 = (dataBuffers[DB_RepeaterUp1].dataLen == 0);

endServ = empty0 && empty1;
lastSrvData = empty0 || empty1;
}

/* If end of data from DTE, update source. */
if (xmDataS == DB_SerialIn && xCopiesLeftS == 0)
{
if (dataLimit <= 0 || GetBufferDataCount (DB_SerialIn) == 0)
{
xmDataS = DB_RepeaterUp0;
SelectRepUpBufsS ();
}
}

if ((linkEvent.info & LEI_RCVDATA) && rcvDataS != DB_Auxiliary)
{
LinkAcceptData ();
if (dataBuffers[rcvDataS].dataRef != thisId)
ScheduleDteTransfer (rcvDataS);
SelectRepDownBufsS ();
}

/* If end of service cycle explicitly or implicitly ACKed. */
if (endServ &&
(linkEvent.info & (LEI_ENDDATA | LEI_POLL) || !fullCycle))
{
xmDataS = DB_SerialIn; /* Transmit DTE data. */
dataLimit = MS_XFER_LIM; /* Reset DTE transfer limit. */
fullCycle = TRUE; /* Restart service cycle. */
endServ = FALSE;
endSlaveSrv = FALSE;
lastSrvData = FALSE;
}

if (linkEvent.info & LEI_POLL)
{
/*
** Request xmit permission if data avail or service cycle
** not completed since powerdown sync point.
*/
LinkSchedulePollResp (GetBufferDataCount (xmDataS) != 0 ||
!pdServDone);
pdServDone = TRUE;
return;
}

GetLinkStatus (masterNode, &lstat);

/* If current unit has transmit permission. */
if (lstat.xmitPerm)
TransmitPPRepeaterS (&lstat);
else
LinkStartReceive (&dataBuffers[rcvDataS]);
break;
}
}


/*******************************************************************
** Function: MPRepeaterMRcv
**
** Description: Service relative slaves for repeater in multipoint
** topology.
**
** On entry: Current unit is repeater.
** Current topology is multipoint or broadcast group.
** Channel is in master phase.
**
** On exit: If receive or transmit initiated, returns MES_Active.
** If operation complete for this frame, returns MES_Done.
** If operation did not terminate properly before end of
** frame, returns MES_Suspended at start of next frame.
*/
static tMachExitStat MPRepeaterMRcv
(
void
)
{
/* If slave service not active. */
if (endSlaveSrv || xmDataS == DB_SerialIn) return (MES_Done);

switch (linkEvent.type)
{
case LET_SOF:
SelectRepUpBufsM ();
break;

case LET_RCVEND:
/* If data block received. */
if ((linkEvent.info & LEI_RCVDATA) && rcvDataM != DB_Auxiliary)
{
servLimit -= dataBuffers[rcvDataM].dataLen;
LinkAcceptData ();
SelectRepUpBufsM ();
}

/* If slave has signalled end of service cycle. */
if (linkEvent.info & LEI_ENDDATA)
{
ackEndServ = TRUE; /* ACK end of slave service cycle. */
servLimit = 0;
servTries = MAX_SERV_TRIES;
}
break;
}

while (TRUE)
{
switch (stateR)
{
case 0: /* Begin + end of slave service. */
if (nextPollx >= CALL_LIST_SIZE ||
localCalls[nextPollx] == CALLX_UNUSED)
{
nextPollx = 1; /* Relative master is 0. */
servx = 1;
endSlaveSrv = TRUE;
return (MES_Done);
}
stateR = 1;
/* Fall through. */

case 1: /* Waiting to transmit poll. */
if (linkEvent.type == LET_SOF)
{
TransmitPoll ();
stateR = 2;
return (MES_Active);
}
return (MES_Done);

case 2: /* Transmitting poll. */
if (linkEvent.type != LET_XMITEND)
{
stateR = 1;
return (MES_Suspended);
}
LinkStartReceive (&dataBuffers[DB_Auxiliary]);
stateR = 3;
return (MES_Active);

case 3: /* Receiving poll responses. */
if (linkEvent.type != LET_SOF)
{
LinkStartReceive (&dataBuffers[DB_Auxiliary]);
return (MES_Active);
}
stateR = 4;
return (MES_Suspended);

case 4: /* Decision: last polled node serviced. */
if (servx == nextPollx)
{
stateR = 0;
break;
}
servNode = localCalls[servx];
stateR = 5;
/* Fall through. */

case 5: /* Decision: polled node requires service. */
{
tLinkStat lstat; /* Status of link to slave. */

GetLinkStatus (servNode, &lstat);
/* If node does not require service. */
if (!lstat.initReq && !lstat.xmitReq)
{
servx++;
stateR = 4;
break;
}

/* If node has no data to transmit. */
if (!lstat.xmitReq)
{
stateR = 10;
break;
}

servLimit = (lstat.isRepeater ? REP_XFER_LIM : MS_XFER_LIM);
servTries = MAX_SERV_TRIES - 2;
stateR = 6;
/* Fall through. */
}

case 6: /* Servicing slave with data to transmit. */
/* If data transfer limit reached. */
if (servLimit <= 0)
{
stateR = 13;
break;
}
stateR = 7;
/* Fall through. */

case 7: /* Waiting to transmit ACK to solicit data. */
if (TransmitAck (servNode, GetBufferSize (rcvDataM)))
{
stateR = 8;
return (MES_Active);
}
return (MES_Done);

case 8: /* Transmitting ACK to solicit data. */
if (linkEvent.type != LET_XMITEND)
{
stateR = 7;
return (MES_Suspended);
}

/* If no receive buffer available. */
if (rcvDataM == DB_Auxiliary)
{
stateR = 7;
return (MES_Done);
}

LinkStartReceive (&dataBuffers[rcvDataM]);
stateR = 9;
return (MES_Active);

case 9: /* Receiving data from slave. */
/* If no data received. */
if (!(linkEvent.info & LEI_RCVDATA))
{
/* If receive failed. */
if (linkEvent.type != LET_RCVEND)
{
servTries++;
if (servTries >= MAX_SERV_TRIES)
{
servx++;
stateR = 4;
}
else
stateR = 7;
return (MES_Suspended);
}
}
else /* Data received: setup for next receive. */
{
SelectRepUpBufsM ();
servTries = 0;
}

stateR = 6;
break;

case 10: /* Waiting to transmit ACK to initialize node. */
if (TransmitAck (servNode, 0))
{
stateR = 11;
return (MES_Active);
}
return (MES_Done);

case 11: /* Transmitting ACK. */
if (linkEvent.type != LET_XMITEND)
{
stateR = 10;
return (MES_Suspended);
}
LinkStartReceive (&dataBuffers[DB_Auxiliary]);
stateR = 12;
return (MES_Active);

case 12: /* End of service this slave. */
servx++;
stateR = 4;
return (MES_Suspended);

case 13: /* End of service this slave. */
if (TransmitAck (servNode, 0))
{
stateR = 12;
return (MES_Active);
}
return (MES_Done);
}
}
}


/*******************************************************************
** Function: MPRepeaterMXmit
**
** Description: Broadcast downstream data for repeater. If initial
** transmit data buffer is empty, function exits, and
** no transmission is made.
**
** On entry: Current unit is a repeater.
** RF channel is in master phase.
** xmDataM selects initial transmit data buffer.
**
** On exit: If transmit operation initiated, returns MES_Active.
** If no transmit possible (no more data or insufficient
** time in frame), returns MES_Done.
*/
static tMachExitStat MPRepeaterMXmit
(
void
)
{
switch (linkEvent.type)
{
case LET_SOF:
SelectRepDownBufsM ();
stateX = 0;
break;

case LET_XMITEND:
/* All transmitted packets contain data. */
if (xCopiesLeftM != 0) xCopiesLeftM--;
if (xCopiesLeftM == 0)
{
LinkAckTransmittedData (CALLX_UNUSED);
FlushDataBuffer (xmDataM); /* Transmits entire buffer. */
nXmitCharsM = 0;
}
break;

case LET_RCVEND:
break;
}

AdjustDataPacing ();
dataSent = FALSE;

while (TRUE)
{
switch (stateX)
{
case 0:
if (GetBufferDataCount (xmDataM) == 0) return (MES_Done);
stateX = 1;
/* Fall through. */

case 1:
if (TransmitBroadcastR (xmDataM))
{
stateX = 2;
return (MES_Active);
}
return (MES_Done);

case 2:
if (xCopiesLeftM != 0)
{
stateX = 1;
break;
}
stateX = 3;
/* Fall through. */

case 3:
SelectRepDownBufsM ();

if (GetBufferDataCount (xmDataM) == 0) return (MES_Done);
stateX = 4;
/* Fall through. */

case 4:
if (TransmitBroadcastR (xmDataM))
{
stateX = 5;
return (MES_Active);
}
return (MES_Done);

case 5:
if (xCopiesLeftM != 0)
{
stateX = 4;
break;
}
return (MES_Done);
}
}
}


/*******************************************************************
** Function: TransmitPP1Master
**
** Description: Transmit packet for master in single-phase,
** point-point mode.
**
** On entry: Current unit is operating in master phase.
**
** On exit: If time in current frame, packet transmit started.
** If packet had room for data and data available,
** packet includes data block. Packet always includes
** an ACK block.
*/
static void TransmitPP1Master
(
void
)
{
tLinkStat lstat; /* Status of link to point-point slave. */
byte navail; /* Space available in receive buffer. */
int dc; /* # data chars that can be transmitted. */

dc = GetCharsInFrame ();

/* If not enough time to transmit ACK. */
if (dc < NCHARS_IN_TICY (TIME_SEND_ACK1M)) return;

/* Always leave time for ACK if transmitting data. */
dc -= NCHARS_IN_TICY (TIME_SEND_DATA1M) +
NCHARS_IN_TICY (TIME_SEND_ACK1S);

GetLinkStatus (ppNode, &lstat);
navail = GetBufferSize (DB_MasterSlave);

LinkSetHeader (ppNode);
LinkFormatAck (navail);

masterReqResp = (navail != 0 || !lstat*******);

/* If time to transmit data and slave is ready. */
if (dc > 0 &&
(!txErrorRetryM || lstat*******) &&
lstat.ravail != 0)
{
/* If no current xmit data, get new data block. */
if (nXmitCharsM == 0)
{
if (dc > lstat.ravail) dc = lstat.ravail;
if (dc > maxPacketSize) dc = maxPacketSize;

nXmitCharsM = GetBufferData (xmDataM, dc, &dataDescM);
if (nXmitCharsM != 0) xCopiesLeftM = packetCopiesM;
}

if (nXmitCharsM != 0 && dc >= nXmitCharsM)
{
LinkFormatData ((xCopiesLeftM == 1 && !txErrorRetryM),
txErrorRetryM, &dataDescM);
dataSent = TRUE;
}
}
LinkStartTransmit ();
}


/*******************************************************************
** Function: TransmitPP2Master
**
** Description: Transmit packet for master in two-phase,
** point-point mode.
**
** On entry: Current unit is operating in master phase.
**
** On exit: If time in current frame, packet transmit started.
** If block limit for frame not reached, packet had room
** for data, and data available, packet includes data
** block. Packet always includes an ACK block.
*/
static void TransmitPP2Master
(
void
)
{
tLinkStat lstat; /* Status of link to point-point slave. */
byte navail; /* Space available in receive buffer. */
int dc; /* # data chars that can be transmitted. */

/* If PP branch is undefined. */
if (ppBranch == CALLX_UNUSED)
{
masterReqResp = TransmitPPConfig (CALLX_UNUSED);
return;
}

dc = GetCharsInFrame ();

/* If not enough time to transmit ACK. */
if (dc < NCHARS_IN_TICY (TIME_SEND_ACK2RM)) return;

/* Always leave time for ACK if transmitting data. */
dc -= NCHARS_IN_TICY (TIME_SEND_DATA2M) +
NCHARS_IN_TICY (TIME_SEND_ACK2RS);

GetLinkStatus (ppBranch, &lstat);

navail = GetBufferSize (DB_MasterSlave);

LinkSetHeader (ppBranch);
LinkFormatAck (navail);
if (ackEndServ)
{
LinkSignalEndServ ();
ackEndServ = FALSE;
}

masterReqResp = (navail != 0 || !lstat*******);

/* If time to transmit data and slave ready. */
if (dc > 0 &&
xmBlocks < 2 &&
(!txErrorRetryM || lstat*******) &&
lstat.ravail != 0)
{
/* If no current xmit data, get new data block. */
if (nXmitCharsM == 0)
{
if (dc > lstat.ravail) dc = lstat.ravail;
if (dc > maxPacketSize) dc = maxPacketSize;

nXmitCharsM = GetBufferData (xmDataM, dc, &dataDescM);
if (nXmitCharsM != 0) xCopiesLeftM = packetCopiesM;
}

if (nXmitCharsM != 0 && dc >= nXmitCharsM)
{
LinkFormatData ((xCopiesLeftM == 1 && !txErrorRetryM),
txErrorRetryM, &dataDescM);
dataSent = TRUE;
}
}

if (!dataSent) LinkFormatPPConfig ();

LinkStartTransmit ();
}


/*******************************************************************
** Function: TransmitSlave
**
** Description: Transmit packet for slave modem.
**
** On entry: Current unit is slave.
** Current unit has permission to transmit.
**
** On exit: If time in current frame, packet transmit started.
** If packet had room for data and data available,
** packet includes data block. Packet always includes
** an ACK block.
*/
static void TransmitSlave
(
tLinkStat xdata* lstat /* Status of link with master. */
)
{
int dc; /* # data chars that can be transmitted. */

dc = GetCharsInFrame ();

if (twoPhase)
{
/* If not enough time to transmit ACK. */
if (dc < NCHARS_IN_TICY (TIME_SEND_ACK2RS)) return;

/* If two-phase mode, leave time for ACK. */
dc -= NCHARS_IN_TICY (TIME_SEND_DATA2S) +
NCHARS_IN_TICY (TIME_SEND_ACK2RM);
}
else
{
/* If not enough time to transmit ACK. */
if (dc < NCHARS_IN_TICY (TIME_SEND_ACK1S)) return;

dc -= NCHARS_IN_TICY (TIME_SEND_DATA1S);
}

LinkSetHeader (masterNode);
LinkFormatAck (GetBufferSize (DB_MasterSlave));

if (dc > 0 &&
(!txErrorRetryS || lstat->online) &&
lstat->ravail != 0)
{
/* If no current xmit data, get new data block. */
if (nXmitCharsS == 0)
{
if (dc > lstat->ravail) dc = lstat->ravail;
if (dc > maxPacketSize) dc = maxPacketSize;

nXmitCharsS = GetBufferData (xmDataS, dc, &dataDescS);
if (nXmitCharsS != 0) xCopiesLeftS = packetCopiesS;
}

/* If data available and time in frame. */
if (nXmitCharsS != 0 && dc >= nXmitCharsS)
{
LinkFormatData ((xCopiesLeftS == 1 && !txErrorRetryS),
txErrorRetryS, &dataDescS);
dataSent = TRUE;
}
}

/* If end of available data, signal end of service cycle. */
if (SerialInNAvail () == nXmitCharsS) LinkSignalEndServ ();

LinkStartTransmit ();
}


/*******************************************************************
** Function: TransmitPPRepeaterM
**
** Description: Transmit packet for repeater in master-phase,
** in point-point topology.
**
** On entry: Current unit is repeater.
** RF channel is in master phase.
**
** On exit: If time in current frame, packet transmit initiated.
** If room for data in packet and data available, packet
** includes data block. Packet always includes an ACK
** block.
*/
static void TransmitPPRepeaterM
(
void
)
{
tLinkStat lstat; /* Status of link to point-point branch. */
byte navail; /* Space available in receive buffer. */
int dc; /* # data chars that can be transmitted. */

/* If PP branch is undefined. */
if (ppBranch == CALLX_UNUSED)
{
masterReqResp = TransmitPPConfig (CALLX_UNUSED);
return;
}

dc = GetCharsInFrame ();

/* If not enough time to transmit ACK. */
if (dc < NCHARS_IN_TICY (TIME_SEND_ACK2RM)) return;

/* Always leave time for ACK if transmitting data. */
dc -= NCHARS_IN_TICY (TIME_SEND_DATA2Rd) +
NCHARS_IN_TICY (TIME_SEND_ACK2RS);

GetLinkStatus (ppBranch, &lstat);

navail = GetBufferSize (rcvDataM);

LinkSetHeader (ppBranch);
LinkFormatAck (navail);
if (ackEndServ)
{
LinkSignalEndServ ();
ackEndServ = FALSE;
}

masterReqResp = (navail != 0 || !lstat*******);

if (dc > 0 &&
(!txErrorRetryM || lstat*******) &&
lstat.ravail != 0)
{
/* If no current xmit data, get new data block. */
if (nXmitCharsM == 0)
{
if (dc > lstat.ravail) dc = lstat.ravail;

nXmitCharsM = GetBufferData (xmDataM, dc, &dataDescM);
if (nXmitCharsM != 0) xCopiesLeftM = packetCopiesM;
}

if (nXmitCharsM != 0 && dc >= nXmitCharsM)
{
LinkFormatData ((xCopiesLeftM == 1 && !txErrorRetryM),
txErrorRetryM, &dataDescM);
dataSent = TRUE;
}
}

if (!dataSent) LinkFormatPPConfig ();

LinkStartTransmit ();
}


/*******************************************************************
** Function: TransmitPPRepeaterS
**
** Description: Transmit packet for repeater in slave-phase,
** in point-point topology.
**
** On entry: Current unit is repeater.
** RF channel is in slave phase.
**
** On exit: If time in current frame, packet transmit initiated.
** If room for data in packet and data available, packet
** includes data block. Packet always includes an ACK
** block.
*/
static void TransmitPPRepeaterS
(
tLinkStat xdata* lstat /* Status of link to master. */
)
{
int dc; /* # data chars that can be transmitted. */

dc = GetCharsInFrame ();

/* If not enough time to transmit ACK. */
if (dc < NCHARS_IN_TICY (TIME_SEND_ACK2RS)) return;

/* Always leave time for ACK when data transmitted. */
dc -= NCHARS_IN_TICY (TIME_SEND_DATA2Ru) +
NCHARS_IN_TICY (TIME_SEND_ACK2RM);

LinkSetHeader (masterNode);
LinkFormatAck (GetBufferSize (rcvDataS));

if (dc > 0 &&
(!txErrorRetryS || lstat->online) &&
lstat->ravail != 0)
{
/* If no current xmit data, get new data block. */
if (nXmitCharsS == 0)
{
if (dc > lstat->ravail) dc = lstat->ravail;
if (xmDataS == DB_SerialIn && dc > maxPacketSize)
dc = maxPacketSize;

nXmitCharsS = GetBufferData (xmDataS, dc, &dataDescS);
if (nXmitCharsS != 0) xCopiesLeftS = packetCopiesS;
}

if (nXmitCharsS != 0 && dc >= nXmitCharsS)
{
LinkFormatData ((xCopiesLeftS == 1 && !txErrorRetryS),
txErrorRetryS, &dataDescS);
dataSent = TRUE;
}
}

/* If end of service cycle, or transmitting last data. */
if (fullCycle &&
(endServ ||
(lastSrvData && GetBufferDataCount (xmDataS) == nXmitCharsS)))
{
LinkSignalEndServ ();
}

LinkStartTransmit ();
}


/*******************************************************************
** Function: TransmitAck
**
** Description: Transmit an ACK block for a relative master.
** Does not reserve time in frame for response.
**
** On entry: None.
**
** On exit: If time in frame, transmit of ACK has been initiated,
** returns TRUE. Else, returns FALSE.
*/
static bit TransmitAck
(
tCallx dest, /* Call list index of destination node. */
byte navail /* Space available in receive buffer. */
)
{
if (twoPhase)
{
if (GetCharsInFrame () < NCHARS_IN_TICY (TIME_SEND_ACKTA2))
return (FALSE);
}
else
{
if (GetCharsInFrame () < NCHARS_IN_TICY (TIME_SEND_ACKTA1))
return (FALSE);
}

LinkSetHeader (dest);
LinkFormatAck (navail);
if (ackEndServ)
{
LinkSignalEndServ ();
ackEndServ = FALSE;
}

LinkStartTransmit ();
return (TRUE);
}


/*******************************************************************
** Function: TransmitBroadcast
**
** Description: Transmit a broadcast data block.
**
** On entry: RF channel is in master phase.
**
** On exit: If data available and time in frame for transmit,
** transmit initiated, returns TRUE. Else, returns FALSE.
*/
static bit TransmitBroadcast
(
tDataBufSelector db /* Source buffer for broadcast data. */
)
{
int dc; /* # data chars that can be transmitted. */

dc = GetCharsInFrame () - NCHARS_IN_TICY (TIME_SEND_BROADM);

/* If not enough time to transmit. */
if (dc < 0) return (FALSE);

LinkSetHeader (CALLX_UNUSED);

/* If no current xmit data, get new data block. */
if (nXmitCharsM == 0)
{
if (twoPhase && dc > REP_DOWN_DATA_LEN)
dc = REP_DOWN_DATA_LEN;
if (db == DB_SerialIn && dc > maxPacketSize)
dc = maxPacketSize;

nXmitCharsM = GetBufferData (db, dc, &dataDescM);
if (nXmitCharsM != 0) xCopiesLeftM = packetCopiesM;
}

if (nXmitCharsM != 0 && dc >= nXmitCharsM)
{
LinkFormatData ((xCopiesLeftM == 1), FALSE, &dataDescM);
dataSent = TRUE;
LinkStartTransmit ();
return (TRUE);
}

return (FALSE);
}


/*******************************************************************
** Function: TransmitBroadcastR
**
** Description: Transmit a broadcast data block for repeater.
**
** On entry: RF channel is in master phase.
**
** On exit: If data available and time in frame to transmit entire
** buffer, transmit initiated, returns TRUE. Else,
** returns FALSE.
*/
static bit TransmitBroadcastR
(
tDataBufSelector db /* Source buffer for broadcast data. */
)
{
int dc; /* # data chars that can be transmitted. */

dc = GetCharsInFrame () - NCHARS_IN_TICY (TIME_SEND_BROADR);

/* If not enough time to transmit anything. */
if (dc < 0) return (FALSE);

/* If not enough time to transmit buffer. */
if (dc < GetBufferDataCount (db)) return (FALSE);

LinkSetHeader (CALLX_UNUSED);

/* If no current xmit data, get new data block. */
if (nXmitCharsM == 0)
{
nXmitCharsM = GetBufferData (db, dc, &dataDescM);
if (nXmitCharsM != 0) xCopiesLeftM = packetCopiesM;
}

if (nXmitCharsM != 0 && dc >= nXmitCharsM)
{
LinkFormatData ((xCopiesLeftM == 1), FALSE, &dataDescM);
dataSent = TRUE;
LinkStartTransmit ();
return (TRUE);
}

return (FALSE);
}


/*******************************************************************
** Function: TransmitPoll
**
** Description: Transmit a poll message.
**
** On entry: nextPollx contains the index of the first local node
** (in localCalls list) to include in the poll.
** localCalls has been initialized.
**
** On exit: Transmit of poll message has been initiated.
** nextPollx contains the index of the local node following
** the last node included in the poll.
*/
static void TransmitPoll
(
void
)
{
tCallx pollEntries[MAX_POLL_IDS]; /* Call indices of poll nodes. */
byte pe; /* Index of poll entry. */

for (pe = 0; pe < MAX_POLL_IDS; pe++)
{
if (nextPollx >= CALL_LIST_SIZE ||
localCalls[nextPollx] == CALLX_UNUSED)
{
pollEntries[pe] = CALLX_UNUSED;
}
else
{
pollEntries[pe] = localCalls[nextPollx];
nextPollx++;
}
}
LinkSetHeader (CALLX_UNUSED);
LinkFormatPoll (pollEntries);
LinkStartTransmit ();
}


/*******************************************************************
** Function: TransmitPPConfig
**
** Description: Transmit a point-point configuration block.
**
** On entry: ppNode != CALLX_UNUSED.
**
** On exit: If sufficient time in frame to transmit PP config block
** transmit initiated, returns TRUE. Else, returns FALSE.
*/
static bit TransmitPPConfig
(
tCallx dest /* Call list index of destination node. */
)
{
if (GetCharsInFrame () < NCHARS_IN_TICY (TIME_SEND_ACK2RM))
return (FALSE);

LinkSetHeader (dest);
LinkFormatPPConfig ();
LinkStartTransmit ();

return (TRUE);
}


/*******************************************************************
** Function: TransmitSync
**
** Description: Transmit a sync block.
**
** On entry: It is start of frame.
**
** On exit: Transmit of sync block has been initiated.
*/
static void TransmitSync
(
void
)
{
LinkSetHeader (CALLX_UNUSED);
LinkStartTransmit ();
}


/*******************************************************************
** Function: ScheduleDteTransfer
**
** Description: Add data block to list of blocks being transferred to DTE.
**
** On entry: db != DB_None.
**
** On exit: If there was no room in the transfer list for another
** data block, no transfer has been scheduled. Else, the
** data block has been setup for transfer to the DTE.
*/
static void ScheduleDteTransfer
(
tDataBufSelector db /* Buffer containing data for DTE. */
)
{
/* Source 0 is transferred first, if it contains data . To maintain */
/* the data block sequence, source 0 should select the "older" data. */
/* If the data from source 1 is currently being transferred, it is */
/* safe to use source 0 for the new block. */

/* If neither DTE transfer source contains data. */
if (dteData0 == DB_None && dteData1 == DB_None)
{
dteData0 = db;
datap0 = dataBuffers[db].datap;
dataLen0 = dataBuffers[db].dataLen;
breakx0 = dataBuffers[db].breakx;
dataBuffers[db].xstat = DBX_Pending;
}

/* If source 1 contains data and source 0 is unused. */
else if (dteData1 != DB_None && dteData0 == DB_None)
{
/* If source 1 transfer not active. */
if (dataBuffers[dteData1].xstat != DBX_Active)
{
/* Schedule older data to transfer first. */
dteData0 = dteData1;
datap0 = datap1;
dataLen0 = dataLen1;
breakx0 = breakx1;

/* Add new data to second transfer source. */
dteData1 = db;
datap1 = dataBuffers[db].datap;
dataLen1 = dataBuffers[db].dataLen;
breakx1 = dataBuffers[db].breakx;
}
else /* Data from source 1 currently being transferred. */
{
/* Source 0 won't be transferred until source 1 done. */
dteData0 = db;
datap0 = dataBuffers[db].datap;
dataLen0 = dataBuffers[db].dataLen;
breakx0 = dataBuffers[db].breakx;
}
dataBuffers[db].xstat = DBX_Pending;
}

/* If source 0 contains data and source 1 is unused. */
else if (dteData0 != DB_None && dteData1 == DB_None)
{
dteData1 = db;
datap1 = dataBuffers[db].datap;
dataLen1 = dataBuffers[db].dataLen;
breakx1 = dataBuffers[db].breakx;
dataBuffers[db].xstat = DBX_Pending;
}
}


/*******************************************************************
** Function: CheckDteTransfer
**
** Description: Check status of DTE transfer. If transfer is complete,
** flushes associated downstream buffer. Both transfer
** buffers are checked and flushed if necessary.
**
** On entry: If buffer contains data for DTE, either it has been
** scheduled for transfer, or transfer is complete.
**
** On exit: If either downstream buffer is not scheduled for DTE
** transfer, it has been flushed.
*/
static void CheckDteTransfer
(
void
)
{
if (dteData0 != DB_RepeaterDn0 && dteData1 != DB_RepeaterDn0)
FlushDataBuffer (DB_RepeaterDn0);
if (dteData0 != DB_RepeaterDn1 && dteData1 != DB_RepeaterDn1)
FlushDataBuffer (DB_RepeaterDn1);
}


/*******************************************************************
** Function: AdjustDataPacing
**
** Description: Adjust packet copies to resynchronize repeater data
** transmission with relative master. The data in both
** downstream buffers will be transmitted approximately
** equal times, and each buffer will be transmitted at
** least once. This routine should be called after any
** link event in master phase, when error retry is not
** being used.
**
** On entry: RF channel is in master phase.
** Transmit error retry is not active.
** Repeater only.
**
** On exit: Remaining transmit data copies have been adjusted to keep
** pace with relative master.
*/
static void AdjustDataPacing
(
void
)
{
tDataBufSelector buffer2; /* Second data buffer to transmit. */
int timeInFrame; /* Time remaining in current frame. */
byte timeXmit1; /* Time to transmit first buffer. */
byte timeXmit2; /* Time to transmit second buffer. */
byte copies1; /* Addl xmit copies of first buffer. */
static bit adjusted; /* Data pacing has been adjusted */

/* Data pacing is intrinsic to retry option. */
if (txErrorRetryM) return;

/* Adjust pacing once per frame. */
if (linkEvent.type == LET_SOF) adjusted = FALSE;

/*
** If pacing already adjusted this frame, or transmit copies has not
** been initialized, exit. (Adjustment is applied after copies set.)
*/
if (adjusted || xCopiesLeftM == 0) return;

/* Only adjust pacing if both downstream buffers contain data. */
if (dataBuffers[DB_RepeaterDn0].dataLen == 0 ||
dataBuffers[DB_RepeaterDn1].dataLen == 0)
{
return;
}

adjusted = TRUE;
copies1 = 0;

if (curTopology == TP_PP)
timeXmit1 = timeXmit2 = NCHARS_IN_TICY (TIME_SEND_DATA2Rd);
else
timeXmit1 = timeXmit2 = NCHARS_IN_TICY (TIME_SEND_BROADR);

if (xmDataM == DB_RepeaterDn0)
{
timeXmit1 += dataBuffers[DB_RepeaterDn0].dataLen;
timeXmit2 += dataBuffers[DB_RepeaterDn1].dataLen;
buffer2 = DB_RepeaterDn1;
}
else
{
timeXmit1 += dataBuffers[DB_RepeaterDn1].dataLen;
timeXmit2 += dataBuffers[DB_RepeaterDn0].dataLen;
buffer2 = DB_RepeaterDn0;
}

timeInFrame = GetCharsInFrame () -
(int) (packetCopiesM - xCopiesLeftM) * timeXmit2;

/* If time in frame for additional transmits. */
if (timeInFrame > 0)
{
int timeXmBoth = timeXmit1 + timeXmit2;

/* Allocate time for transmit both buffers. */
while (xCopiesLeftM > 0 && timeInFrame >= timeXmBoth)
{
timeInFrame -= timeXmBoth;
xCopiesLeftM--; /* Total copies remaining. */
copies1++; /* Addl copies of first buffer to xmit. */
}

/* One more copy of first buffer? */
if (xCopiesLeftM != 0 && timeInFrame >= timeXmit1) copies1++;
}

/* If no further transmits of first buffer. */
if (copies1 == 0)
{
FlushDataBuffer (xmDataM);

if (curTopology != TP_PP)
LinkAckTransmittedData (CALLX_UNUSED);
else if (ppNode != CALLX_UNUSED && ppBranch != CALLX_UNUSED)
LinkAckTransmittedData (ppBranch);

nXmitCharsM = 0;
xmDataM = buffer2; /* Select second buffer for transmit. */
}

xCopiesLeftM = copies1; /* Adjust copies first buffer. */
}


/*******************************************************************
** Function: SelectRepDownBufsS
**
** Description: Select downstream receive and transmit buffers for
** repeater in slave phase. If transmit error retry is
** not selected, data in one or both buffers at start of
** slave phase may be discarded to make buffer available
** for new (receive) data. If necessary, buffer containing
** older data block is discarded first.
**
** On exit: Downstream receive selector is set to available buffer,
** if it exists. If no buffer is available, receive selector
** is set to DB_Auxiliary. Downstream transmit selector is
** set to buffer containing data, if it exists.
*/
static void SelectRepDownBufsS
(
void
)
{
bit avail0; /* DB_RepeaterDn0 is available. */
bit avail1; /* DB_RepeaterDn1 is available. */


avail0 = GetBufferDataCount (DB_RepeaterDn0) == 0 &&
dataBuffers[DB_RepeaterDn0].xstat == DBX_None;
avail1 = GetBufferDataCount (DB_RepeaterDn1) == 0 &&
dataBuffers[DB_RepeaterDn1].xstat == DBX_None;

/* If both downstream buffers are available. */
if (avail0 && avail1)
{
xmDataM = DB_RepeaterDn0;
rcvDataS = DB_RepeaterDn0;

if (linkEvent.type == LET_SOF)
{
discardBuf = DB_RepeaterDn0;
nDiscardBufs = 0;
}
}
else if (avail1)
{
xmDataM = DB_RepeaterDn0; /* Setup data for transmit. */
rcvDataS = DB_RepeaterDn1; /* Use avail buffer for receive. */

if (linkEvent.type == LET_SOF)
{
discardBuf = DB_RepeaterDn0;
nDiscardBufs = 1;
}
}
else if (avail0)
{
xmDataM = DB_RepeaterDn1; /* Setup data for transmit. */
rcvDataS = DB_RepeaterDn0; /* Use avail buffer for receive. */

if (linkEvent.type == LET_SOF)
{
discardBuf = DB_RepeaterDn1;
nDiscardBufs = 1;
}
}
else /* Both downstream buffers in use. */
{
/* If retry mode, data is never discarded. */
if (txErrorRetryM)
{
rcvDataS = DB_Auxiliary;
}
else /* No retry: check for discardable buffer. */
{
/* Relative master has transmitted next data block. */
bit dataLost = (dataRcvd && rcvDataS == DB_Auxiliary);

if (linkEvent.type == LET_SOF) nDiscardBufs = 2;

/*
** If no buffers discarded yet, or one discarded and
** next data block was received (and lost).
*/
if ((nDiscardBufs == 2 ||
(nDiscardBufs == 1 && dataLost)) &&
dataBuffers[discardBuf].xstat != DBX_Active)
{
FlushDataBuffer (discardBuf);

rcvDataS = discardBuf;

/* If discarded buffer was being transmitted. */
if (discardBuf == xmDataM && xCopiesLeftM > 0)
{
if (curTopology != TP_PP)
LinkAckTransmittedData (CALLX_UNUSED);
else if (ppNode != CALLX_UNUSED &&
ppBranch != CALLX_UNUSED)
{
LinkAckTransmittedData (ppBranch);
}

nXmitCharsM = 0;
xCopiesLeftM = 0;
}

/* Update DTE transfer selectors. */
if (dteData0 == discardBuf)
dteData0 = DB_None;
else if (dteData1 == discardBuf)
dteData1 = DB_None;

if (discardBuf == DB_RepeaterDn0)
{
dataBuffers[DB_RepeaterDn0].xstat = DBX_None;

discardBuf = DB_RepeaterDn1;
xmDataM = DB_RepeaterDn1;
}
else
{
dataBuffers[DB_RepeaterDn1].xstat = DBX_None;

discardBuf = DB_RepeaterDn0;
xmDataM = DB_RepeaterDn0;
}

nDiscardBufs--;
}
else
rcvDataS = DB_Auxiliary;
}
}
}


/*******************************************************************
** Function: SelectRepUpBufsS
**
** Description: Select upstream receive and transmit buffers for
** repeater in slave phase.
**
** On exit: Upstream receive selector is set to available buffer, if
** it exists. Upstream transmit selector is set to buffer
** containing data, if it exists. If both receive and
** transmit buffers contain data, selectors are unchanged.
*/
static void SelectRepUpBufsS
(
void
)
{
bit avail0; /* DB_RepeaterUp0 is available. */
bit avail1; /* DB_RepeaterUp1 is available. */


/* If transmitting from DTE, adjustment to passthru unneeded. */
if (xmDataS == DB_SerialIn) return;

avail0 = GetBufferDataCount (DB_RepeaterUp0) == 0;
avail1 = GetBufferDataCount (DB_RepeaterUp1) == 0;

/* If both upstream buffers are available. */
if (avail0 && avail1)
{
rcvDataM = DB_RepeaterUp0;
xmDataS = DB_RepeaterUp0;
}
else if (avail1)
{
rcvDataM = DB_RepeaterUp1;
xmDataS = DB_RepeaterUp0;
}
else if (avail0)
{
rcvDataM = DB_RepeaterUp0;
xmDataS = DB_RepeaterUp1;
}
}


/*******************************************************************
** Function: SelectRepDownBufsM
**
** Description: Select downstream receive and transmit buffers for
** repeater in master phase.
**
** On exit: Downstream receive selector is set to available buffer,
** if it exists. If no downstream receive buffer is
** available, rcvDataM = DB_Auxiliary. Downstream transmit
** selector is set to buffer containing data, if it exists.
*/
static void SelectRepDownBufsM
(
void
)
{
bit avail0; /* DB_RepeaterDn0 is available. */
bit avail1; /* DB_RepeaterDn1 is available. */


avail0 = GetBufferDataCount (DB_RepeaterDn0) == 0;
avail1 = GetBufferDataCount (DB_RepeaterDn1) == 0;

/* If both downstream buffers are available. */
if (avail0 && avail1)
{
xmDataM = DB_RepeaterDn0;
rcvDataS = DB_RepeaterDn0;
}
else if (avail1)
{
xmDataM = DB_RepeaterDn0; /* Setup data for transmit. */
rcvDataS = DB_RepeaterDn1; /* Use avail buffer for receive. */
}
else if (avail0)
{
xmDataM = DB_RepeaterDn1; /* Setup data for transmit. */
rcvDataS = DB_RepeaterDn0; /* Use avail buffer for receive. */
}
}


/*******************************************************************
** Function: SelectRepUpBufsM
**
** Description: Select upstream receive and transmit buffers for
** repeater in master phase.
**
** On exit: Upstream receive selector is set to available buffer,
** if it exists. If no upstream receive buffer is
** available, rcvDataM = DB_Auxiliary. Upstream transmit
** selector is set to buffer containing data, if it exists.
*/
static void SelectRepUpBufsM
(
void
)
{
bit avail0; /* DB_RepeaterUp0 is available. */
bit avail1; /* DB_RepeaterUp1 is available. */


/* If transmitting from DTE, adjustment to passthru unneeded. */
if (xmDataS == DB_SerialIn) return;

avail0 = GetBufferDataCount (DB_RepeaterUp0) == 0;
avail1 = GetBufferDataCount (DB_RepeaterUp1) == 0;

/* If both upstream buffers are available. */
if (avail0 && avail1)
{
rcvDataM = DB_RepeaterUp0;
xmDataS = DB_RepeaterUp0;
}
else if (avail1)
{
rcvDataM = DB_RepeaterUp1; /* Use avail buffer for receive. */
xmDataS = DB_RepeaterUp0; /* Setup data for transmit. */
}
else if (avail0)
{
rcvDataM = DB_RepeaterUp0; /* Use avail buffer for receive. */
xmDataS = DB_RepeaterUp1; /* Setup data for transmit. */
}
else /* Both upstream buffers contain data. */
rcvDataM = DB_Auxiliary;
}


/*******************************************************************
** Function: GetBufferData
**
** Description: Get description of data in buffer.
**
** On entry: db != DB_SerialOut.
**
** On exit: Returns number of available data chars.
*/
static byte GetBufferData
(
tDataBufSelector db, /* Source buffer for data. */
int dc, /* Max. number data chars returned. */
tDataDesc idata* desc /* Descriptor for returned data. */
)
{
byte nChars; /* Return value: number avail. data chars. */

if (dc <= 0) return 0;

if (db == DB_SerialIn)
{
nChars = SerialInGetList (&(desc->sdata), dc);
if (curUse == US_MASTER && twoPhase && curTopology == TP_PP)
desc->dataRef = callList[ppNode].id;
else
desc->dataRef = thisId;
}
else
{
tBreakx breakx; /* Index of break in buffer data. */
tBreakx offset; /* Offset of break in buffer. */

nChars = dataBuffers[db].dataLen;
breakx = dataBuffers[db].breakx;

if (nChars == 0) return 0;

offset = 0;
if (breakx == UBREAK)
offset = nChars;
else if (breakx != NO_BREAK)
offset = breakx;

if (nChars > dc) nChars = dc;

desc->sdata.breakx = NO_BREAK;
if (offset <= nChars) desc->sdata.breakx = breakx;

desc->sdata.dlist[0].startp = dataBuffers[db].datap;
desc->sdata.dlist[0].len = nChars;
desc->sdata.dlist[1].startp = NULL;
desc->sdata.dlist[1].len = 0;
desc->dataRef = dataBuffers[db].dataRef;
}
return (nChars);
}


/*******************************************************************
** Function: DiscardBufferData
**
** Description: Discard buffer data. If nChars >= data chars in
** buffer, buffer is flushed.
**
** On entry: None.
**
** On exit: Data has been discarded from buffer.
*/
static void DiscardBufferData
(
tDataBufSelector db, /* Source buffer for data. */
byte nChars /* Number of bytes to discard. */
)
{
if (nChars == 0) return;

if (db == DB_SerialIn)
SerialInTailAdvance (nChars);
else
{
if (nChars >= dataBuffers[db].dataLen)
FlushDataBuffer (db);
else
{
tBreakx breakx;

breakx = dataBuffers[db].breakx;

/* If terminated break in discarded data. */
if (breakx < UBREAK)
{
if (nChars >= breakx)
dataBuffers[db].breakx = NO_BREAK;
else
dataBuffers[db].breakx -= nChars;
}
dataBuffers[db].datap += nChars;
dataBuffers[db].dataLen -= nChars;
}
}
}


/*******************************************************************
** Function: GetBufferDataCount
**
** Description: Get number of data chars in buffer.
**
** On entry: db != DB_SerialOut.
**
** Note: The "then" and "else" clauses are ordered to prevent allocating
** storage to db, thereby making the function non-reentrant.
*/
static byte GetBufferDataCount
(
tDataBufSelector db /* Data buffer. */
)
{
if (db != DB_SerialIn)
return dataBuffers[db].dataLen;
else
return SerialInNAvail ();
}


/*******************************************************************
** Function: GetBufferSize
**
** Description: Get buffer space available.
**
** On entry: db != DB_SerialIn.
**
** Note: The "then" and "else" clauses are ordered to prevent allocating
** storage to db, thereby making the function non-reentrant.
*/
static byte GetBufferSize
(
tDataBufSelector db /* Data buffer. */
)
{
if (db == DB_Auxiliary)
return (0);
else if (curUse == US_REPEATER)
{
/* If buffer contains data. */
if (dataBuffers[db].dataLen != 0)
return (0);
else if (db <= DB_RepeaterUp1)
return (REP_UP_DATA_LEN );
else
return (REP_DOWN_DATA_LEN);
}
else /* Master or slave unit. */
{
/* If buffer contains data. */
if (dteData0 != DB_None)
return (SerialOutNEmpty () -
dataBuffers[DB_MasterSlave].dataLen);
else
return (SerialOutNEmpty ());
}
}

/*
Function: ResetCheck

Description: Resets modem every 27000 Frames (15min.)

On Entry: None

On Exit: None, or modem forced to reset via watchdog timeout.

*/

/*static void ResetCheck (void)

{
if(FrameCtr == 27000)
{
EA=0;
FOREVER;
}

++FrameCtr;
}*/



#pragma NOAREGS /* Called from background or interrupt. */
/*******************************************************************
** Function: FlushDataBuffer
**
** Description: Flush data buffer.
**
** On entry: None.
**
** On exit: Buffer has been flushed.
*/
static void FlushDataBuffer
(
tDataBufSelector db /* Data buffer to flush. */
)
{
/* If serial input buffer: can't do that from here. */
if (db == DB_SerialIn) return;

dataBuffers[db].datap = NULL;
dataBuffers[db].dataLen = 0;
dataBuffers[db].breakx = NO_BREAK;
}
[/QUOTE]
 
Back
Top