home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * UUSER.C UUSER:devicename/unitnumber/options
- * UUSER:serial.device/0/R1000
- *
- * $Header: Beta:src/uucp/src/uuser/RCS/uuser.c,v 1.1 90/02/02 12:10:15 dillon Exp Locker: dillon $
- *
- * (C) Copyright 1989-1990 by Matthew Dillon, All Rights Reserved.
- *
- * options:
- * Rn Set read timeout when no data available to n millisecs
- * C0 Ignore carrier detect
- *
- * features:
- * 1K asynchronous write capability (write 0 bytes to sync up)
- * programmable read-timeout (Getty starts procs up w/ 1sec to)
- *
- * combined together, you can easily implement 100% efficient
- * protocols even with that 1 second read timeout!
- */
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <devices/serial.h>
- #include <devices/timer.h>
- #include <libraries/dos.h>
- #include <libraries/dosextens.h>
- #include <libraries/filehandler.h>
- #include <hardware/cia.h>
- #include <stdio.h>
- #include "protos.h"
- #include "version.h"
-
- IDENT(".02");
-
- #define WRITEBUFSIZE 1024
- #define MPC (MEMF_PUBLIC|MEMF_CLEAR) /* options to AllocMem() */
-
- #define BTOC(x, type) ((type *)((long)x << 2))
- #define CTOB(x) ((BPTR)((long)x >> 2))
-
- #define DOS_FALSE 0L
- #define DOS_TRUE -1L
-
- typedef struct IOExtSer IOS;
- typedef struct timerequest IOT;
- typedef struct IORequest IOR;
- typedef struct timeval TimeVal;
-
- typedef struct FileLock LOCK;
- typedef struct DosPacket Packet;
- typedef struct Process PROC;
- typedef struct DeviceNode DEVNODE;
- typedef struct FileHandle FH;
- typedef struct Message MSG;
- typedef struct Node NODE;
- typedef struct List LIST;
- typedef struct MsgPort PORT;
-
- typedef struct SHandle {
- NODE Node;
- IOT Iot; /* wait-for-char and read req */
- IOS Ios;
- IOS Iosr; /* 1005 */
- IOS Iosw; /* 1005,1006 */
- char IotIP;
- char IosrIP;
- char IoswIP;
- char RxIn[1]; /* one char buffer */
- char *TxOut; /* asynch write buffer */
- Packet *RPacket; /* current pending read packet */
- Packet *WPacket; /* current pending write packet */
- short Flags;
- LIST RxWait; /* requests waiting for data */
- LIST TxWait; /* requests waiting to write */
- LIST CxWait; /* wait for char */
- TimeVal ReadTo;
- } SHandle;
-
- #define HF_IGNORECD 0x01
- #define HF_CDLOST 0x02
- #define HF_RTO 0x04
- #define HF_DONTLOCK 0x08 /* if G option for from-getty */
-
- extern Packet *taskwait(); /* wait for a message */
-
- /* long SysBase; /* required to make Exec calls */
- char ScrBuf[256]; /* Scratch buffer */
- PORT *IoSink;
- LIST HanList;
- LIST NodList;
- IOT Iot; /* Iot master, also used for CD */
- char IotIP;
-
- void AttemptRead();
- void AttemptWrite();
- void AbortPackets();
- void StartTimer();
-
- void
- _main()
- {
- PROC *myproc;
- DEVNODE *mynode;
- UBYTE notdone;
- long mask;
-
- /* SysBase = *(long *)4; */
- IoSink = CreatePort(NULL, 0L);
- NewList(&HanList);
- NewList(&NodList);
-
- Iot.tr_node.io_Message.mn_ReplyPort = IoSink;
- OpenDevice("timer.device", UNIT_VBLANK, &Iot.tr_node, 0L);
- Iot.tr_node.io_Command = TR_ADDREQUEST;
- Iot.tr_time.tv_secs = 4;
- Iot.tr_time.tv_micro= 0;
- SendIO(&Iot);
- IotIP = 1;
-
- myproc = (PROC *)FindTask(0L);
-
- /*
- * INITIAL STARTUP MESSAGE
- */
-
- {
- Packet *mypkt;
-
- mypkt = taskwait(myproc);
- mynode = BTOC(mypkt->dp_Arg3, DEVNODE);
- mynode->dn_Task = &myproc->pr_MsgPort;
- returnpkt(mypkt, myproc, DOS_TRUE, 0L);
- }
-
- loop:
- notdone = 1;
- mask = (1 << IoSink->mp_SigBit) | (1 << myproc->pr_MsgPort.mp_SigBit);
- while (notdone) {
- Packet *mypkt; /* dos packet received */
- IOR *ior;
- SHandle *handle;
- long type; /* type of packet */
-
- ior = (IOR *)GetMsg(IoSink);
- mypkt = (Packet *)GetMsg(&myproc->pr_MsgPort);
- if (mypkt)
- mypkt = (Packet *)(((MSG *)mypkt)->mn_Node.ln_Name);
- while (mypkt == NULL && ior == NULL) {
- Wait(mask);
- ior = (IOR *)GetMsg(IoSink);
- mypkt = (Packet *)GetMsg(&myproc->pr_MsgPort);
- if (mypkt)
- mypkt = (Packet *)(((MSG *)mypkt)->mn_Node.ln_Name);
- }
-
- /*
- * Make sure there is at least one free node in node list
- */
-
- if (NodList.lh_Head == (NODE *)&NodList.lh_Tail) {
- NODE *pknode = AllocMem(sizeof(NODE), MPC);
- AddTail(&NodList, pknode);
- }
-
- /*
- * Returned IO request, sift through lists to find it.
- */
-
- if (ior) {
- if (ior == &Iot.tr_node) { /* Check for carrier lost */
- for (handle = (SHandle *)HanList.lh_Head; handle != (SHandle *)&HanList.lh_Tail; handle = (SHandle *)handle->Node.ln_Succ) {
- if (!(handle->Flags & HF_IGNORECD) && !(handle->Flags & HF_CDLOST)) {
- handle->Ios.IOSer.io_Command = SDCMD_QUERY;
- DoIO((IOR *)&handle->Ios);
- if (handle->Ios.io_Status & CIAF_COMCD) {
- handle->Flags |= HF_CDLOST;
- AbortPackets(handle, myproc);
- }
- }
- }
- if (HanList.lh_Head == (NODE *)&HanList.lh_Tail) {
- IotIP = 0;
- } else {
- Iot.tr_time.tv_secs = 4;
- Iot.tr_time.tv_micro= 0;
- SendIO(&Iot.tr_node);
- IotIP = 1;
- }
- } else
- for (handle = (SHandle *)HanList.lh_Head; handle != (SHandle *)&HanList.lh_Tail; handle = (SHandle *)handle->Node.ln_Succ) {
- if (ior == (IOR *)&handle->Iosr) {
- handle->IosrIP = 0;
- if (handle->RPacket) {
- returnpkt(handle->RPacket, myproc, handle->Iosr.IOSer.io_Actual, 0L);
- handle->RPacket = NULL;
- }
- if (handle->IotIP) {
- AbortIO(&handle->Iot.tr_node);
- WaitIO(&handle->Iot.tr_node);
- handle->IotIP = 0;
- }
- AttemptRead(handle, myproc);
- }
- if (ior == (IOR *)&handle->Iosw) {
- handle->IoswIP = 0;
- if (handle->WPacket) {
- handle->Iosw.IOSer.io_Data = (APTR)handle->TxOut;
- handle->Iosw.IOSer.io_Length= handle->WPacket->dp_Arg3 - handle->WPacket->dp_Res1;
- SendIO((IOR *)&handle->Iosw);
- handle->IoswIP = 1;
- handle->WPacket->dp_Res1 = handle->WPacket->dp_Arg3;
- returnpktplain(handle->WPacket, myproc);
- handle->WPacket = NULL;
- } else {
- AttemptWrite(handle, myproc);
- }
- }
- if (ior == (IOR *)&handle->Iot.tr_node) {
- handle->IotIP = 0;
- if ((handle->Flags & HF_RTO) && handle->IosrIP) {
- AbortIO((IOR *)&handle->Iosr);
- }
- }
- }
- }
-
- if (mypkt) {
- mypkt->dp_Res1 = DOS_TRUE; /* default return value */
- mypkt->dp_Res2 = 0; /* default no error */
- type = mypkt->dp_Type; /* packet type */
-
- /*
- * Extract pipe pointer (only applies to read/write)
- */
-
- handle = (SHandle *)mypkt->dp_Arg1; /* READ/WRITE only */
-
- switch(type) {
- case ACTION_FINDINPUT:
- case ACTION_FINDOUTPUT:
- case ACTION_FINDUPDATE:
- if (IotIP == 0)
- StartTimer(4);
- {
- FH *fh = BTOC(mypkt->dp_Arg1, FH);
- char *path = BTOC(mypkt->dp_Arg3, char);
- char *unit;
- long n;
-
- movmem(path + 1, ScrBuf, *path);
- ScrBuf[*path] = 0;
- path = ScrBuf;
-
- handle = AllocMem(sizeof(SHandle), MPC);
-
- if (strcmp(ScrBuf, "*") == 0)
- strcpy(ScrBuf, "serial.device/0");
- for (unit = path; *unit && *unit != '/'; ++unit) {
- if (*unit == ':')
- path = unit + 1;
- }
- if (*unit == '/') {
- char *opts;
-
- *unit = 0;
- ++unit;
- for (opts = unit; *opts && *opts != '/'; ++opts);
- while (*opts) {
- n = atoi(opts + 1);
- switch(*opts) {
- case '/':
- break;
- case 'R':
- handle->ReadTo.tv_secs = n / 1000;
- handle->ReadTo.tv_micro= (n % 1000) * 1000;
- handle->Flags |= HF_RTO;
- break;
- case 'C':
- handle->Flags |= HF_IGNORECD;
- break;
- case 'G':
- if (n)
- handle->Flags |= HF_DONTLOCK;
- break;
- }
- ++opts;
- }
- }
-
- /* proc = (PROC *)mypkt->dp_Port->mp_SigTask; */
-
- /*
- * Open the device
- */
-
- handle->Ios.IOSer.io_Message.mn_ReplyPort = IoSink;
- handle->Ios.io_SerFlags = SERF_XDISABLED | SERF_RAD_BOOGIE | SERF_SHARED;
- if (OpenDevice(path, atoi(unit), (IOR *)&handle->Ios, 0L)) {
- FreeMem(handle, sizeof(SHandle));
- mypkt->dp_Res1 = DOS_FALSE;
- mypkt->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
- returnpktplain(mypkt, myproc);
- break;
- }
- fh->fh_Arg1 = (long)handle;
- fh->fh_Port = (struct MsgPort *)DOS_TRUE;
-
- handle->Iosr = handle->Ios;
- handle->Iosw = handle->Ios;
- handle->Iosr.IOSer.io_Command = CMD_READ;
- handle->Iosw.IOSer.io_Command = CMD_WRITE;
- handle->Iot = Iot;
- NewList(&handle->RxWait);
- NewList(&handle->TxWait);
- NewList(&handle->CxWait);
- AddTail(&HanList, &handle->Node);
- returnpktplain(mypkt, myproc);
- }
- break;
- case ACTION_END:
- Remove(&handle->Node);
- AbortPackets(handle, myproc);
- if (handle->IotIP) {
- AbortIO((IOR *)&handle->Iot);
- WaitIO((IOR *)&handle->Iot);
- handle->IotIP = 0;
- }
- CloseDevice((IOR *)&handle->Ios);
- returnpktplain(mypkt, myproc);
- if (handle->TxOut)
- FreeMem(handle->TxOut, WRITEBUFSIZE);
- FreeMem(handle, sizeof(SHandle));
- break;
- case ACTION_READ:
- {
- NODE *pknode = RemHead(&NodList);
- mypkt->dp_Res1 = 0;
- pknode->ln_Name = (char *)mypkt;
- AddTail(&handle->RxWait, pknode);
- AttemptRead(handle, myproc);
- }
- break;
- case ACTION_WRITE:
- {
- NODE *pknode = RemHead(&NodList);
- mypkt->dp_Res1 = 0;
- pknode->ln_Name = (char *)mypkt;
- AddTail(&handle->TxWait, pknode);
- AttemptWrite(handle, myproc);
- }
- break;
- case ACTION_WAIT_CHAR:
- default:
- returnpkt(mypkt, myproc, DOS_FALSE, ERROR_ACTION_NOT_KNOWN);
- break;
- }
- }
- }
-
- /*
- * Can only exit if no messages pending. There might be a window
- * here, but there is nothing that can be done about it.
- */
-
- Forbid();
- if (taskpktrdy(myproc)) {
- Permit();
- goto loop;
- }
- mynode->dn_Task = FALSE;
- Permit();
-
- if (IotIP) {
- AbortIO(&Iot.tr_node);
- WaitIO(&Iot.tr_node);
- }
- CloseDevice(&Iot.tr_node);
-
- /* we are a process "so we fall off the end of the world" */
- /* MUST fall through */
- }
-
- void
- AttemptRead(handle, myproc)
- SHandle *handle;
- PROC *myproc;
- {
- Packet *mypkt;
- NODE *pknode;
-
- if (handle->Flags & HF_CDLOST) {
- AbortPackets(handle, myproc);
- return;
- }
- loop:
- if (handle->IosrIP == 0 && (pknode = RemHead(&handle->RxWait))) {
- long n;
-
- AddTail(&NodList, pknode);
-
- mypkt = (Packet *)pknode->ln_Name;
-
- /*
- * special case. If you read 0 bytes, 0 is returned if data
- * is pending, else -1, and NO timeout occurs.
- */
-
- handle->Ios.IOSer.io_Command = SDCMD_QUERY;
- DoIO((IOR *)&handle->Ios);
-
- if (mypkt->dp_Arg3 == 0) {
- if (handle->Ios.IOSer.io_Actual > 0)
- returnpkt(mypkt, myproc, DOS_FALSE, 0L); /* 0=data rdy */
- else
- returnpkt(mypkt, myproc, DOS_TRUE, 0L); /* -1=data not rdy */
- goto loop;
- }
-
- if ((n = handle->Ios.IOSer.io_Actual) > 0) {
- if (n > mypkt->dp_Arg3)
- n = mypkt->dp_Arg3;
- handle->Iosr.IOSer.io_Data = (APTR)mypkt->dp_Arg2;
- handle->Iosr.IOSer.io_Length = n;
- DoIO((IOR *)&handle->Iosr);
- mypkt->dp_Res1 = handle->Iosr.IOSer.io_Actual;
- returnpktplain(mypkt, myproc);
- goto loop;
- }
- handle->Iosr.IOSer.io_Data = (APTR)mypkt->dp_Arg2;
- handle->Iosr.IOSer.io_Length = 1;
- SendIO((IOR *)&handle->Iosr);
- handle->IosrIP = 1;
- handle->RPacket = mypkt;
-
- if (handle->Flags & HF_RTO) {
- if (handle->IotIP) {
- AbortIO(&handle->Iot.tr_node);
- WaitIO(&handle->Iot.tr_node);
- }
- handle->Iot.tr_time = handle->ReadTo;
- SendIO(&handle->Iot.tr_node);
- handle->IotIP = 1;
- }
- }
- }
-
- void
- AttemptWrite(handle, myproc)
- SHandle *handle;
- PROC *myproc;
- {
- Packet *mypkt;
- NODE *pknode;
-
- if (handle->Flags & HF_CDLOST) {
- AbortPackets(handle, myproc);
- return;
- }
- if (handle->IoswIP == 0 && (pknode = RemHead(&handle->TxWait))) {
- AddTail(&NodList, pknode);
-
- mypkt = (Packet *)pknode->ln_Name;
-
- if (handle->TxOut == NULL)
- handle->TxOut = AllocMem(WRITEBUFSIZE, MPC);
-
- if (mypkt->dp_Arg3 <= WRITEBUFSIZE) { /* fully asynch */
- movmem((char *)mypkt->dp_Arg2, handle->TxOut, mypkt->dp_Arg3);
- handle->Iosw.IOSer.io_Data = (APTR)handle->TxOut;
- handle->Iosw.IOSer.io_Length = mypkt->dp_Arg3;
- SendIO(&handle->Iosw);
- mypkt->dp_Res1 = mypkt->dp_Arg3;
- returnpktplain(mypkt, myproc);
- handle->WPacket = NULL;
- } else { /* semi-asynch */
- long n = mypkt->dp_Arg3 - WRITEBUFSIZE;
- handle->Iosw.IOSer.io_Data = (APTR)mypkt->dp_Arg2;
- handle->Iosw.IOSer.io_Length = n;
- SendIO(&handle->Iosw);
- movmem((char *)mypkt->dp_Arg2 + n, handle->TxOut, WRITEBUFSIZE);
- mypkt->dp_Res1 += n;
- handle->WPacket = mypkt;
- }
- handle->IoswIP = 1;
- }
- }
-
- void
- AbortPackets(handle, myproc)
- SHandle *handle;
- {
- NODE *pknode;
- Packet *mypkt;
-
- if (handle->RPacket)
- returnpktplain(handle->RPacket, myproc);
-
- if (handle->WPacket)
- returnpktplain(handle->WPacket, myproc);
-
- if (handle->IosrIP) {
- AbortIO((IOR *)&handle->Iosr);
- WaitIO((IOR *)&handle->Iosr);
- handle->IosrIP = 0;
- }
- if (handle->IoswIP) {
- AbortIO((IOR *)&handle->Iosw);
- WaitIO((IOR *)&handle->Iosw);
- handle->IoswIP = 0;
- }
-
- handle->RPacket = NULL;
- handle->WPacket = NULL;
-
- while (pknode = RemHead(&handle->RxWait)) {
- mypkt = (Packet *)pknode->ln_Name;
- if (mypkt->dp_Arg3 == 0)
- mypkt->dp_Res1 = 0; /* for poll, return data rdy */
- else
- mypkt->dp_Res1 = -1;
- returnpktplain(mypkt, myproc);
- AddTail(&NodList, pknode);
- }
-
- while (pknode = RemHead(&handle->TxWait)) {
- mypkt = (Packet *)pknode->ln_Name;
- mypkt->dp_Res1 = -1;
- returnpktplain(mypkt, myproc);
- AddTail(&NodList, pknode);
- }
- }
-
- void
- StartTimer(secs)
- {
- if (IotIP) {
- AbortIO(&Iot.tr_node);
- WaitIO(&Iot.tr_node);
- }
- Iot.tr_time.tv_secs = secs;
- Iot.tr_time.tv_micro= 0;
- SendIO(&Iot.tr_node);
- IotIP = 1;
- }
-
-
-