/* * SERNET.C * * DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved. * * NetWork device interface. */ #include "dnet.h" #define WPEND 4 /* must be at least 2 */ static IOSER Iowq[WPEND]; static ubyte Iowact[WPEND]; static IOSER *CNet; /* control-req (synchro) */ static IOSER *RNet; /* read-request */ static ubyte RNetInProg; /* read request in progress */ static ubyte SerialIsOpen; /* serial device is open */ static ubyte RecvEnabled = 1; static char *DevName; static long UnitNum; extern void *CheckIO(); NetOpen(iosink, devname, unitnum, pbaud) PORT *iosink; char *devname; long *pbaud; { IOSER ios; short i; long baud = *pbaud; DevName = devname; UnitNum = unitnum; bzero(&ios, sizeof(ios)); ios.io_CtlChar = 0x11130102; ios.io_SerFlags = SERF_SHARED|SERF_XDISABLED|SERF_RAD_BOOGIE; if (OpenDevice(devname, unitnum, &ios, 0)) dneterror(devname); ios.IOSer.io_Message.mn_ReplyPort = iosink; SerialIsOpen = 1; RNet = (IOSER *)AllocMem(sizeof(IOSER), MEMF_PUBLIC); CNet = (IOSER *)AllocMem(sizeof(IOSER), MEMF_PUBLIC); *RNet = ios; *CNet = ios; { register IOSER *ioc = CNet; ioc->IOSer.io_Command = SDCMD_QUERY; DoIO(ioc); ioc->IOSer.io_Command = SDCMD_SETPARAMS; ioc->io_SerFlags = SERF_SHARED|SERF_XDISABLED|SERF_RAD_BOOGIE; ioc->io_ExtFlags = 0; ioc->io_ReadLen = ioc->io_WriteLen = 8; ioc->io_CtlChar = 0x01020304; if (baud) ioc->io_Baud = baud; *pbaud = Baud = ioc->io_Baud; if (DoIO(ioc) != 0) dneterror("Unable to set serial parameters"); } RNet->IOSer.io_Command = CMD_READ; RNet->IOSer.io_Message.mn_Node.ln_Name = (char *)RNET_REQ; CNet->IOSer.io_Command = CMD_WRITE; CNet->IOSer.io_Message.mn_Node.ln_Name = (char *)WNET_REQ; for (i = 0; i < WPEND; ++i) Iowq[i] = *CNet; CNet->IOSer.io_Message.mn_Node.ln_Name = (char *)CNET_REQ; } /* * Closedown the network. */ NetClose() { NetAbortRead(); NetWaitWrite(); if (SerialIsOpen) CloseDevice(RNet); if (RNet) FreeMem(RNet, sizeof(IOSER)); if (CNet) FreeMem(CNet, sizeof(IOSER)); SerialIsOpen = 0; RNet = CNet = NULL; } /* * NETCLWRITE() * * Clear write request which was GetMsg()'d in DNET.C instead of * WaitIO()'d here. */ NetClWrite(ior) IOSER *ior; { short i = ior - &Iowq[0]; if (i < 0 || i >= WPEND) { printf("NetClWrite: Software error %ld\n", i); } else { Iowact[i] = 0; } } /* * NETWRITE() * * Write data to the network. Only one standard request (for which we * expect a reply) is allowed queued at one time, while several (WPEND-1) * expect-no-reply requests may be queued. */ void NetWrite(buf, bytes, expectreply) APTR buf; { register short i; if (PDebug) printf("SEND %02x %4ld bytes\n", ((ubyte *)buf)[1], bytes); if (!SerialIsOpen) return; if (expectreply) { if (Iowact[0]) { WaitIO(&Iowq[0]); Iowact[0] = 0; } i = 0; } else { for (i = 1; i < WPEND; ++i) { if (!Iowact[i]) break; if (CheckIO(&Iowq[i])) { WaitIO(&Iowq[i]); Iowact[i] = 0; break; } } if (i == WPEND) { WaitIO(&Iowq[1]); Iowact[1] = 0; i = 1; } } if (bytes) { register IOSER *iow = &Iowq[i]; iow->IOSer.io_Message.mn_Node.ln_Name = (char *)((expectreply) ? WNET_REQ : IGWNET_REQ); iow->IOSer.io_Data = buf; iow->IOSer.io_Length = bytes; SendIO(iow); Iowact[i] = 1; } fixsignal(Iowq[0].IOSer.io_Message.mn_ReplyPort); } NetBreak() { if (SerialIsOpen) { CNet->IOSer.io_Command = SDCMD_BREAK; DoIO(CNet); fixsignal(Iowq[0].IOSer.io_Message.mn_ReplyPort); } } /* * NETREADY() * * Using the specified inactive request, return the # bytes ready and * the carrier status. */ NetReady() { register long n = 0; if (SerialIsOpen && RecvEnabled) { CNet->IOSer.io_Command = SDCMD_QUERY; if (DoIO(CNet) == 0) n = CNet->IOSer.io_Actual; Cd = !(CNet->io_Status & (1 << 5)); } return(n); } /* * SetBaudRate() */ SetBaudRate(baud) long baud; { register long result; if (TOBaud == 0) SetTimeouts(baud); if (CNet) CNet->io_Baud = baud; if (!SerialIsOpen) return(1); SaveState(); CNet->IOSer.io_Command = SDCMD_SETPARAMS; result = DoIO(CNet); RestoreState(); return(result == 0); } /* * Assumes CNet holds current settings */ DropDTR() { if (SerialIsOpen) { /* only if serial.device currently open */ NetSerialOff(); Delay(50L); NetSerialOn(); } } IOSER * NetAbortRead() { if (RNetInProg) { if (SerialIsOpen && RecvEnabled) { AbortIO(RNet); WaitIO(RNet); } RNetInProg = 0; } return(RNet); } static APTR SaveBuf; static long SaveLen; NetStartRead(buf, len) APTR buf; long len; { if (SerialIsOpen && RecvEnabled) { if (RNetInProg) NetAbortRead(); SaveBuf = RNet->IOSer.io_Data = buf; SaveLen = RNet->IOSer.io_Length = len; SendIO(RNet); } else { SaveBuf = buf; /* fake it */ SaveLen = len; RNet->IOSer.io_Actual = 0; } RNetInProg = 1; } IOSER * NetReadReady() { return((IOSER *)CheckIO(RNet)); } NetReadReturned() { RNetInProg = 0; } NetWaitWrite() { register short i; register short flag = 0; for (i = 0; i < WPEND; ++i) { if (Iowact[i]) { WaitIO(&Iowq[i]); Iowact[i] = 0; flag = 1; } } if (flag) fixsignal(Iowq[0].IOSer.io_Message.mn_ReplyPort); } static char SvRInProg; SaveState() { if (SvRInProg = RNetInProg) NetAbortRead(); NetWaitWrite(); } RestoreState() { if (SvRInProg) { register long n = RNet->IOSer.io_Actual; if (n < 0) n = 0; NetStartRead((char *)SaveBuf + n, SaveLen - n); } } NetRecvOff() { if (RecvEnabled) { SaveState(); RecvEnabled = 0; } } NetRecvOn() { if (!RecvEnabled) { RecvEnabled = 1; RestoreState(); } } NetSerialOff() { if (SerialIsOpen) { SaveState(); /* make sure no requests pending */ CloseDevice(RNet); /* close the device */ SerialIsOpen = 0; } } NetSerialOn() { if (!SerialIsOpen) { register short i; if (OpenDevice(DevName, UnitNum, RNet, 0)) /* OH HELL! */ return(0); /* * Fix the Device / Unit fields and restore the previous * modes. */ SerialIsOpen = 1; for (i = 0; i < WPEND; ++i) { Iowq[i].IOSer.io_Device = RNet->IOSer.io_Device; Iowq[i].IOSer.io_Unit = RNet->IOSer.io_Unit; } CNet->IOSer.io_Device = RNet->IOSer.io_Device; CNet->IOSer.io_Unit = RNet->IOSer.io_Unit; RNet->IOSer.io_Command = CMD_READ; /* restore params */ CNet->IOSer.io_Command = SDCMD_SETPARAMS; CNet->io_SerFlags = SERF_SHARED|SERF_XDISABLED|SERF_RAD_BOOGIE; DoIO(CNet); RestoreState(); /* restore pending read req. */ } return(1); }