home *** CD-ROM | disk | FTP | other *** search
- /* mdio.c - bmodem i/o routines for the Amiga/Aztec C */
- /*
- by David Betz, BYTE Magazine/BIX
- */
-
- #include <stdio.h>
- #include <setjmp.h>
- #include <exec/exec.h>
- #include <libraries/dos.h>
- #include <devices/serial.h>
- #include <devices/timer.h>
- #include <functions.h>
-
- /* definitions */
- #define IBSIZE 512 /* input buffer size */
-
- /* return status codes */
- #define DT_TIME -1
-
- /* local variables */
- static int readOpen = FALSE;
- static struct IOExtSer *readReq = NULL;
- static int timerOpen = FALSE;
- static struct timerequest *timerReq = NULL;
- static int writeOpen = FALSE;
- static struct IOExtSer *writeReq = NULL;
- static int inputOpen = FALSE;
- static unsigned char inbuf[IBSIZE],*inptr;
- static int incnt;
-
- /* external variables */
- extern jmp_buf xfr_error;
-
- /* md_init - common initialization routine */
- md_init(baud)
- long baud;
- {
- /* create a read request block */
- readReq = (struct IOExtSer *)
- AllocMem((long)sizeof(struct IOExtSer),MEMF_PUBLIC|MEMF_CLEAR);
- if (readReq == NULL)
- cleanup("can't create read request block");
- readReq->io_SerFlags = SERF_SHARED;
-
- /* create a reply port for the read request block */
- readReq->IOSer.io_Message.mn_ReplyPort = CreatePort("ReadReply",0L);
- if (readReq->IOSer.io_Message.mn_ReplyPort == NULL)
- cleanup("can't create read reply port");
-
- /* open the serial device - input */
- if (OpenDevice("serial.device",0L,readReq,0L))
- cleanup("can't open serial device for input");
- readOpen = TRUE;
-
- /* set the baud rate and character size */
- readReq->IOSer.io_Command = SDCMD_SETPARAMS;
- readReq->io_CtlChar = 0x13150506L;
- readReq->io_SerFlags = SERF_XDISABLED;
- readReq->io_ExtFlags = 0;
- readReq->io_Baud = baud;
- readReq->io_ReadLen = 8;
- readReq->io_WriteLen = 8;
- readReq->io_StopBits = 1;
- DoIO(readReq);
-
- /* create a timer request block */
- timerReq = (struct timerequest *)
- AllocMem((long)sizeof(struct timerequest),MEMF_PUBLIC|MEMF_CLEAR);
- if (timerReq == NULL)
- cleanup("can't create timer request block");
-
- /* create a reply port for the timer request block */
- timerReq->tr_node.io_Message.mn_ReplyPort = CreatePort("TimerReply",0L);
- if (timerReq->tr_node.io_Message.mn_ReplyPort == NULL)
- cleanup("can't create timer reply port");
-
- /* open the timer device */
- if (OpenDevice("timer.device",UNIT_VBLANK,timerReq,0L))
- cleanup("can't open timer device");
- timerOpen = TRUE;
-
- /* setup for a timer request */
- timerReq->tr_node.io_Command = TR_ADDREQUEST;
-
- /* create a write request block */
- writeReq = (struct IOExtSer *)
- AllocMem((long)sizeof(struct IOExtSer),MEMF_PUBLIC|MEMF_CLEAR);
- if (writeReq == NULL)
- cleanup("can't create write request block");
- writeReq->io_SerFlags = SERF_SHARED;
-
- /* create a reply port for the write request block */
- writeReq->IOSer.io_Message.mn_ReplyPort = CreatePort("WriteReply",0L);
- if (writeReq->IOSer.io_Message.mn_ReplyPort == NULL)
- cleanup("can't create write reply port");
-
- /* open the serial device - output */
- if (OpenDevice("serial.device",0L,writeReq,0L))
- cleanup("can't open serial device for output");
- writeOpen = TRUE;
-
- /* input buffer starts out empty */
- incnt = 0;
- }
-
- /* cleanup - cleanup and exit after an error */
- cleanup(msg)
- char *msg;
- {
- fprintf(stderr,"error: %s\n",msg);
- md_done();
- exit(1);
- }
-
- /* md_done - terminate modem communications */
- md_done()
- {
- /* delete the read reply port */
- if (readReq != NULL && readReq->IOSer.io_Message.mn_ReplyPort)
- DeletePort(readReq->IOSer.io_Message.mn_ReplyPort);
-
- /* close the read request and free the memory */
- if (readOpen)
- CloseDevice(readReq);
- if (readReq)
- FreeMem(readReq,(long)sizeof(struct IOExtSer));
-
- /* delete the timer reply port */
- if (timerReq != NULL && timerReq->tr_node.io_Message.mn_ReplyPort)
- DeletePort(timerReq->tr_node.io_Message.mn_ReplyPort);
-
- /* close the timer request and free the memory */
- if (timerOpen)
- CloseDevice(timerReq);
- if (timerReq)
- FreeMem(timerReq,(long)sizeof(struct timerequest));
-
- /* delete the write reply port */
- if (writeReq != NULL && writeReq->IOSer.io_Message.mn_ReplyPort)
- DeletePort(writeReq->IOSer.io_Message.mn_ReplyPort);
-
- /* close the write request and free the memory */
- if (writeOpen)
- CloseDevice(writeReq);
- if (writeReq)
- FreeMem(writeReq,(long)sizeof(struct IOExtSer));
- }
-
- /* md_get - get a character with timeout */
- int md_get(tmo)
- int tmo;
- {
- long mask,rmask;
-
- /* check for a buffered character */
- if (--incnt >= 0)
- return (*inptr++);
-
- /* check for buffered characters */
- if (GetBufferedCharacters() > 0) {
- --incnt;
- return (*inptr++);
- }
-
- /* set the timeout timer */
- timerReq->tr_time.tv_secs = tmo;
- timerReq->tr_time.tv_micro = 0;
- SendIO(timerReq);
-
- /* setup to read a single character */
- SetupRead();
-
- /* compute the signal mask */
- mask = (1L << readReq->IOSer.io_Message.mn_ReplyPort->mp_SigBit)
- | (1L << timerReq->tr_node.io_Message.mn_ReplyPort->mp_SigBit)
- | SIGBREAKF_CTRL_C;
-
- /* wait for a character or a timeout */
- for (;;) {
-
- /* wait for the read request to complete or timeout */
- rmask = Wait(mask);
-
- /* check for the abort signal */
- if (rmask & SIGBREAKF_CTRL_C) {
- AbortIO(timerReq); /* abort the timer request */
- WaitIO(timerReq);
- AbortIO(readReq); /* abort the read request */
- WaitIO(readReq);
- longjmp(xfr_error,1);
- }
-
- /* check for timer completion */
- if (CheckIO(timerReq)) {
- WaitIO(timerReq); /* dequeue the request */
- AbortIO(readReq); /* abort the read request */
- WaitIO(readReq); /* and wait for abort to complete */
- return (DT_TIME); /* return a timeout indication */
- }
-
- /* check for read completion */
- if (CheckIO(readReq)) {
- WaitIO(readReq); /* dequeue the request */
- if (readReq->IOSer.io_Actual == 1L) {
- AbortIO(timerReq); /* abort the timer request */
- WaitIO(timerReq); /* and wait for abort to complete */
- return (inbuf[0]); /* return the character */
- }
- SetupRead(); /* setup another read */
- }
- }
- }
-
- /* md_iflush - flush the input buffer */
- md_iflush(flg)
- int flg;
- {
- int cnt;
- incnt = 0; /* clear the input buffer */
- if (flg) { /* flush the line */
- log("flushing input buffer");
- for (cnt = 0; md_get(1) != DT_TIME; ++cnt)
- ;
- log("flushed %d bytes",cnt);
- }
- }
-
- /* md_put - output a character to the modem */
- md_put(ch)
- int ch;
- {
- char buf[1];
- buf[0] = ch;
- writeReq->IOSer.io_Command = CMD_WRITE;
- writeReq->IOSer.io_Data = (APTR)&buf[0];
- writeReq->IOSer.io_Length = (LONG)1;
- DoIO(writeReq);
- }
-
- /* md_write - write a packet to the modem */
- int md_write(buf,len)
- char *buf;
- int len;
- {
- writeReq->IOSer.io_Command = CMD_WRITE;
- writeReq->IOSer.io_Data = (APTR)&buf[0];
- writeReq->IOSer.io_Length = (LONG)len;
- DoIO(writeReq);
- }
-
- /* GetBufferedCharacters - get characters already buffered */
- static int GetBufferedCharacters()
- {
- /* do a status query */
- readReq->IOSer.io_Command = SDCMD_QUERY;
- DoIO(readReq);
-
- /* read the characters that are in the input buffer */
- if (readReq->IOSer.io_Actual > 0L) {
-
- /* compute the number of character to read */
- if ((incnt = (int)readReq->IOSer.io_Actual) > IBSIZE)
- incnt = IBSIZE;
- inptr = inbuf;
-
- /* get the buffered characters */
- readReq->IOSer.io_Command = CMD_READ;
- readReq->IOSer.io_Length = (LONG)incnt;
- readReq->IOSer.io_Data = (APTR)&inbuf[0];
- DoIO(readReq);
- }
-
- /* return the number of characters read */
- return (incnt = (int)readReq->IOSer.io_Actual);
- }
-
- /* SetupRead - setup to read a single character */
- static SetupRead()
- {
- readReq->IOSer.io_Command = CMD_READ;
- readReq->IOSer.io_Length = (LONG)1;
- readReq->IOSer.io_Data = (APTR)&inbuf[0];
- BeginIO(readReq);
- }
-
- /* log - log an error */
- log(fmt,a1,a2,a3,a4,a5,a6,a7,a8)
- char *fmt;
- {
- /*
- extern int blknum;
- fprintf(stderr,fmt,a1,a2,a3,a4,a5,a6,a7,a8);
- fprintf(stderr,", blknum=%d\n",blknum);
- */
- }
-