static char sccsid
[] = "@(#)pk1.c 5.9 (Berkeley) %G%";
#include <eunice/eunice.h>
#define MAXPKTIME 32 /* was 16 */
extern char *sys_errlist
[];
* packet driver support routines
extern struct pack
*pklines
[];
* start initial synchronization.
register struct pack
*pk
;
if ((pk
= (struct pack
*) malloc(sizeof (struct pack
))) == NULL
)
bzero((caddr_t
) pk
, sizeof (struct pack
));
pk
->p_xsize
= pk
->p_rsize
= PACKSIZE
;
pk
->p_rwindow
= pk
->p_swindow
= WINDOWS
;
/* allocate input windows */
for (i
= 0; i
< pk
->p_rwindow
; i
++) {
if ((bp
= (char **) malloc((unsigned)pk
->p_xsize
)) == NULL
)
*bp
= (char *) pk
->p_ipool
;
DEBUG(1, "pkopen: can't malloc i = 0\n", CNULL
);
/* start synchronization */
pk
->p_msg
= pk
->p_rmsg
= M_INITA
;
for (i
= 0; i
< NPLINES
; i
++) {
if (pklines
[i
] == NULL
) {
DEBUG(1,"pkopen: i>=NPLINES\n", CNULL
);
for (i
= 0; i
< PKMAXSTMSG
; i
++) {
if ((pk
->p_state
& LIVE
) != 0)
DEBUG(1, "pkopen: i>= PKMAXSTMSG\n", CNULL
);
* input framing and block checking.
* frame layout for most devices is:
* S|K|X|Y|C|Z| ... data ... |
* where S == initial synch byte
* K == encoded frame size (indexes pksizes[])
* X, Y == block check bytes
* Z == XOR of header (K^X^Y^C)
* data == 0 or more data bytes
1, 32, 64, 128, 256, 512, 1024, 2048, 4096, 1
* Pseudo-dma byte collection.
register struct pack
*pk
;
register struct header
*h
;
if ((pk
->p_state
& DOWN
) || Connodata
> CONNODATA
|| Ntimeout
> MAXTIMEOUT
)
for (tries
= 0, noise
= 0; tries
< GETRIES
; ) {
p
= (caddr_t
) &pk
->p_ihbuf
;
if (pkcget(ifn
, p
, 1) == SUCCESS
) {
if (pkcget(ifn
, p
, HDRSIZ
-1) == SUCCESS
)
if (noise
++ < 10 || noise
< (3*pk
->p_rsize
))
DEBUG(4, "Noisy line - set up RXMIT\n", CNULL
);
/* set up retransmit or REJ */
if ((pk
->p_state
& LIVE
) == LIVE
)
DEBUG(4, "tries = %d\n", tries
);
h
= (struct header
*) &pk
->p_ihbuf
;
hdchk
= p
[1] ^ p
[2] ^ p
[3] ^ p
[4];
sum
= (unsigned) *p
++ & 0377;
sum
|= (unsigned) *p
<< 8;
DEBUG(7, "rec h->cntl 0%o\n", h
->cntl
&0xff);
DEBUG(7, "bad header 0%o,", hdchk
&0xff);
DEBUG(7, "h->ccntl 0%o\n", h
->ccntl
&0xff);
if (((h
->sum
+ h
->cntl
) & 0xffff) == CHECK
) {
DEBUG(7, "state - 0%o\n", pk
->p_state
);
DEBUG(7, "bad header (k==9) 0%o\n", h
->cntl
&0xff);
if (k
&& pksizes
[k
] == pk
->p_rsize
) {
pk
->p_rpr
= (h
->cntl
>> 3) & MOD8
;
DEBUG(7, "bp NULL %s\n", "");
pk
->p_ipool
= (char **) *bp
;
if (pkcget(pk
->p_ifn
, (char *) bp
, pk
->p_rsize
) == SUCCESS
) {
pkdata(h
->cntl
, h
->sum
, pk
, (char **) bp
);
*bp
= (char *)pk
->p_ipool
;
register struct pack
*pk
;
if (pk
->p_state
& DRAINO
|| !(pk
->p_state
& LIVE
)) {
for(x
=pk
->p_pr
; x
!=t
; x
= (x
-1)&7) {
*bp
= (char *)pk
->p_ipool
;
pk
->p_ib
[x
] = (char *)bp
;
* Start transmission on output device associated with pk.
* For asynch devices (t_line==1) framing is
* imposed. For devices with framing and crc
* in the driver (t_line==2) the transfer is
* passed on to the driver.
register struct pack
*pk
;
p
= (caddr_t
) &pk
->p_ohbuf
;
*p
++ = hdchk
= pk
->p_lpsize
;
checkword
= pk
->p_osum
[x
] ^ (unsigned)(cntl
& 0377);
checkword
= CHECK
- checkword
;
DEBUG(7, "send 0%o\n", cntl
&0xff);
p
= (caddr_t
) & pk
->p_ohbuf
;
if(write(pk
->p_ofn
, p
, HDRSIZ
) != HDRSIZ
) {
logent("PKXSTART write failed", sys_errlist
[errno
]);
char buf
[PKMAXBUF
+ HDRSIZ
+ TAILSIZE
], *b
;
for (i
= 0, b
= buf
; i
< HDRSIZ
; i
++)
for (i
= 0, p
= pk
->p_ob
[x
]; i
< pk
->p_xsize
; i
++)
for (i
= 0; i
< TAILSIZE
; i
++)
if (write(pk
->p_ofn
, buf
, pk
->p_xsize
+ HDRSIZ
+ TAILSIZE
)
!= (HDRSIZ
+ TAILSIZE
+ pk
->p_xsize
)) {
logent("PKXSTART write failed", sys_errlist
[errno
]);
pkmove(p1
, p2
, count
, flag
)
for (i
= 0; i
< count
; i
++)
* get n characters from input
* n - number of characters returned
long r
, itime
= 100000L; /* guess it's been 1/10th second since we
int SYS$
QioW(); /* use this for long reads on vms */
DEBUG(4, "pkcget: alarm %d\n", pktimeout
* 1000 + Ntimeout
);
if (pktimeout
> MAXPKTIME
)
signal(SIGALRM
, cgalarm
);
/* we predict that more than 1/50th of a
second will go by before the read will
give back all that we want. */
tv
.tv_sec
= r
/ 1000000L;
tv
.tv_usec
= r
% 1000000L;
DEBUG(11, "PKCGET stall for %d", tv
.tv_sec
);
DEBUG(11, ".%06d sec\n", tv
.tv_usec
);
(void) select (0, (int *)0, (int *)0, (int *)0, &tv
);
_$Cancel_IO_On_Signal
= FD_FAB_Pointer
[fn
];
ret
= SYS$
QioW(_$EFN
,(FD_FAB_Pointer
[fn
]->fab
).fab$l_stv
,
IO$_READVBLK
|IO$M_NOFILTR
|IO$M_NOECHO
,
_$Cancel_IO_On_Signal
= 0;
ret
= iosb
[1]+iosb
[3]; /* get length of transfer */
logent(sys_errlist
[errno
],"FAILED pkcget Read");