home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 112.lha / BModem / mdio.c < prev   
Encoding:
C/C++ Source or Header  |  1986-11-20  |  7.9 KB  |  296 lines

  1. /* mdio.c - bmodem i/o routines for the Amiga/Aztec C */
  2. /*
  3.     by David Betz, BYTE Magazine/BIX
  4. */
  5.  
  6. #include <stdio.h>
  7. #include <setjmp.h>
  8. #include <exec/exec.h>
  9. #include <libraries/dos.h>
  10. #include <devices/serial.h>
  11. #include <devices/timer.h>
  12. #include <functions.h>
  13.  
  14. /* definitions */
  15. #define IBSIZE        512        /* input buffer size */
  16.  
  17. /* return status codes */
  18. #define DT_TIME    -1
  19.  
  20. /* local variables */
  21. static int readOpen = FALSE;
  22. static struct IOExtSer *readReq = NULL;
  23. static int timerOpen = FALSE;
  24. static struct timerequest *timerReq = NULL;
  25. static int writeOpen = FALSE;
  26. static struct IOExtSer *writeReq = NULL;
  27. static int inputOpen = FALSE;
  28. static unsigned char inbuf[IBSIZE],*inptr;
  29. static int incnt;
  30.  
  31. /* external variables */
  32. extern jmp_buf xfr_error;
  33.  
  34. /* md_init - common initialization routine */
  35. md_init(baud)
  36.   long baud;
  37. {
  38.     /* create a read request block */
  39.     readReq = (struct IOExtSer *)
  40.         AllocMem((long)sizeof(struct IOExtSer),MEMF_PUBLIC|MEMF_CLEAR);
  41.     if (readReq == NULL)
  42.     cleanup("can't create read request block");
  43.     readReq->io_SerFlags = SERF_SHARED;
  44.  
  45.     /* create a reply port for the read request block */
  46.     readReq->IOSer.io_Message.mn_ReplyPort = CreatePort("ReadReply",0L);
  47.     if (readReq->IOSer.io_Message.mn_ReplyPort == NULL)
  48.     cleanup("can't create read reply port");
  49.  
  50.     /* open the serial device - input */
  51.     if (OpenDevice("serial.device",0L,readReq,0L))
  52.     cleanup("can't open serial device for input");
  53.     readOpen = TRUE;
  54.  
  55.     /* set the baud rate and character size */
  56.     readReq->IOSer.io_Command = SDCMD_SETPARAMS;
  57.     readReq->io_CtlChar = 0x13150506L;
  58.     readReq->io_SerFlags = SERF_XDISABLED;
  59.     readReq->io_ExtFlags = 0;
  60.     readReq->io_Baud = baud;
  61.     readReq->io_ReadLen = 8;
  62.     readReq->io_WriteLen = 8;
  63.     readReq->io_StopBits = 1;
  64.     DoIO(readReq);
  65.  
  66.     /* create a timer request block */
  67.     timerReq = (struct timerequest *)
  68.         AllocMem((long)sizeof(struct timerequest),MEMF_PUBLIC|MEMF_CLEAR);
  69.     if (timerReq == NULL)
  70.     cleanup("can't create timer request block");
  71.  
  72.     /* create a reply port for the timer request block */
  73.     timerReq->tr_node.io_Message.mn_ReplyPort = CreatePort("TimerReply",0L);
  74.     if (timerReq->tr_node.io_Message.mn_ReplyPort == NULL)
  75.     cleanup("can't create timer reply port");
  76.  
  77.     /* open the timer device */
  78.     if (OpenDevice("timer.device",UNIT_VBLANK,timerReq,0L))
  79.     cleanup("can't open timer device");
  80.     timerOpen = TRUE;
  81.  
  82.     /* setup for a timer request */
  83.     timerReq->tr_node.io_Command = TR_ADDREQUEST;
  84.  
  85.     /* create a write request block */
  86.     writeReq = (struct IOExtSer *)
  87.         AllocMem((long)sizeof(struct IOExtSer),MEMF_PUBLIC|MEMF_CLEAR);
  88.     if (writeReq == NULL)
  89.     cleanup("can't create write request block");
  90.     writeReq->io_SerFlags = SERF_SHARED;
  91.  
  92.     /* create a reply port for the write request block */
  93.     writeReq->IOSer.io_Message.mn_ReplyPort = CreatePort("WriteReply",0L);
  94.     if (writeReq->IOSer.io_Message.mn_ReplyPort == NULL)
  95.     cleanup("can't create write reply port");
  96.  
  97.     /* open the serial device - output */
  98.     if (OpenDevice("serial.device",0L,writeReq,0L))
  99.     cleanup("can't open serial device for output");
  100.     writeOpen = TRUE;
  101.  
  102.     /* input buffer starts out empty */
  103.     incnt = 0;
  104. }
  105.  
  106. /* cleanup - cleanup and exit after an error */
  107. cleanup(msg)
  108.   char *msg;
  109. {
  110.     fprintf(stderr,"error: %s\n",msg);
  111.     md_done();
  112.     exit(1);
  113. }
  114.  
  115. /* md_done - terminate modem communications */
  116. md_done()
  117. {
  118.     /* delete the read reply port */
  119.     if (readReq != NULL && readReq->IOSer.io_Message.mn_ReplyPort)
  120.     DeletePort(readReq->IOSer.io_Message.mn_ReplyPort);
  121.  
  122.     /* close the read request and free the memory */
  123.     if (readOpen)
  124.     CloseDevice(readReq);
  125.     if (readReq)
  126.     FreeMem(readReq,(long)sizeof(struct IOExtSer));
  127.  
  128.     /* delete the timer reply port */
  129.     if (timerReq != NULL && timerReq->tr_node.io_Message.mn_ReplyPort)
  130.     DeletePort(timerReq->tr_node.io_Message.mn_ReplyPort);
  131.  
  132.     /* close the timer request and free the memory */
  133.     if (timerOpen)
  134.     CloseDevice(timerReq);
  135.     if (timerReq)
  136.     FreeMem(timerReq,(long)sizeof(struct timerequest));
  137.  
  138.     /* delete the write reply port */
  139.     if (writeReq != NULL && writeReq->IOSer.io_Message.mn_ReplyPort)
  140.     DeletePort(writeReq->IOSer.io_Message.mn_ReplyPort);
  141.  
  142.     /* close the write request and free the memory */
  143.     if (writeOpen)
  144.     CloseDevice(writeReq);
  145.     if (writeReq)
  146.     FreeMem(writeReq,(long)sizeof(struct IOExtSer));
  147. }
  148.  
  149. /* md_get - get a character with timeout */
  150. int md_get(tmo)
  151.   int tmo;
  152. {
  153.     long mask,rmask;
  154.  
  155.     /* check for a buffered character */
  156.     if (--incnt >= 0)
  157.     return (*inptr++);
  158.  
  159.     /* check for buffered characters */
  160.     if (GetBufferedCharacters() > 0) {
  161.     --incnt;
  162.     return (*inptr++);
  163.     }
  164.  
  165.     /* set the timeout timer */
  166.     timerReq->tr_time.tv_secs = tmo;
  167.     timerReq->tr_time.tv_micro = 0;
  168.     SendIO(timerReq);
  169.  
  170.     /* setup to read a single character */
  171.     SetupRead();
  172.  
  173.     /* compute the signal mask */
  174.     mask = (1L << readReq->IOSer.io_Message.mn_ReplyPort->mp_SigBit)
  175.          | (1L << timerReq->tr_node.io_Message.mn_ReplyPort->mp_SigBit)
  176.          | SIGBREAKF_CTRL_C;
  177.  
  178.     /* wait for a character or a timeout */
  179.     for (;;) {
  180.  
  181.     /* wait for the read request to complete or timeout */
  182.     rmask = Wait(mask);
  183.  
  184.     /* check for the abort signal */
  185.     if (rmask & SIGBREAKF_CTRL_C) {
  186.         AbortIO(timerReq);    /* abort the timer request */
  187.         WaitIO(timerReq);
  188.         AbortIO(readReq);    /* abort the read request */
  189.         WaitIO(readReq);
  190.         longjmp(xfr_error,1);
  191.     }
  192.  
  193.     /* check for timer completion */
  194.     if (CheckIO(timerReq)) {
  195.         WaitIO(timerReq);    /* dequeue the request */
  196.         AbortIO(readReq);    /* abort the read request */
  197.         WaitIO(readReq);    /* and wait for abort to complete */
  198.         return (DT_TIME);    /* return a timeout indication */
  199.     }
  200.  
  201.     /* check for read completion */
  202.     if (CheckIO(readReq)) {
  203.         WaitIO(readReq);    /* dequeue the request */
  204.         if (readReq->IOSer.io_Actual == 1L) {
  205.         AbortIO(timerReq);    /* abort the timer request */
  206.         WaitIO(timerReq);    /* and wait for abort to complete */
  207.         return (inbuf[0]);    /* return the character */
  208.         }
  209.         SetupRead();    /* setup another read */
  210.     }
  211.     }
  212. }
  213.  
  214. /* md_iflush - flush the input buffer */
  215. md_iflush(flg)
  216.   int flg;
  217. {
  218.     int cnt;
  219.     incnt = 0;    /* clear the input buffer */
  220.     if (flg) {    /* flush the line */
  221.     log("flushing input buffer");
  222.     for (cnt = 0; md_get(1) != DT_TIME; ++cnt)
  223.         ;
  224.     log("flushed %d bytes",cnt);
  225.     }
  226. }
  227.  
  228. /* md_put - output a character to the modem */
  229. md_put(ch)
  230.   int ch;
  231. {
  232.     char buf[1];
  233.     buf[0] = ch;
  234.     writeReq->IOSer.io_Command = CMD_WRITE;
  235.     writeReq->IOSer.io_Data = (APTR)&buf[0];
  236.     writeReq->IOSer.io_Length = (LONG)1;
  237.     DoIO(writeReq);
  238. }
  239.  
  240. /* md_write - write a packet to the modem */
  241. int md_write(buf,len)
  242.   char *buf;
  243.   int len;
  244. {
  245.     writeReq->IOSer.io_Command = CMD_WRITE;
  246.     writeReq->IOSer.io_Data = (APTR)&buf[0];
  247.     writeReq->IOSer.io_Length = (LONG)len;
  248.     DoIO(writeReq);
  249. }
  250.  
  251. /* GetBufferedCharacters - get characters already buffered */
  252. static int GetBufferedCharacters()
  253. {
  254.     /* do a status query */
  255.     readReq->IOSer.io_Command = SDCMD_QUERY;
  256.     DoIO(readReq);
  257.  
  258.     /* read the characters that are in the input buffer */
  259.     if (readReq->IOSer.io_Actual > 0L) {
  260.  
  261.     /* compute the number of character to read */
  262.     if ((incnt = (int)readReq->IOSer.io_Actual) > IBSIZE)
  263.         incnt = IBSIZE;
  264.     inptr = inbuf;
  265.  
  266.     /* get the buffered characters */
  267.     readReq->IOSer.io_Command = CMD_READ;
  268.     readReq->IOSer.io_Length = (LONG)incnt;
  269.     readReq->IOSer.io_Data = (APTR)&inbuf[0];
  270.     DoIO(readReq);
  271.     }
  272.  
  273.     /* return the number of characters read */
  274.     return (incnt = (int)readReq->IOSer.io_Actual);
  275. }
  276.  
  277. /* SetupRead - setup to read a single character */
  278. static SetupRead()
  279. {
  280.     readReq->IOSer.io_Command = CMD_READ;
  281.     readReq->IOSer.io_Length = (LONG)1;
  282.     readReq->IOSer.io_Data = (APTR)&inbuf[0];
  283.     BeginIO(readReq);
  284. }
  285.  
  286. /* log - log an error */
  287. log(fmt,a1,a2,a3,a4,a5,a6,a7,a8)
  288.   char *fmt;
  289. {
  290. /*
  291.     extern int blknum;
  292.     fprintf(stderr,fmt,a1,a2,a3,a4,a5,a6,a7,a8);
  293.     fprintf(stderr,", blknum=%d\n",blknum);
  294. */
  295. }
  296.