#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 <netat/sysglue.h>
#include <netat/appletalk.h>
#include <netat/ddp.h>
#include <netat/debug.h>
#include <netat/at_pcb.h>
#include <netat/atp.h>
#define TRPS_PER_BLK 16
gbuf_t *atp_resource_m = 0;
extern caddr_t atp_free_cluster_list;
extern struct atp_rcb_qhead atp_need_rel;
struct atp_trans *atp_trans_alloc(atp)
struct atp_state *atp;
{
int i;
gbuf_t *m;
register struct atp_trans *trp, *trp_array;
if (atp_trans_free_list == 0) {
if ((m = gbuf_alloc_wait(TRPS_PER_BLK*sizeof(struct atp_trans),
atp == NULL)) == 0)
return (struct atp_trans *)0;
bzero(gbuf_rptr(m), TRPS_PER_BLK*sizeof(struct atp_trans));
trp_array = (struct atp_trans *)gbuf_rptr(m);
for (i=0; i < TRPS_PER_BLK-1; i++)
trp_array[i].tr_list.next = (struct atp_trans *)&trp_array[i+1];
gbuf_cont(m) = atp_resource_m;
atp_resource_m = m;
trp_array[i].tr_list.next = atp_trans_free_list;
atp_trans_free_list = (struct atp_trans *)&trp_array[0];
}
trp = atp_trans_free_list;
atp_trans_free_list = trp->tr_list.next;
trp->tr_queue = atp;
trp->tr_state = TRANS_TIMEOUT;
trp->tr_local_node = 0;
ATEVENTINIT(trp->tr_event);
dPrintf(D_M_ATP_LOW, D_L_TRACE,
("atp_trans_alloc(0x%x): alloc'd trp 0x%x\n",
(u_int) atp, (u_int) trp));
return trp;
}
void atp_trans_free(trp)
register struct atp_trans *trp;
{
trp->tr_queue = 0;
trp->tr_list.next = atp_trans_free_list;
atp_trans_free_list = trp;
}
struct atp_rcb *atp_rcb_alloc(atp)
struct atp_state *atp;
{
register struct atp_rcb *rcbp;
if ((rcbp = atp_rcb_free_list) != NULL) {
atp_rcb_free_list = rcbp->rc_list.next;
rcbp->rc_queue = atp;
rcbp->rc_pktcnt = 0;
rcbp->rc_local_node = 0;
}
dPrintf(D_M_ATP_LOW, D_L_TRACE,
("atp_rcb_alloc: allocated rcbp 0x%x\n", (u_int) rcbp));
return(rcbp);
}
void atp_rcb_free(rcbp)
register struct atp_rcb *rcbp;
{
register struct atp_state *atp;
register int i;
register int rc_state;
dPrintf(D_M_ATP_LOW, D_L_TRACE,
("atp_rcb_free: freeing rcbp 0x%x\n", (u_int) rcbp));
atp = rcbp->rc_queue;
if ((rc_state = rcbp->rc_state) == -1) {
dPrintf(D_M_ATP, D_L_WARNING,
("atp_rcb_free(%d): tid=%d,loc=%d,rem=%d\n",
0, rcbp->rc_tid,
rcbp->rc_socket.socket, atp->atp_socket_no));
return;
}
rcbp->rc_state = -1;
rcbp->rc_xo = 0;
rcbp->rc_queue = 0;
if (rcbp->rc_timestamp) {
rcbp->rc_timestamp = 0;
ATP_Q_REMOVE(atp_need_rel, rcbp, rc_tlist);
rcbp->rc_tlist.prev = NULL;
rcbp->rc_tlist.next = NULL;
}
if (rcbp->rc_xmt) {
gbuf_freem(rcbp->rc_xmt);
rcbp->rc_xmt = NULL;
for (i=0; i < rcbp->rc_pktcnt; i++)
rcbp->rc_snd[i] = 0;
}
if (atp_free_cluster_list)
atp_delete_free_clusters(NULL);
if (rc_state != RCB_UNQUEUED) {
if (rc_state == RCB_PENDING) {
ATP_Q_REMOVE(atp->atp_attached, rcbp, rc_list);
} else {
ATP_Q_REMOVE(atp->atp_rcb, rcbp, rc_list);
}
}
if (rcbp->rc_ioctl) {
gbuf_freem(rcbp->rc_ioctl);
rcbp->rc_ioctl = NULL;
}
rcbp->rc_list.next = atp_rcb_free_list;
atp_rcb_free_list = rcbp;
}