#include <sys/errno.h>
#include <sys/types.h>
#include <sys/param.h>
#include <machine/spl.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/filedesc.h>
#include <sys/fcntl.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/time.h>
#include <netat/sysglue.h>
#include <netat/appletalk.h>
#include <netat/at_pcb.h>
#include <netat/debug.h>
#include <netat/adsp.h>
#include <netat/adsp_internal.h>
gbuf_t *releaseData(mp, len)
gbuf_t *mp;
int len;
{
register gbuf_t *tmp;
register int cnt;
int freeit;
dPrintf(D_M_ADSP, D_L_TRACE,
("releaseData: mbuf=0x%x, len=%d\n", (unsigned)mp, len));
KERNEL_DEBUG(DBG_ADSP_RCV, 0, mp, len, 0, 0);
do {
freeit = 1;
if ((cnt = gbuf_len(mp)) > len) {
freeit = 0;
cnt = len;
}
gbuf_rinc(mp,cnt);
len -= cnt;
tmp = mp;
mp = gbuf_cont(mp);
if (freeit) {
gbuf_freeb(tmp);
} else
return tmp;
} while (len && mp);
return mp;
}
void CheckRecvSeq(sp, f)
register CCBPtr sp;
register ADSP_FRAMEPtr f;
{
int s;
int pktNextRecvSeq;
int sendWdwSeq;
int eom;
int hlen;
register gbuf_t *mp;
ATDISABLE(s, sp->lock);
if (f->descriptor & ADSP_ACK_REQ_BIT) {
sp->sendDataAck = 1;
sp->callSend = 1;
}
pktNextRecvSeq = netdw(UAL_VALUE(f->pktNextRecvSeq));
if (GT(pktNextRecvSeq, sp->maxSendSeq))
goto noack;
if (GTE(pktNextRecvSeq, sp->timerSeq) && sp->waitingAck) {
sp->waitingAck = 0;
sp->pktSendCnt = 0;
RemoveTimerElem(&adspGlobal.fastTimers, &sp->RetryTimer);
if (!sp->resentData) {
short diff;
diff = (((word)(SysTicks() - sp->sendStamp)) / (word)10) -
sp->roundTrip + 1;
sp->roundTrip += diff >> 3;
if (diff < 0)
diff = -diff;
sp->deviation += (diff - sp->deviation) >> 2;
sp->rtmtInterval = sp->roundTrip +
((short)2 * (short)sp->deviation);
if (!sp->noXmitFlow &&
sp->pktSendMax < 50)
sp->pktSendMax++;
sp->noXmitFlow = 0;
}
else
sp->resentData = 0;
}
if (LTE(pktNextRecvSeq,
sp->firstRtmtSeq))
goto noack;
if (!sp->sData)
goto noack;
do {
if (mp = sp->sbuf_mb) {
sp->sbuf_mb = gbuf_next(mp);
eom = 1;
} else {
mp = sp->csbuf_mb;
sp->csbuf_mb = 0;
eom = 0;
}
if (mp == 0) {
sp->sData = 0;
goto noack;
}
if (LTE((sp->firstRtmtSeq + eom + (hlen = gbuf_msgsize(mp))),
pktNextRecvSeq)) {
gbuf_freem(mp);
sp->firstRtmtSeq += eom + hlen;
if ((sp->sbuf_mb == 0) && (sp->csbuf_mb == 0)) {
sp->sData = 0;
sp->writeFlush = 0;
if (sp->state == sClosing)
CheckOkToClose(sp);
atalk_enablew(sp->gref);
break;
}
}
else
{
short acked;
acked = (pktNextRecvSeq - sp->firstRtmtSeq);
mp = releaseData(mp, acked);
if (eom) {
if (mp) {
gbuf_next(mp) = sp->sbuf_mb;
sp->sbuf_mb = mp;
}
} else
sp->csbuf_mb = mp;
sp->firstRtmtSeq = pktNextRecvSeq;
break;
}
} while (LT(sp->firstRtmtSeq, pktNextRecvSeq));
if (sp->sData)
sp->callSend = 1;
noack:
sendWdwSeq = netw(UAS_VALUE(f->pktRecvWdw)) - 1 + pktNextRecvSeq;
if (GT(sendWdwSeq, sp->sendWdwSeq))
{
sp->callSend = 1;
sp->sendWdwSeq = sendWdwSeq;
}
ATENABLE(s, sp->lock);
}
int RXData(sp, mp, f, len)
CCBPtr sp;
register gbuf_t *mp;
ADSP_FRAMEPtr f;
int len;
{
int s, offset;
int PktFirstByteSeq;
short cnt;
char eom;
len -= ADSP_FRAME_LEN;
eom = (f->descriptor & ADSP_EOM_BIT) ? 1 : 0;
dPrintf(D_M_ADSP, D_L_TRACE,
("RXData: sp=0x%x, mbuf=0x%x, f=0x%x, len=%d, eom=%d\n",
(unsigned)sp, (unsigned)mp, (unsigned)f, len, eom));
KERNEL_DEBUG(DBG_ADSP_RCV, 1, sp, mp, len, eom);
trace_mbufs(D_M_ADSP, " mp", mp);
PktFirstByteSeq = netdw(UAL_VALUE(f->pktFirstByteSeq));
ATDISABLE(s, sp->lock);
if (GT(PktFirstByteSeq, sp->recvSeq))
{
if (sp->badSeqCnt++ > sp->badSeqCnt)
sp->sendCtl |= B_CTL_RETRANSMIT;
ATENABLE(s, sp->lock);
CheckRecvSeq(sp, f);
CheckReadQueue(sp);
gbuf_freem(mp);
KERNEL_DEBUG(DBG_ADSP_RCV, 2, sp, 0, 0, 0);
trace_mbufs(D_M_ADSP, " exRXD m", sp->rbuf_mb);
dPrintf(D_M_ADSP, D_L_TRACE, (" End RXData - missed a packet\n"));
return 0;
}
if (LTE(PktFirstByteSeq + len + eom, sp->recvSeq)) {
ATENABLE(s, sp->lock);
CheckRecvSeq(sp, f);
CheckReadQueue(sp);
gbuf_freem(mp);
KERNEL_DEBUG(DBG_ADSP_RCV, 3, sp, 0, 0, 0);
trace_mbufs(D_M_ADSP, " exRXD m", sp->rbuf_mb);
dPrintf(D_M_ADSP, D_L_TRACE, (" End RXData - duplicate data\n"));
return 0;
}
sp->badSeqCnt = 0;
cnt = sp->recvSeq - PktFirstByteSeq;
offset = ((unsigned char *)&f->data[cnt]) - (unsigned char *)gbuf_rptr(mp);
gbuf_rinc(mp,offset);
len -= cnt;
cnt = len;
if (!sp->rData)
{
sp->rData = 1;
if ((sp->rpb)->ioc == (caddr_t)mp) {
dPrintf(D_M_ADSP, D_L_TRACE,
("RXData: (pb->ioc == mp) no stored data\n"));
KERNEL_DEBUG(DBG_ADSP_RCV, 4, sp, sp->rpb, 0, 0);
}
if (eom)
sp->rbuf_mb = mp;
else
sp->crbuf_mb = mp;
}
else {
gbuf_t *rmp;
if (eom) {
if (sp->crbuf_mb) {
gbuf_linkb(sp->crbuf_mb, mp);
mp = sp->crbuf_mb;
sp->crbuf_mb = 0;
}
if (rmp = sp->rbuf_mb) {
while(gbuf_next(rmp))
rmp = gbuf_next(rmp);
gbuf_next(rmp) = mp;
} else
sp->rbuf_mb = mp;
} else if (sp->crbuf_mb)
gbuf_linkb(sp->crbuf_mb, mp);
else
sp->crbuf_mb = mp;
}
sp->recvSeq += (cnt + eom);
ATENABLE(s, sp->lock);
CheckRecvSeq(sp, f);
CheckReadQueue(sp);
KERNEL_DEBUG(DBG_ADSP_RCV, 5, sp, sp->rbuf_mb, 0, 0);
trace_mbufs(D_M_ADSP, " eRXD m", sp->rbuf_mb);
return 0;
}