home *** CD-ROM | disk | FTP | other *** search
- RCS_ID_C="$Id: agnet.c,v 4.8 1994/02/25 01:13:12 ppessi Exp $";
- /*
- * agnet.c --- agnet main program and arexx interface
- *
- * Author: ppessi <Pekka.Pessi@hut.fi>
- *
- * Copyright (c) 1993 OHT-AmiTCP/IP Group,
- * Helsinki University of Technology, Finland.
- * All rights reserved.
- *
- * Created : Sat Feb 20 18:30:59 1993 ppessi
- * Last modified: Thu Oct 7 18:23:33 1993 ppessi
- *
- * $Log: agnet.c,v $
- * Revision 4.8 1994/02/25 01:13:12 ppessi
- * *** empty log message ***
- *
- * Revision 3.1 93/10/07 19:24:08 ppessi
- * Release 2.1 version
- *
- * Revision 2.1 93/05/14 16:46:32 ppessi
- * Release version.
- *
- * Revision 2.0 93/03/10 16:35:03 16:35:03 ppessi (Pekka Pessi)
- * Prototype release.
- */
-
- #include <string.h>
- #include <stdarg.h>
-
- #include <dos/dostags.h>
- #include <dos/rdargs.h>
- #include <intuition/intuition.h>
- #include <rexx/storage.h>
- #include <rexx/rxslib.h>
-
- #include <clib/exec_protos.h>
- #include <clib/dos_protos.h>
- #include <clib/utility_protos.h>
- #include <clib/intuition_protos.h>
-
- #ifdef __SASC
- #include <pragmas/exec_sysbase_pragmas.h>
- #include <pragmas/dos_pragmas.h>
- #include <pragmas/utility_pragmas.h>
- #include <pragmas/intuition_pragmas.h>
- #endif
-
- #include "agnet.h"
- #include "agnet_protos.h"
- #include "agnet_rev.h"
- #include "bases.h"
-
- static ULONG init_arexx(VOID);
- static VOID poll_arexx(VOID);
- static VOID deinit_arexx(VOID);
-
- /*
- * We start as a CLI.
- * Assembler stub routine does a MakeLibrary and
- * initializes needed librarybases
- */
- LONG ASM main(REG(a6)struct AgnetDevice *adb)
- {
- struct Process *proc;
- struct IOSana2Req *io;
- ULONG waitmask, rexxsignal, signals;
- UBYTE devsignal;
- UBYTE myname[sizeof(AGNETDEVNAME)+5];
-
- AgnetDeviceBase = adb;
-
- proc = (struct Process *)FindTask(0L);
-
- /* Initialize the device base */
- adb->ad_Device.lib_Node.ln_Pri = AGNET_DEV_PRI;
- adb->ad_Device.lib_Node.ln_Type = NT_DEVICE;
- adb->ad_Device.lib_Node.ln_Name = myname;
- adb->ad_Device.lib_Version = VERSION;
- adb->ad_Device.lib_Revision = REVISION;
- adb->ad_Device.lib_IdString = VSTRING;
- adb->ad_Task = (struct Task *)proc;
-
- /* Set up our unit message port */
- /* Attempt to allocate a signal bit for our Unit MsgPort. */
- devsignal = AllocSignal(-1L);
- if (devsignal == -1) {
- return 20;
- }
- NewList(&adb->ad_MsgPort.mp_MsgList);
- adb->ad_MsgPort.mp_SigBit = devsignal;
- adb->ad_MsgPort.mp_SigTask = (struct Task *)proc;
- adb->ad_MsgPort.mp_Flags = PA_SIGNAL;
-
- /* Initialize our device base semafore */
- InitSemaphore(&adb->ad_Lock);
-
- InitLRandom();
-
- #ifdef AGREXX
- /* Initialize Arexx port */
- rexxsignal = init_arexx();
- #else
- rexxsignal = 0;
- #endif
- /* OK, we are ready to add agnet.device to system */
- {
- int i, n = sizeof(AGNETDEVNAME) - 1;
- strcpy(myname, AGNETDEVNAME);
-
- Forbid();
- for (i = 0; i < 9; i++) {
- if (!FindName(&adb->ad_SysBase->DeviceList, myname))
- break;
- myname[n] = '.'; myname[n+1] = '1' + i; myname[n+2] = '\0';
- }
- AddDevice(adb);
- Permit();
- }
-
- waitmask = (1<<devsignal) | rexxsignal | SIGBREAKF_CTRL_F ;
-
- while (TRUE) {
- signals = Wait(waitmask); /* wait for device command */
-
- if (signals & SIGBREAKF_CTRL_F) {
- if (DoExpunge(adb))
- break;
- }
-
- while (io = (struct IOSana2Req *)GetMsg(&adb->ad_MsgPort))
- PerformIO(io);
-
- #ifdef AGREXX
- if (signals & rexxsignal)
- poll_arexx();
- #endif
- }
-
- /* Clean up */
- #ifdef AGREXX
- deinit_arexx();
- #endif
- FreeSignal(devsignal);
- return 0;
- }
-
- /* Local prototypes */
- static LONG ParseConfig(struct AgnetDevUnit *, struct RDArgs *, STRPTR*);
- static BOOL GetBitAddress(UBYTE *addr, UBYTE *string, LONG bitsize);
- static char *SanaSprintf(register char *ap, int len);
- static ULONG csprintf(struct CSource *buf, const char *fmt, ...);
-
- #define CONFIG_ENV_TEMPLATE "ENV:SANA2/config%ld.agnet"
-
- #define UNINITIALIZED 0xffffffff
-
- /*
- * ReadConfig
- *
- * Attempt to read in the driver's configuration file.
- *
- * The files are named by ENV:SANA2/agnet%d.config where %d is the decimal
- * representation of the device's unit number.
- *
- * Return FALSE upon error.
- */
- BOOL ReadConfig(struct AgnetDevUnit *adu)
- {
- UBYTE *fbuf = NULL;
- UBYTE buff[40];
- struct CSource csbuff = { NULL, sizeof(buff), 0L };
- BPTR ConfigFile;
- LONG offset, len;
- BOOL ok = FALSE;
-
- csbuff.CS_Buffer = buff;
-
- /* This configures unit by default values */
- adu->adu_HardwareType = UNINITIALIZED;
-
- /* Create the name of our config file.. */
- csprintf(&csbuff, CONFIG_ENV_TEMPLATE, (ULONG)adu->adu_UnitNum);
-
- /* ...and open it. */
- ConfigFile = Open(buff, MODE_OLDFILE);
- if (!ConfigFile)
- return TRUE;
-
- len = (Seek(ConfigFile, 0L, 1), Seek(ConfigFile, 0L, 0));
- if (len >= 0 && (fbuf = AllocMem(len+2, MEMF_PUBLIC))) {
- Seek(ConfigFile, 0L, -1);
- if (Read(ConfigFile, fbuf, len) == len) {
- ok = TRUE;
- fbuf[len] = '\n';
- fbuf[len+1] = '\0';
- }
- }
- Close(ConfigFile);
-
- if (ok) {
- struct RDArgs *rdargs = AllocDosObject(DOS_RDARGS, NULL);
- STRPTR *errmsg;
-
- if (rdargs) {
- /* Remove Comment lines */
- for (offset = 0; offset < len;) {
- if (fbuf[offset] == '#')
- while(fbuf[offset] != '\n')
- fbuf[offset++] = ' ';
- else
- while(fbuf[offset++] != '\n');
- fbuf[offset - 1] = ' '; /* remove linefeeds in file */
- }
- /* Add sentinel */
- fbuf[len] = '\n';
-
- rdargs->RDA_Source.CS_Buffer = fbuf;
- rdargs->RDA_Source.CS_Length = len + 1;
- rdargs->RDA_Source.CS_CurChr = 0;
-
- if (ParseConfig(adu, rdargs, &errmsg)) {
- struct EasyStruct es;
- APTR args[2];
- args[0] = errmsg;
- args[1] = buff;
- es.es_StructSize = sizeof(es);
- es.es_Flags = 0;
- es.es_Title = AGNETDEVNAME;
- es.es_TextFormat="Error %s in \nthe configuration file\n%s";
- es.es_GadgetFormat="Okay";
- EasyRequestArgs(NULL, &es, 0, args);
- ok = FALSE;
- }
- }
- FreeDosObject(DOS_RDARGS, rdargs);
- }
-
- if (fbuf) FreeMem(fbuf, len+2);
- return ok;
- }
-
- #define MYREXXNAME "agnet"
- #define MYREXXEXTENSION "agnet"
-
- /* Error strings */
- #define ERR_MALFORMED "Malformed command line"
- #define ERR_SYNTAX "Syntax error"
- #define ERR_WIRE "Illegal wiretype"
- #define ERR_ADDRESS "Illegal address"
- #define ERR_UNIT "Illegal unit number"
- #define ERR_INITUNIT "Error initializing unit"
- #define ERR_MEMORY "Memory exhausted"
- #define ERR_OPEN "Unit is currently opened"
- #define ERR_VALUE "Illegal value"
-
- #ifdef AGREXX
- /*
- * Arexx interface functions to agnet.device
- */
-
- #include <rexx/storage.h>
- #include <rexx/rxslib.h>
- #include <clib/rexxsyslib_protos.h>
- #ifdef __SASC
- #include <pragmas/rexxsyslib_pragmas.h>
- #endif
- #include "SimpleRexx.h"
-
- AREXXCONTEXT RexxContext;
-
- static LONG ParseRexx(UBYTE *arg, UBYTE **errstr, UBYTE **result);
- static LONG ParseQuery(struct AgnetDevUnit *, struct RDArgs *,
- STRPTR *,STRPTR *);
- /*
- * Initialize Arexx port
- */
- static ULONG
- init_arexx(VOID)
- {
- ULONG rexxsignal;
-
- RexxContext = InitARexx(MYREXXNAME, MYREXXEXTENSION);
-
- if (!RexxContext)
- return 0L;
-
- rexxsignal = ARexxSignal(RexxContext);
-
- return rexxsignal;
- }
-
- /*
- * Free ARexx port
- */
- static VOID
- deinit_arexx(VOID)
- {
- if (RexxContext)
- FreeARexx(RexxContext);
- }
-
- /*
- * Poll Arexx port
- */
- static VOID
- poll_arexx(VOID)
- {
- struct RexxMsg *rmsg;
-
- /*
- * Process the ARexx messages...
- */
- while (rmsg = GetARexxMsg(RexxContext)) {
- UBYTE *error = NULL, *result = NULL;
- LONG errlevel=0;
-
- if (errlevel = ParseRexx(ARG0(rmsg), &error, &result)) {
- SetARexxLastError(RexxContext, rmsg, error);
- }
- ReplyARexxMsg(RexxContext, rmsg, result, errlevel);
- }
- }
-
- /*
- * Rexx commands
- */
-
- #define REXXKEYWORDS "U=UNIT,Q=QUERY,E=EXIT=EXPUNGE"
- #define KEYWORDLEN 16
-
- #define KEY_UNIT 0
- #define KEY_QUERY 1
- #define KEY_EXIT 2
-
- /*
- * Parse the ARexx command
- */
- static LONG
- ParseRexx(UBYTE *arg, UBYTE **errstr, UBYTE **result)
- {
- struct AgnetDevice *adb = AgnetDeviceBase;
- LONG errlevel = 0;
- UBYTE Buffer[KEYWORDLEN];
- LONG len = LengthArgstring(arg) + 2;
- UBYTE *cmd = AllocMem(len, 0);
- struct RDArgs *rdargs = AllocDosObject(DOS_RDARGS, NULL);
- LONG unit, keyword;
- struct AgnetDevUnit *adu;
-
- if (!cmd || !rdargs) {
- errlevel = 40;
- *errstr = ERR_MEMORY;
- } else {
- memcpy(cmd, arg, len - 2);
- /* Add sentinel */
- cmd[len-2] = '\n'; cmd[len-1] = '\0';
- rdargs->RDA_Source.CS_Buffer = cmd;
- rdargs->RDA_Source.CS_Length = len - 1;
- rdargs->RDA_Source.CS_CurChr = 0;
- /* First, parse the command keyword */
- if (ReadItem(Buffer, sizeof(Buffer), &rdargs->RDA_Source) <= 0 ||
- (keyword = FindArg(REXXKEYWORDS, Buffer)) < 0) {
- errlevel = 20;
- *errstr = ERR_MALFORMED;
- } else {
- switch (keyword) {
- case KEY_UNIT:
- case KEY_QUERY:
- /* Parse unit number */
- if ((len = StrToLong(cmd + rdargs->RDA_Source.CS_CurChr, &unit)) < 0 ||
- unit >= AD_MAXUNITS) {
- errlevel = 20;
- *errstr = ERR_UNIT;
- break;
- }
- rdargs->RDA_Source.CS_CurChr += len;
-
- if (!(adu = adb->ad_Units[unit]))
- /* If there is no opened unit, we init one */
- if (keyword == KEY_QUERY || !(adu = InitUnit(unit))) {
- /* We got no unit structure, there was an initialization
- problem, we must give up */
- *errstr = ERR_INITUNIT;
- errlevel = 20;
- break;
- }
- if (keyword == KEY_UNIT) {
- /* Parse the rest of the line with ParseConfig */
- errlevel = ParseConfig(adu, rdargs, errstr);
- break;
- } else {
- errlevel = ParseQuery(adb->ad_Units[unit], rdargs, errstr, result);
- break;
- }
- case KEY_EXIT:
- /* We try to expunge */
- SetSignal(SIGBREAKF_CTRL_F, SIGBREAKF_CTRL_F);
- break;
- }
- }
- }
-
- if (cmd) FreeMem(cmd, len);
- if (rdargs) FreeDosObject(DOS_RDARGS, rdargs);
-
- return errlevel;
- }
- #endif /* AGREXX */
-
- /*
- * Configuration parameters
- */
- #define CONFIG_ARGS 20 /* # of args in CONFIG_TEMPLATE */
- #define CONFIG_TEMPLATE "WIRE/K" \
- ",MTU/N/K,MINTU/N/K,BPS/N/K,ADDR=ADDRESS/K" \
- ",DELAY/N/K,DEV=DEVIATION/N/K,ERRORS/K/N,LOSS/K/N,DST=DSTUNIT/N"
-
- #define CMD_WIRE 0
- #define CMD_MTU 1 /* Maximum transfer unit */
- #define CMD_MINTU 2 /* Minimum Trransfer unit */
- #define CMD_BPS 3 /* Bits per second */
- #define CMD_ADDR 4 /* Address string */
- #define CMD_DELAY 5 /* Delay in ms */
- #define CMD_DEVIATION 6 /* Deviation in ms */
- #define CMD_ERRORS 7 /* Bit error probability */
- #define CMD_LOSS 8 /* Packet loss probability */
- #define CMD_PPUNIT 9 /* Destination unit */
-
- #define CMD_ALL 10 /* All values queried */
-
- #define WIRE_TEMPLATE "LOOPBACK,ETHERNET,IEEE802,ARCNET" \
- ",LOCALTALK,AMOKNET" \
- ",PPP,SLIP,CSLIP" \
-
- #define WIRE_LOOPBACK 0
- #define WIRE_ETHERNET 1
- #define WIRE_IEEE802 2
- #define WIRE_ARCNET 3
- #define WIRE_LOCALTALK 4
- #define WIRE_AMOKNET 5
- #define WIRE_PPP 6
- #define WIRE_SLIP 7
- #define WIRE_CSLIP 8
-
- #ifdef AGREXX
- #include <exec/initializers.h>
-
- #define MAXQUERYLEN 512
-
- #define QUERY_TEMPLATE "WIRE/S" \
- ",MTU/S,MINTU/S,BPS/S,ADDR=ADDRESS/S" \
- ",DELAY/S,DEV=DEVIATION/S,ERRORS/S,LOSS/S,DST=DSTUNIT/S,ALL/S"
-
- static struct {
- STRPTR title;
- WORD offset;
- enum { nulong, wire, address } type;
- } query_titles[] = {
- { "WIRE", OFFSET(AgnetDevUnit, adu_HardwareType), wire },
- { "MTU", OFFSET(AgnetDevUnit, adu_MaxTU), nulong },
- { "MINTU", OFFSET(AgnetDevUnit, adu_MinTU), nulong },
- { "BPS", OFFSET(AgnetDevUnit, adu_BPS), nulong },
- { "ADDRESS", OFFSET(AgnetDevUnit, adu_Addr), address },
- { "DELAY", OFFSET(AgnetDevUnit, adu_Delay), nulong },
- { "DEVIATION",OFFSET(AgnetDevUnit, adu_Deviation), nulong },
- { "ERRORS", OFFSET(AgnetDevUnit, adu_Errors), nulong },
- { "LOSS", OFFSET(AgnetDevUnit, adu_Loss), nulong },
- { "DSTUNIT", OFFSET(AgnetDevUnit, adu_PPUnit), nulong }
- };
-
- #define AT_OFFSET(X,Y) ((UBYTE *)X + Y)
- #define ULONG_AT(X,Y) (*(ULONG*)AT_OFFSET(X,Y))
-
- static struct {
- ULONG type;
- STRPTR name;
- } wirenames[] = {
- { S2WireType_LoopBack, "Loopback" },
- { S2WireType_Ethernet, "Ethernet" },
- { S2WireType_IEEE802, "IEEE802" },
- { S2WireType_Arcnet, "Arcnet" },
- { S2WireType_LocalTalk, "LocalTalk" },
- { S2WireType_AmokNet, "AmokNet" },
- { S2WireType_PPP, "PPP" },
- { S2WireType_SLIP, "SLIP" },
- { S2WireType_CSLIP, "CSLIP" },
- { S2WireType_LoopBack, "Unknown" }
- };
- #endif
-
- /*
- * Parse a configuration command
- * adu = NULL if parse an ARexx command
- * return differs from zero if an error
- */
- static LONG
- ParseConfig(struct AgnetDevUnit *adu, struct RDArgs *rdargs,
- STRPTR *errormessage)
- {
- LONG args[CONFIG_ARGS] = {0};
- LONG error;
- LONG ppunit;
- UBYTE address[MAX_ADDR_BYTES] = {0};
- UWORD addrfieldsize;
- ULONG hardwaretype, maxtu, mintu, bps, delay, deviation, errors, loss;
- BOOL virgin;
- LONG wire;
-
- /* Parse the file or the line...*/
- rdargs = ReadArgs(CONFIG_TEMPLATE, args, rdargs);
- if (error = !rdargs) {
- if (errormessage)
- *errormessage = ERR_SYNTAX;
- return error;
- }
-
- hardwaretype = adu->adu_HardwareType;
- addrfieldsize = adu->adu_AddrFieldSize;
- ppunit = adu->adu_PPUnit;
- maxtu = adu->adu_MaxTU;
- mintu = adu->adu_MinTU;
- bps = adu->adu_BPS;
- delay = adu->adu_Delay;
- deviation = adu->adu_Deviation;
- errors = adu->adu_Errors;
- loss = adu->adu_Loss ;
- memcpy(address, adu->adu_Addr, MAX_ADDR_BYTES);
-
- virgin = hardwaretype == UNINITIALIZED;
-
- if (args[CMD_WIRE]) {
- wire = FindArg(WIRE_TEMPLATE, args[CMD_WIRE]);
- } else if (virgin) {
- wire = S2WireType_Ethernet;
- }
-
- if (args[CMD_WIRE] || virgin) {
- switch (wire) {
- case WIRE_LOOPBACK:
- /* This is simple loopback type */
- hardwaretype = S2WireType_LoopBack;
- addrfieldsize = 0; /* No addresses */
- maxtu = 1024;
- bps = 100000000; /* it's fast like a hell...*/
- mintu = 0;
- /* There is no need for address but we zero it anyways */
- memset(address, 0, MAX_ADDR_BYTES);
- break;
-
- case WIRE_ETHERNET:
- /* This is default */
- hardwaretype = S2WireType_Ethernet;
- addrfieldsize = 48;
- maxtu = 1500;
- bps = 10000000; /* 10 Mb/s */
- mintu = 1;
- /* Ethernet address is same as unit number */
- memset(address + 6, 0, MAX_ADDR_BYTES-2);
- memcpy(address, "ETHER", 5);
- address[5] = adu->adu_UnitNum;
- ppunit = -1;
- break;
-
- case WIRE_IEEE802:
- /* Wiretype is IEEE802 */
- hardwaretype = S2WireType_IEEE802;
- addrfieldsize = 48;
- maxtu = 1500;
- bps = 10000000; /* 10 Mb/s */
- mintu = 1;
- /* IEEE802 address is same as unit number */
- memset(address+6, 0, MAX_ADDR_BYTES-6);
- memcpy(address, "IEEE8", 5);
- address[5] = adu->adu_UnitNum;
- ppunit = -1;
- break;
-
- case WIRE_ARCNET:
- hardwaretype = S2WireType_Arcnet;
- addrfieldsize = 8;
- maxtu = 506;
- bps = 5000000L; /* 5 Mb/s */
- mintu = 1;
- /* Arcnet address is got from unit number */
- memset(adu->adu_Addr, 0, MAX_ADDR_BYTES);
- adu->adu_Addr[0] = 255 - adu->adu_UnitNum;
- ppunit = -1;
- break;
-
- case WIRE_LOCALTALK:
- /* Don't know much, but... */
- hardwaretype = S2WireType_LocalTalk;
- addrfieldsize = 8;
- maxtu = 256;
- bps = 128000L; /* 128 kb/s */
- mintu = 1;
- /* Localnet address is got from unit number */
- memset(address, 0, MAX_ADDR_BYTES);
- address[0] = adu->adu_UnitNum;
- ppunit = -1;
- break;
-
- /* Amoknet parameters are all got with RaHi method */
- case WIRE_AMOKNET:
- /* Don't know much, but... */
- hardwaretype = S2WireType_AmokNet;
- addrfieldsize = 8;
- maxtu = 512;
- bps = 128000L; /* 128 kb/s */
- mintu = 1;
- /* Amoknet address is got from unit number */
- memset(address, 0, MAX_ADDR_BYTES);
- address[0] = adu->adu_UnitNum;
- break;
-
- case WIRE_PPP:
- hardwaretype = S2WireType_PPP; goto serials;
- case WIRE_SLIP:
- hardwaretype = S2WireType_SLIP; goto serials;
- case WIRE_CSLIP:
- hardwaretype = S2WireType_CSLIP;
- serials:
- addrfieldsize = 32;
- maxtu = 1006;
- bps = 9600L; /* 9600 b/s */
- mintu = 1;
- /* SLIP address is set during config */
- memset(address, 0, MAX_ADDR_BYTES);
- break;
- default:
- if (errormessage)
- *errormessage = ERR_WIRE;
- error = 5;
- goto free_and_exit;
- }
- }
- if (args[CMD_MTU]) {
- maxtu = *(ULONG *)args[CMD_MTU];
- }
-
- if (args[CMD_MINTU]) {
- mintu = *(ULONG *)args[CMD_MINTU];
- }
-
- if (args[CMD_BPS]) {
- bps = *(ULONG *)args[CMD_BPS];
- }
-
- if (args[CMD_ADDR]) {
- memset(address, 0, MAX_ADDR_BYTES);
- if (!GetBitAddress(address, (UBYTE *)args[CMD_ADDR], addrfieldsize)) {
- if (errormessage)
- *errormessage = ERR_ADDRESS;
- error = 7;
- goto free_and_exit;
- }
- }
-
- if (args[CMD_DELAY]) {
- delay = *(ULONG *)args[CMD_DELAY];
- /* maximum delay is 0x800000 ms, that is fairly over an hour */
- if (delay >= 0x800000)
- delay = 0x7fffff;
- }
-
- if (args[CMD_DEVIATION]) {
- deviation = *(ULONG *)args[CMD_DEVIATION];
- }
-
- if (args[CMD_ERRORS]) {
- errors = *(ULONG *)args[CMD_ERRORS];
- if (errors > ERRORS_MAX) {
- error = 5;
- *errormessage = ERR_VALUE;
- goto free_and_exit;
- }
- }
-
- if (args[CMD_LOSS]) {
- loss = *(ULONG *)args[CMD_LOSS];
- if (loss > LOSS_MAX) {
- error = 5;
- *errormessage = ERR_VALUE;
- goto free_and_exit;
- }
- }
-
- if (args[CMD_PPUNIT]) {
- ppunit = *(ULONG *)args[CMD_PPUNIT];
- }
-
- if (!virgin) {
- LockUnit(adu);
- /*
- * Changing the hardware type or reducing the MTU requires
- * that the unit is not currently open
- */
- if ((adu->adu_HardwareType != hardwaretype ||
- adu->adu_MaxTU > maxtu) &&
- adu->adu_Unit.unit_OpenCnt != 0 ) {
- UnlockUnit(adu);
- error = 5;
- *errormessage = ERR_OPEN;
- goto free_and_exit;
- }
- }
-
- adu->adu_HardwareType = hardwaretype;
- adu->adu_AddrFieldSize = addrfieldsize;
- adu->adu_PPUnit = ppunit;
- adu->adu_MinTU = mintu;
- adu->adu_BPS = bps;
- adu->adu_Delay = delay;
- adu->adu_Deviation = deviation;
- adu->adu_Errors = errors;
- adu->adu_Loss = loss;
- memcpy(adu->adu_Addr, address, MAX_ADDR_BYTES);
-
- /*
- * Enlarging the MTU requires offlining the device temporarily
- */
- if (!virgin && adu->adu_MaxTU < maxtu) {
- DoOffline(adu);
- adu->adu_MaxTU = maxtu;
- DoOnline(adu);
- } else {
- adu->adu_MaxTU = maxtu;
- }
-
- if (!virgin)
- UnlockUnit(adu);
-
- free_and_exit:
- if (rdargs)
- FreeArgs(rdargs);
- return error;
- }
-
- #ifdef AGREXX
- /*
- * Parse Query Command
- */
- static LONG
- ParseQuery(struct AgnetDevUnit *adu,
- struct RDArgs *rdargs,
- STRPTR *errstr,
- STRPTR *result)
- {
- LONG errlevel = 0;
- LONG args[CONFIG_ARGS] = {0};
- char res[MAXQUERYLEN];
- struct CSource csres = { NULL, sizeof(res), 0L };
- BOOL all;
- LONG i;
-
- csres.CS_Buffer = res;
-
- /* Parse the file or the line...*/
- rdargs = ReadArgs(QUERY_TEMPLATE, args, rdargs);
- if (errlevel = !rdargs) {
- *errstr = ERR_SYNTAX;
- return errlevel;
- }
-
- all = args[CMD_ALL];
- for (i = CMD_WIRE; i < CMD_ALL; i++)
- if (all || args[i]) {
- if (csres.CS_CurChr != 0 && csres.CS_CurChr < csres.CS_Length)
- res[csres.CS_CurChr++] = ' ';
- switch (query_titles[i].type) {
- case nulong:
- csprintf(&csres, "%s=%ld", query_titles[i].title,
- ULONG_AT(adu, query_titles[i].offset));
- break;
-
- case wire:
- {
- int j; int type = ULONG_AT(adu, query_titles[i].offset);
- for (j = 0; j < sizeof(wirenames)/sizeof(wirenames[0]) - 2; j++)
- if (wirenames[j].type == type)
- break;
- csprintf(&csres, "%s=%s", query_titles[i].title,
- wirenames[j].name);
- }
- break;
-
- case address:
- csprintf(&csres, "%s=%s", query_titles[i].title,
- SanaSprintf(AT_OFFSET(adu,query_titles[i].offset),
- adu->adu_AddrFieldSize + 7 >> 3));
- break;
- }
- }
-
- *result = CreateArgstring(res, csres.CS_CurChr);
- if (!*result) {
- *errstr = ERR_MEMORY;
- return 40;
- }
- return errlevel;
- }
-
- #endif /* AGREXX */
-
- /*
- * Read hexadecimal address string into array.
- *
- * UBYTE *addr = address array
- * UBYTE *string = hexadecimal address string,
- * each byte sparated by colon (":")
- * LONG bitsize = address length in bits
- *
- * Return true if no errors.
- * If there is error, may trash the address.
- */
- static BOOL
- GetBitAddress(UBYTE *addr, UBYTE *string, LONG bitsize)
- {
- LONG bitsperbyte; UWORD next; UWORD chars;
- UBYTE c;
-
- memset(addr, 0, (bitsize + 7) >> 3);
-
- while (bitsize > 0) {
- bitsperbyte = bitsize < 8 ? bitsize : 8;
- chars = next = 0;
- while ((c = *string - '0') <= 9
- || (c = c - 'A' + '0' + 10) >= 9 && c < 16 /*ABCDEF*/
- || (c = c - 'a' + 'A') >= 9 && c < 16) /*abcdef*/ {
- chars++; string++;
- next = (next << 4) + c;
- if (next >= 1 << bitsperbyte)
- return FALSE;
- }
- if (!chars)
- return FALSE;
-
- *addr++ = next << (8 - bitsperbyte);
- bitsize -= bitsperbyte;
- if (*string != ':')
- break;
- string++;
- }
- if (bitsize || *string) return FALSE;
- return TRUE;
- }
-
- /*
- * Print Hardware Address
- */
- static char *
- SanaSprintf(register char *ap, int len)
- {
- const char *digits = "0123456789ABCDEF";
- register i;
- static char addrbuf[17*3];
- register unsigned char *cp = addrbuf;
-
- for (i = 0; i < len; ) {
- *cp++ = digits[*ap >> 4];
- *cp++ = digits[*ap++ & 0xf];
- i++;
- if (i < len)
- *cp++ = ':';
- }
- *cp = 0;
- return (addrbuf);
- }
-
- void ASM stuffchar(REG(d0) char ch, REG(a3) struct CSource * sc)
- {
- if (sc->CS_CurChr < sc->CS_Length
- && (sc->CS_Buffer[sc->CS_CurChr] = ch))
- sc->CS_CurChr++;
- }
-
- static ULONG
- csprintf(struct CSource *buf, const char *fmt, ...)
- {
- ULONG start = buf->CS_CurChr;
- va_list ap;
-
- va_start(ap, fmt);
- RawDoFmt((STRPTR)fmt, ap, stuffchar, buf);
- va_end(ap);
-
- buf->CS_Buffer[buf->CS_CurChr] = '\0';
- return buf->CS_CurChr - start;
- }
-
-