#define ATP_DECLARE
#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/ioctl.h>
#include <sys/malloc.h>
#include <sys/socket.h>
#include <vm/vm_kern.h>
#include <netat/sysglue.h>
#include <netat/appletalk.h>
#include <netat/ddp.h>
#include <netat/at_pcb.h>
#include <netat/atp.h>
#include <netat/asp.h>
#include <netat/debug.h>
int atp_inited = 0;
struct atp_rcb_qhead atp_need_rel;
int atp_pidM[256];
gref_t *atp_inputQ[256];
struct atp_state *atp_used_list;
int atp_input(mp)
gbuf_t *mp;
{
register gref_t *gref;
switch (gbuf_type(mp)) {
case MSG_DATA:
gref = atp_inputQ[((at_ddp_t *)gbuf_rptr(mp))->dst_socket];
if ((gref == 0) || (gref == (gref_t *)1)) {
dPrintf(D_M_ATP, D_L_WARNING, ("atp_input: no socket, skt=%d\n",
((at_ddp_t *)gbuf_rptr(mp))->dst_socket));
gbuf_freem(mp);
return 0;
}
break;
case MSG_IOCACK:
case MSG_IOCNAK:
gref = (gref_t *)((ioc_t *)gbuf_rptr(mp))->ioc_private;
break;
case MSG_IOCTL:
default:
dPrintf(D_M_ATP, D_L_WARNING, ("atp_input: unknown msg, type=%d\n",
gbuf_type(mp)));
gbuf_freem(mp);
return 0;
}
atp_rput(gref, mp);
return 0;
}
void atp_init(void)
{
if (!atp_inited) {
atp_inited = 1;
atp_used_list = 0;
atp_trans_abort.head = NULL;
atp_trans_abort.tail = NULL;
atp_need_rel.head = NULL;
atp_need_rel.tail = NULL;
bzero(atp_inputQ, sizeof(atp_inputQ));
bzero(atp_pidM, sizeof(atp_pidM));
asp_init();
}
}
int atp_open(gref, flag)
gref_t *gref;
int flag;
{
register struct atp_state *atp;
register int i;
vm_offset_t temp;
if (atp_rcb_data == NULL) {
if (kmem_alloc(kernel_map, &temp, sizeof(struct atp_rcb) * NATP_RCB) != KERN_SUCCESS)
return(ENOMEM);
if (atp_rcb_data == NULL) {
bzero((caddr_t)temp, sizeof(struct atp_rcb) * NATP_RCB);
atp_rcb_data = (struct atp_rcb*)temp;
for (i = 0; i < NATP_RCB; i++) {
atp_rcb_data[i].rc_list.next = atp_rcb_free_list;
atp_rcb_free_list = &atp_rcb_data[i];
}
} else
kmem_free(kernel_map, temp, sizeof(struct atp_rcb) * NATP_RCB);
}
if (atp_state_data == NULL) {
if (kmem_alloc(kernel_map, &temp, sizeof(struct atp_state) * NATP_STATE) != KERN_SUCCESS)
return(ENOMEM);
if (atp_state_data == NULL) {
bzero((caddr_t)temp, sizeof(struct atp_state) * NATP_STATE);
atp_state_data = (struct atp_state*) temp;
for (i = 0; i < NATP_STATE; i++) {
atp_state_data[i].atp_trans_waiting = atp_free_list;
atp_free_list = &atp_state_data[i];
}
} else
kmem_free(kernel_map, temp, sizeof(struct atp_state) * NATP_STATE);
}
if ((atp = atp_free_list) == NULL)
return(EAGAIN);
atp_free_list = atp->atp_trans_waiting;
atp->dflag = 0;
atp->atp_trans_wait.head = NULL;
atp->atp_trans_waiting = NULL;
atp->atp_gref = gref;
atp->atp_retry = 10;
atp->atp_timeout = HZ/8;
atp->atp_rcb_waiting = NULL;
atp->atp_rcb.head = NULL;
atp->atp_attached.head = NULL;
atp->atp_flags = T_MPSAFE;
atp->atp_socket_no = -1;
atp->atp_pid = gref->pid;
atp->atp_msgq = 0;
ATEVENTINIT(atp->atp_event);
ATEVENTINIT(atp->atp_delay_event);
gref->info = (void *)atp;
if (flag) {
if ((atp->atp_trans_waiting = atp_used_list) != 0)
atp->atp_trans_waiting->atp_rcb_waiting = atp;
atp_used_list = atp;
}
return(0);
}
int atp_close(gref, flag)
gref_t *gref;
int flag;
{
register struct atp_state *atp;
register struct atp_trans *trp;
register struct atp_rcb *rcbp;
int socket;
pid_t pid;
atp = (struct atp_state *)gref->info;
if (atp->dflag)
atp = (struct atp_state *)atp->atp_msgq;
if (atp->atp_msgq) {
gbuf_freem(atp->atp_msgq);
atp->atp_msgq = 0;
}
atp->atp_flags |= ATP_CLOSING;
socket = atp->atp_socket_no;
if (socket != -1)
atp_inputQ[socket] = (gref_t *)1;
for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next)
atp_untimout(atp_req_timeout, trp);
while ((trp = atp->atp_trans_wait.head))
atp_free(trp);
while ((rcbp = atp->atp_rcb.head))
atp_rcb_free(rcbp);
while ((rcbp = atp->atp_attached.head))
atp_rcb_free(rcbp);
if (flag && (socket == -1))
atp_dequeue_atp(atp);
atp->atp_socket_no = -1;
atp->atp_trans_waiting = atp_free_list;
atp_free_list = atp;
if (socket != -1) {
pid = (pid_t)atp_pidM[socket];
atp_pidM[socket] = 0;
atp_inputQ[socket] = NULL;
if (pid)
ddp_notify_nbp(socket, pid, DDP_ATP);
}
return 0;
}