/* * DNET.C * * DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved. * * V <1.05 Alpha Release * V <1.10 Beta Release (Internal) * V1.10 First Release */ #include "dnet.h" extern int Enable_Abort; main(ac,av) char *av[]; { long sink_mask, dnet_mask; long baud = 0; short networknum = 0; char *netdevice = "serial.device"; long netunit = 0; ubyte notdone; ubyte autofterm = 1; char buf[sizeof(DNETPORTNAME)+32]; Enable_Abort = 0; bzero(Pkts,sizeof(Pkts)); { register short i; register char *ptr; for (i = 1; i < ac; ++i) { if (*(ptr = av[i]) == '-') { while (*++ptr) { switch(*ptr) { case 'b': baud = atoi(ptr+1); ptr = "\0\0"; break; case 'd': DDebug = 1; puts("Debugger on"); break; case 'n': HostName = ptr+1; ptr = "\0\0"; break; case 's': autofterm = 0; break; case 'h': AutoHangup = 1; break; case 'U': netunit = atoi(ptr+1); ptr = "\0\0"; break; case 'D': netdevice = ptr + 1; ptr = "\0\0"; break; case 'N': networknum = atoi(ptr+1); ptr = "\0\0"; break; default: printf("Unknown option: %c\n", *ptr); dneterror("Unknown switch"); break; /* not reached */ } } } } } sprintf(buf, "%s%d", DNETPORTNAME, networknum); { PORT *port; if (port = (PORT *)FindPort(buf)) { puts("DNET: Network number in use"); exit(1); } } DNetPort = (PORT *)CreatePort(buf, 0); IOSink = (PORT *)CreatePort(NULL,0); if (!DNetPort || !IOSink) dneterror("CreatePort"); NewList(&TxList); NewList(&SvList); Rto_act = Wto_act = 0; NetOpen(&RNet,&WNet, IOSink, netdevice, netunit, baud); TimerOpen(&Rto, IOSink); TimerOpen(&Wto, IOSink); WTimeoutVal = ((MAXPKT * 2) * 1000 / (Baud / 10 + 1)); RTimeoutVal = ((MAXPKT + 50) * 1000 / (Baud / 10 + 1)); WTimeoutVal *= 1000; RTimeoutVal *= 1000; RNet->io_Data = (APTR)&Raux->sync; /* Startup the network read */ RNet->io_Length = 3; SendIO(RNet); if (do_dnetwindow() < 0) dneterror(NULL); Rto.tr_node.io_Message.mn_Node.ln_Name = (char *)RTO_REQ; Wto.tr_node.io_Message.mn_Node.ln_Name = (char *)WTO_REQ; sink_mask = 1 << IOSink->mp_SigBit; dnet_mask = 1 << DNetPort->mp_SigBit; do_netreset(); loop: if (autofterm) { char buf[32]; sprintf(buf, "RUN NIL: FTERM -N%ld", networknum); if (Execute(buf, NULL, NULL) == 0) { puts("Unable to RUN FTERM (path not setup?)"); puts("You can do it yourself"); } } NetWrite(RestartPkt, 3, 1); Restart = 1; /* * NOTE: Routines must be particularly careful not to clear the * signal mask unless it doesn't matter. Specifically, * routines in the dnet_mask section cannot arbitrarily * clear the signal associated with the sink_mask section. * * If you look at NetWrite(), you will note that the signal * is restored if it must do a WaitIO(). */ notdone = 1; while (notdone) { long mask = Wait(sink_mask|dnet_mask|SIGBREAKF_CTRL_C); if (mask & sink_mask) { /* IOSink returns */ register IOR *ior; while (ior = (IOR *)GetMsg(IOSink)) { switch((long)ior->io_Message.mn_Node.ln_Name) { case PKT_REQ: --NumCon; if (ior->io_Length) FreeMem(ior->io_Data, ior->io_Length); FreeMem(ior, sizeof(IOR)); break; case RTO_REQ: /* Read timeout, reset READ state */ Rto_act = 0; do_rto(ior); break; case WTO_REQ: /* Write-Ack timeout, send CHECK */ Wto_act = 0; do_wto(ior); break; case RNET_REQ: /* Receive data ready, interpret */ if (do_rnet(ior) < 0 && AutoHangup) /* handle receive data */ notdone = 0; SendIO(ior); /* restart receive */ break; case WNET_REQ: /* Write data sent, start WTO */ NetClWrite(ior); do_wnet(ior); break; case IGWNET_REQ: NetClWrite(ior); break; } } } if (mask & dnet_mask) { /* Receive commands */ register IOR *ior; while (ior = (IOR *)GetMsg(DNetPort)) { ior->io_Actual = 0; switch(ior->io_Command) { case DNCMD_WRITE: /* write data to net */ { uword chan = (ulong)ior->io_Unit; if (Chan[chan].state != CHAN_OPEN) { ior->io_Error = 1; break; } ior->io_Error = 0; ior->io_Command = SCMD_DATA; ior->io_Message.mn_Node.ln_Pri = Chan[chan].pri; Enqueue(&TxList, ior); do_wupdate(); ior = NULL; } break; case DNCMD_SOPEN: /* Reply from server port on remote */ /* open request */ { CACKCMD ack; uword chan = (ulong)ior->io_Unit; ack.chanh = chan >> 8; ack.chanl = chan; ack.error = ior->io_Error; WriteStream(SCMD_ACKCMD, &ack, sizeof(ack), chan); if (ack.error) { Chan[chan].state = CHAN_FREE; --NumCon; } else { if (Chan[chan].state == CHAN_CLOSE && !ack.error) { WritePort(Chan[chan].port, DNCMD_CLOSE, NULL, 0, PKT_REQ, chan); goto sopenbrk; } Chan[chan].state = CHAN_OPEN; Chan[chan].port = (PORT *)ior->io_Offset; Chan[chan].flags = CHANF_ROK|CHANF_WOK; } do_wupdate(); sopenbrk: if (ior->io_Length) FreeMem(ior->io_Data, ior->io_Length); FreeMem(ior, sizeof(IOR)); ior = NULL; } break; case DNCMD_EOF: { CEOFCMD eof; uword chan = (ulong)ior->io_Unit; ior->io_Error = 0; eof.chanh = chan >> 8; eof.chanl = chan; eof.flags = CHANF_ROK; WriteStream(SCMD_EOFCMD, &eof, sizeof(CEOFCMD), chan); Chan[chan].flags &= ~CHANF_WOK; do_wupdate(); } break; case DNCMD_IOCTL: { CIOCTL cio; uword chan = (ulong)ior->io_Unit; ior->io_Error = 0; cio.chanh = chan >> 8; cio.chanl = chan; cio.valh = (ubyte)((ulong)ior->io_Data >> 24); cio.vall = (ubyte)((ulong)ior->io_Data >> 16); cio.valaux = (ubyte)((ulong)ior->io_Data >> 8); cio.cmd = (ubyte)(ulong)ior->io_Data; WriteStream(SCMD_IOCTL, &cio, sizeof(CIOCTL), chan); do_wupdate(); } break; case DNCMD_QUIT: { char dummy; DeldQuit = 1; WriteStream(SCMD_QUIT, &dummy, 1, -1); do_wupdate(); } break; case DNCMD_OPEN: ior->io_Error = 0; { uword chan = alloc_channel(); COPEN co; if (chan >= MAXCHAN) { ior->io_Error = 1; break; } co.chanh = chan >> 8; co.chanl = chan; co.porth = (ulong)ior->io_Unit >> 8; /* port # */ co.portl = (ulong)ior->io_Unit; co.error= 0; co.pri = (char)(long)ior->io_Message.mn_Node.ln_Name; Chan[chan].ior = ior; Chan[chan].port= (PORT *)ior->io_Offset; Chan[chan].state = CHAN_LOPEN; Chan[chan].flags = 0; Chan[chan].pri = ior->io_Message.mn_Node.ln_Pri; WriteStream(SCMD_OPEN, &co, sizeof(COPEN), chan); ior = NULL; do_wupdate(); } break; case DNCMD_CLOSE: /* same io_Command for CCTL_? */ ior->io_Error = 0; { CCLOSE cc; uword chan = (ulong)ior->io_Unit; cc.chanh = chan >> 8; cc.chanl = chan; WriteStream(SCMD_CLOSE, &cc, sizeof(CCLOSE), chan); Chan[chan].ior = ior; Chan[chan].state = CHAN_CLOSE; Chan[chan].flags |= CHANF_LCLOSE; if (Chan[chan].flags & CHANF_RCLOSE) { Chan[chan].state = CHAN_FREE; Chan[chan].ior = NULL; } else { ior = NULL; } do_wupdate(); } break; } if (ior) ReplyMsg(ior); } } if (mask & SIGBREAKF_CTRL_C) notdone = 0; } do_netreset(); if (do_dnetwindow() > 0) goto loop; dneterror(NULL); } do_netreset() { register short i; register CHAN *ch; register IOR *ior; while (ior = RemHead(&TxList)) { ior->io_Error = 1; ReplyMsg(ior); } for (i = 0, ch = Chan; i < MAXCHAN; ++i, ++ch) { switch(ch->state) { case CHAN_OPEN: WritePort(Chan[i].port, DNCMD_CLOSE, NULL, 0, PKT_REQ, i); case CHAN_ROPEN: /* pending on listen port */ ch->state = CHAN_CLOSE; ch->flags = CHANF_RCLOSE; ch->ior = NULL; break; case CHAN_LOPEN: /* pending on network */ ch->ior->io_Error = 1; ReplyMsg(ch->ior); ch->ior = NULL; ch->state = CHAN_FREE; ch->flags = 0; --NumCon; break; case CHAN_CLOSE: if (!(ch->flags & CHANF_LCLOSE)) break; ch->ior->io_Error = 1; ReplyMsg(ch->ior); ch->ior = NULL; ch->state = CHAN_FREE; ch->flags = 0; --NumCon; } } RPStart = 0; WPStart = 0; WPUsed = 0; RState = 0; RChan = 0; WChan = 0; }