home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * DNETLIB.C
- *
- * DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
- *
- * Library Interface for DNET.
- */
-
- #define NOEXT
- #include "/dnet/dnet.h"
-
- #define CHANN struct _CHANN
-
- #define NAMELEN sizeof("DNET.PORT.XXXXX")
- #define NAMEPAT "DNET.PORT.%ld"
-
- CHANN {
- PORT port; /* receive data, replies */
- PORT *dnetport; /* dnet's master port */
- LIST rdylist; /* ready to be read */
- uword chan; /* channel # for open channels */
- ubyte eof; /* channel remotely closed/eof */
- ubyte filler;
- int qlen; /* allowed write queue size */
- int queued; /* current # packets queued */
- };
-
- static CHANN *MakeChannel();
-
- PORT *
- DListen(portnum)
- uword portnum;
- {
- PORT *port = NULL;
- char *ptr;
-
- ptr = AllocMem(NAMELEN, MEMF_PUBLIC); /* memory the the name */
- sprintf(ptr, NAMEPAT, portnum);
- Forbid(); /* task-atomic operation */
- if (FindPort(ptr) || !(port = CreatePort(ptr,0)))
- FreeMem(ptr, NAMELEN);
- Permit();
- return(port);
- }
-
- void
- DUnListen(lisport)
- PORT *lisport;
- {
- if (lisport) {
- register char *ptr = lisport->mp_Node.ln_Name;
- Forbid(); /* task-atomic operation */
- while (DNAAccept(lisport)); /* remove all pending requests */
- DeletePort(lisport); /* gone! */
- Permit();
- FreeMem(ptr, NAMELEN);
- }
- }
-
- /*
- * DAccept()
- *
- * Note: This call will work even if called by a task which does not
- * own the listen port.
- */
-
- PORT *
- DAccept(lisport)
- PORT *lisport;
- {
- register IOR *ior;
- register CHANN *chan = NULL;
-
- while (!chan && (ior = GetMsg(lisport))) {
- switch(ior->io_Command) {
- case DNCMD_SOPEN:
- chan = MakeChannel(ior, NULL);
- break;
- default:
- ior->io_Error = 1;
- break;
- }
- ReplyMsg(ior);
- }
- if (lisport->mp_MsgList.lh_Head != (NODE *)&lisport->mp_MsgList.lh_Tail)
- SetSignal(1 << lisport->mp_SigBit, 1 << lisport->mp_SigBit);
- return((PORT *)chan);
- }
-
- /*
- * Refuse a connection
- */
-
- DNAAccept(lisport)
- PORT *lisport;
- {
- IOR *ior;
-
- if (ior = GetMsg(lisport)) {
- ior->io_Error = 1;
- ReplyMsg(ior);
- }
- if (lisport->mp_MsgList.lh_Head != (NODE *)&lisport->mp_MsgList.lh_Tail)
- SetSignal(1 << lisport->mp_SigBit, 1 << lisport->mp_SigBit);
- return(ior != NULL);
- }
-
- DPri(chan, pri)
- CHANN *chan;
- {
- }
-
-
- PORT *
- DOpen(host, portnum, txpri, rxpri)
- char *host;
- char txpri, rxpri;
- uword portnum;
- {
- IOR ior;
- CHANN *chan;
-
- if (!host)
- host = "0";
- chan = MakeChannel(&ior, host);
- if (rxpri > 126)
- rxpri = 126;
- if (rxpri < -127)
- rxpri = -127;
- if (txpri > 126)
- txpri = 126;
- if (txpri < -127)
- txpri = -127;
- if (chan->dnetport) {
- ior.io_Command = DNCMD_OPEN;
- ior.io_Unit = (void *)portnum;
- ior.io_Offset = (long)chan;
- ior.io_Message.mn_ReplyPort = (PORT *)chan;
- ior.io_Message.mn_Node.ln_Pri = txpri;
- ior.io_Message.mn_Node.ln_Name= (char *)rxpri;
-
- PutMsg(chan->dnetport, &ior);
- WaitMsg(&ior);
- if (ior.io_Error == 0) {
- chan->chan = (long)ior.io_Unit;
- FixSignal(chan);
- return((PORT *)chan);
- }
- }
- DeleteChannel(chan);
- return(NULL);
- }
-
-
- DNRead(chan, buf, bytes)
- CHANN *chan;
- char *buf;
- {
- register IOR *ior;
- int len = 0;
- long n;
-
- if (chan->eof)
- return(-1);
- while (bytes && ((ior = RemHead(&chan->rdylist)) || (ior = GetMsg(chan)))) {
- if (ior->io_Message.mn_Node.ln_Type == NT_REPLYMSG) {
- if (!chan->queued)
- puts("DNRead: Software Error");
- else
- --chan->queued;
- if (ior->io_Length)
- FreeMem(ior->io_Data, ior->io_Length);
- FreeMem(ior, sizeof(IOR));
- continue;
- }
- switch(ior->io_Command) {
- case DNCMD_CLOSE:
- case DNCMD_EOF:
- chan->eof = 1;
- ReplyMsg(ior);
- break;
- case DNCMD_WRITE:
- n = ior->io_Length - ior->io_Actual;
- if (n <= bytes) {
- CopyMem((char *)ior->io_Data + ior->io_Actual, buf, n);
- bytes -= n;
- len += n;
- buf += n;
- ReplyMsg(ior);
- } else {
- CopyMem((char *)ior->io_Data + ior->io_Actual, buf, bytes);
- len += bytes;
- ior->io_Actual += bytes;
- bytes = 0;
- Forbid(); /* DNET device is a task, no need to Disable() */
- ior->io_Message.mn_Node.ln_Type = NT_MESSAGE;
- AddHead(&chan->port.mp_MsgList, ior);
- Permit();
- }
- break;
- default:
- ior->io_Error = 1;
- ReplyMsg(ior);
- }
- }
- FixSignal(chan);
- if (chan->eof)
- SetSignal(1 << chan->port.mp_SigBit, 1 << chan->port.mp_SigBit);
- return(len);
- }
-
- DRead(chan, buf, bytes)
- char *buf;
- CHANN *chan;
- {
- long len = 0;
- long n;
-
- if (chan->eof)
- return(-1);
- while (bytes) {
- WaitPort(chan);
- n = DNRead(chan, buf, bytes);
- if (n < 0)
- break;
- len += n;
- buf += n;
- bytes -= n;
- if (chan->eof)
- break;
- }
- return(len);
- }
-
- DQueue(chan, n)
- CHANN *chan;
- {
- chan->qlen = n;
- }
-
- DWrite(chan, buf, bytes)
- CHANN *chan;
- {
- int error = bytes;
-
- if (chan->qlen) {
- if (WaitQueue(chan, NULL) >= 0) {
- register IOR *ior = AllocMem(sizeof(IOR), MEMF_CLEAR|MEMF_PUBLIC);
- ior->io_Command = DNCMD_WRITE;
- ior->io_Unit = (void *)chan->chan;
- ior->io_Offset = (long)chan;
- ior->io_Message.mn_ReplyPort = (PORT *)chan;
- ior->io_Data = AllocMem(bytes, MEMF_PUBLIC);
- ior->io_Length = bytes;
- CopyMem(buf, ior->io_Data, bytes);
- PutMsg(chan->dnetport, ior);
- ++chan->queued;
- } else {
- error = -1;
- }
- } else {
- IOR ior;
- ior.io_Command = DNCMD_WRITE;
- ior.io_Unit = (void *)chan->chan;
- ior.io_Offset = (long)chan;
- ior.io_Message.mn_ReplyPort = (PORT *)chan;
- ior.io_Data = (APTR)buf;
- ior.io_Length = bytes;
- PutMsg(chan->dnetport, &ior);
- WaitMsg(&ior);
- if (ior.io_Error)
- error = -1;
- }
- FixSignal(chan);
- return(error);
- }
-
- DEof(chan)
- CHANN *chan;
- {
- IOR ior;
-
- ior.io_Command = DNCMD_EOF;
- ior.io_Unit = (void *)chan->chan;
- ior.io_Offset = (long)chan;
- ior.io_Message.mn_ReplyPort = (PORT *)chan;
- PutMsg(chan->dnetport, &ior);
- WaitMsg(&ior);
- FixSignal(chan);
- }
-
- DIoctl(chan, cmd, val, aux)
- CHANN *chan;
- ubyte cmd;
- uword val;
- ubyte aux;
- {
- IOR ior;
-
- ior.io_Command = DNCMD_IOCTL;
- ior.io_Unit = (void *)chan->chan;
- ior.io_Offset = (long)chan;
- ior.io_Message.mn_ReplyPort = (PORT *)chan;
- ior.io_Data = (APTR)(long)((val<<16)|(aux<<8)|cmd);
- PutMsg(chan->dnetport, &ior);
- WaitMsg(&ior);
- FixSignal(chan);
- }
-
- DQuit(host)
- char *host;
- {
- IOR ior;
- char buf[sizeof(DNETPORTNAME)+32];
- PORT *replyport = CreatePort(NULL, 0);
- PORT *dnetport;
-
- if (!host)
- host = "0";
- sprintf(buf, "%s%s", DNETPORTNAME, host);
- if (dnetport = FindPort(buf)) {
- ior.io_Command = DNCMD_QUIT;
- ior.io_Unit = 0;
- ior.io_Offset = 0;
- ior.io_Message.mn_ReplyPort = replyport;
- PutMsg(dnetport, &ior);
- WaitMsg(&ior);
- DeletePort(replyport);
- }
- return(dnetport != NULL);
- }
-
-
- DClose(chan)
- CHANN *chan;
- {
- IOR ior;
- IOR *io;
-
- ior.io_Command = DNCMD_CLOSE;
- ior.io_Unit = (void *)chan->chan;
- ior.io_Offset = (long)chan;
- ior.io_Message.mn_ReplyPort = (PORT *)chan;
- PutMsg(chan->dnetport, &ior);
- ++chan->queued;
- chan->qlen = 0;
- WaitQueue(chan, &ior);
- while ((io = RemHead(&chan->rdylist)) || (io = GetMsg(chan))) {
- io->io_Error = 1;
- ReplyMsg(io);
- }
- DeleteChannel(chan);
- }
-
- WaitMsg(ior)
- IOR *ior;
- {
- while (ior->io_Message.mn_Node.ln_Type != NT_REPLYMSG)
- Wait(1 << ior->io_Message.mn_ReplyPort->mp_SigBit);
- Forbid();
- Remove(ior);
- Permit();
- }
-
- WaitQueue(chan, skipior)
- CHANN *chan;
- IOR *skipior;
- {
- register IOR *io;
- short error = 0;
- while (chan->queued > chan->qlen) { /* until done */
- WaitPort(chan); /* something */
- io = (IOR *)GetMsg(chan);
- if (io->io_Message.mn_Node.ln_Type == NT_REPLYMSG) {
- if (error == 0)
- error = io->io_Error;
- if (io != skipior) {
- if (io->io_Length)
- FreeMem(io->io_Data, io->io_Length);
- FreeMem(io, sizeof(IOR));
- }
- --chan->queued;
- } else {
- AddTail(&chan->rdylist, io);
- }
- }
- return(error);
- }
-
- static
- CHANN *
- MakeChannel(ior, host)
- register IOR *ior;
- char *host;
- {
- CHANN *chan = AllocMem(sizeof(CHANN), MEMF_PUBLIC|MEMF_CLEAR);
-
- /* Name, Pri */
- chan->port.mp_Node.ln_Type = NT_MSGPORT;
- chan->port.mp_SigBit = AllocSignal(-1);
- chan->port.mp_SigTask = FindTask(NULL);
- NewList(&chan->port.mp_MsgList);
- NewList(&chan->rdylist);
- chan->chan = (long)ior->io_Unit;
- ior->io_Offset = (long)chan;
- if (host) {
- char buf[sizeof(DNETPORTNAME)+32];
- sprintf(buf, "%s%s", DNETPORTNAME, host);
- ior->io_Message.mn_ReplyPort = FindPort(buf);
- }
- chan->dnetport = ior->io_Message.mn_ReplyPort;
- return(chan);
- }
-
- static
- DeleteChannel(chan)
- CHANN *chan;
- {
- FreeSignal(chan->port.mp_SigBit);
- FreeMem(chan, sizeof(CHANN));
- }
-
- static
- FixSignal(chan)
- register CHANN *chan;
- {
- if (chan->port.mp_MsgList.lh_Head != (NODE *)&chan->port.mp_MsgList.lh_Tail ||
- chan->rdylist.lh_Head != (NODE *)&chan->rdylist.lh_Tail)
- SetSignal(1 << chan->port.mp_SigBit, 1 << chan->port.mp_SigBit);
- }
-
-