home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Netzwerk / prlink-080b.lha / prlink-0.8.0b / src / pramiga.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-07  |  8.5 KB  |  359 lines

  1. #include "prtrans.h"
  2.  
  3. /*
  4.  * Note that for the Amiga only the pramiga cable is supported. This is
  5.  * because nobody would/could use the pc64 or 64net cables, because they
  6.  * are for compatibility with pc software. To make up for this, we can use
  7.  * the same prlink cable to its full potential by using all 8 data lines
  8.  * bidirectionally.
  9.  *
  10.  * To enable this, define PRLINK88 (in the Makefile below), and don't forget
  11.  * to set the cable type to prlink88 in the pet/vic/64 side programs as
  12.  * well.
  13.  */
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <unistd.h>
  17.  
  18. #include <exec/exec.h>
  19. #include <resources/misc.h>
  20. #include <hardware/cia.h>
  21. #include <clib/exec_protos.h>
  22. #include <clib/misc_protos.h>
  23.  
  24. /*
  25.  * The CIAs are volatile, otherwise the while loop waiting for ACK to
  26.  * change is "optimized".
  27.  */
  28. extern volatile struct CIA ciaa;
  29. extern volatile struct CIA ciab;
  30.  
  31. struct Library *MiscBase;
  32. static unsigned long MiscAllocated;
  33. static unsigned char ack;
  34. int        bounce;
  35. char        myname[] = "pramiga.c";
  36.  
  37. #define BUSY    (1 << CIAB_PRTRBUSY)    /* == 0x01 */
  38. #define POUT    (1 << CIAB_PRTRPOUT)    /* == 0x02 */
  39. #define NO_ASM    1
  40.  
  41. int
  42. prinit(void)
  43. {
  44.     atexit(prclose);
  45.  
  46.     MiscBase = OpenResource("misc.resource");
  47.     if (MiscBase == NULL) {
  48.     printf("Can't open misc.resource\n");
  49.     return -1;
  50.     } {
  51.     const char     *user;
  52.  
  53.     user = AllocMiscResource(MR_PARALLELPORT, myname);
  54.     if (user != NULL && user != myname) {
  55.         printf("Printer data lines already in use by %s.\n", user);
  56.         return -2;
  57.     }
  58.     MiscAllocated = 1 << MR_PARALLELPORT;
  59. #ifndef TRANSNIB
  60.     user = AllocMiscResource(MR_PARALLELBITS, myname);
  61.     if (user != NULL && user != myname) {
  62.         printf("Printer control lines already in use by %s.\n", user);
  63.         return -3;
  64.     }
  65.     MiscAllocated |= 1 << MR_PARALLELBITS;
  66. #endif
  67.     }
  68.  
  69. #ifndef TRANSNIB
  70.     /* turn POUT into output (BUSY is input) */
  71.     ciab.ciaddra = (ciab.ciaddra | POUT) & ~BUSY;
  72.     ciab.ciapra |= POUT;    /* and set it high */
  73.     ack = ciab.ciapra & BUSY;    /* get the current state of the BUSY line */
  74. #endif
  75.     ciaa.ciaddrb = 0xFF;    /* set all lines to output */
  76.     ciaa.ciaprb = 0xFF;     /* and high */
  77.  
  78.     return 0;
  79. }
  80.  
  81. void
  82. prclose(void)
  83. {
  84.     if (bounce != 0) {
  85.     printf("*** bounce, bounce! (%d times)\n", bounce);
  86.     bounce = 0;
  87.     }
  88. #ifndef TRANSNIB
  89.     if (MiscAllocated & (1 << MR_PARALLELBITS)) {
  90.     ciab.ciaddra &= ~POUT;    /* turn POUT back into input */
  91.     FreeMiscResource(MR_PARALLELBITS);
  92.     }
  93. #endif
  94.     if (MiscAllocated & (1 << MR_PARALLELPORT)) {
  95.     ciaa.ciaprb = 0xFF;
  96.     ciaa.ciaddrb = 0xFF;    /* set all data lines to output */
  97.     FreeMiscResource(MR_PARALLELPORT);
  98.     }
  99.     MiscAllocated = 0;
  100.     /* There is no CloseResource() function, really! */
  101. }
  102.  
  103. void
  104. output(unsigned char byte)
  105. {
  106.     send(&byte, 1);
  107. }
  108.  
  109. unsigned
  110. input(void)
  111. {
  112.     unsigned char   byte;
  113.  
  114.     receive(&byte, 1);
  115.     return byte;
  116. }
  117.  
  118. unsigned
  119. wait_input(void)
  120. {
  121. #ifdef TRANSNIB
  122.     while (ciaa.ciaprb & 0x40)    /* wait for DRDY to go low */
  123.     usleep (SLEEP_TIME);
  124. #else
  125.     ciab.ciapra &= ~POUT;        /* drop the -FLAG to low */
  126.     while (ack == (BUSY & ciab.ciapra)) /* wait for BUSY to change */
  127.     usleep (SLEEP_TIME);
  128. #endif
  129.     return input();
  130. }
  131.  
  132. #ifndef TRANSNIB
  133. void
  134. send(unsigned char *buffer, unsigned length)
  135. {
  136.     ciaa.ciaddrb = 0xFF;    /* set all lines to output */
  137.  
  138. #if defined(__GNUC__) && !NO_ASM
  139. /* INDENT OFF */
  140.     asm("
  141.     subql #1,%1
  142.     moveq #-1,d0
  143.     cmpl %1,d0
  144.     jeq .send
  145. .sbyteloop:
  146.     moveb %2@+,%4@
  147.     andb %6,%5@
  148. .sackloop:
  149.     moveb %5@,d0
  150.     andb %7,d0
  151.     cmpb %3,d0
  152.     jeq .sackloop
  153.  
  154.     orb %8,%5@
  155.     eorb %7,%3
  156.     dbra %1,.sbyteloop
  157.     clrw %1
  158.     subql #1,%1
  159.     jcc .sbyteloop
  160. .send:
  161.     " : "=d" (ack)              /* 0 output */
  162.       : "d" (length),           /* 1 input */
  163.     "a" (buffer),           /* 2 */
  164.     "0" (ack),              /* 3 */
  165.     "a" (&ciaa.ciaprb),     /* 4 */
  166.     "a" (&ciab.ciapra),     /* 5 */
  167.     "g" (~POUT),            /* 6 */
  168.     "g" (BUSY),             /* 7 */
  169.     "g" (POUT)              /* 8 */
  170.       : "d0"                    /* clobbered */
  171.     );
  172.     /* INDENT ON */
  173. #else
  174.     while (length--) {
  175.     ciaa.ciaprb = *buffer++;
  176.     ciab.ciapra &= ~POUT;    /* drop the -FLAG to low */
  177.     while (ack == (BUSY & ciab.ciapra));    /* wait for BUSY to change */
  178.     ciab.ciapra |= POUT;    /* raise -FLAG again */
  179.     ack ^= BUSY;        /* store the new state of -BUSY */
  180.     }
  181. #endif
  182. }
  183.  
  184. #ifdef PRLINK88
  185. void
  186. receive(unsigned char *buffer, unsigned length)
  187. {
  188.  
  189.     ciaa.ciaddrb = 0x00;    /* set the bidirectional signals to input */
  190.  
  191. #if defined(__GNUC__) && !NO_ASM
  192. /* INDENT OFF */
  193.     asm("
  194.     subql #1,%1
  195.     moveq #-1,d0
  196.     cmpl %1,d0
  197.     jeq .rend
  198.  
  199. .rbyteloop:
  200.     andb %6,%5@
  201. .rackloop:
  202.     moveb %5@,d0
  203.     andb %7,d0
  204.     cmpb %3,d0
  205.     jeq .rackloop
  206.  
  207.     orb %8,%5@
  208.     moveb %4@,%2@+
  209.  
  210.     eorb %7,%3
  211.     dbra %1,.rbyteloop
  212.     clrw %1
  213.     subql #1,%1
  214.     jcc .rbyteloop
  215.  
  216. .rend:
  217.     " : "=d" (ack)              /* 0 output */
  218.       : "d" (length),           /* 1 input */
  219.     "a" (buffer),           /* 2 */
  220.     "0" (ack),              /* 3 */
  221.     "a" (&ciaa.ciaprb),     /* 4 data */
  222.     "a" (&ciab.ciapra),     /* 5 ctl */
  223.     "g" (~POUT),            /* 6 */
  224.     "g" (BUSY),             /* 7 */
  225.     "g" (POUT)              /* 8 */
  226.       : "d0"                    /* clobbered */
  227.     );
  228.     /* INDENT ON */
  229. #else
  230.     while (length--) {
  231.     ciab.ciapra &= ~POUT;    /* drop the -FLAG to low */
  232. bounced:
  233.     while (ack == (BUSY & ciab.ciapra));    /* wait for BUSY to change */
  234.     *buffer++ = ciaa.ciaprb;/* read the byte */
  235.     ciab.ciapra |= POUT;    /* raise -FLAG again */
  236.     /* debounce */
  237.     {
  238.         int         bouncecount;
  239.  
  240.         for (bouncecount = 0; bouncecount < 2; bouncecount++) {
  241.         if (ack == (BUSY & ciab.ciapra) || buffer[-1] != ciaa.ciaprb) {
  242.             buffer--;
  243.             bounce++;
  244.             goto bounced;
  245.         }
  246.         }
  247.     }
  248.     ack ^= BUSY;        /* store the new state of -BUSY */
  249.     }
  250. #endif
  251. }
  252.  
  253. #else                /* not PRLINK88 */
  254.  
  255. void
  256. receive(unsigned char *buffer, unsigned length)
  257. {
  258.     register unsigned char data;
  259.  
  260.     ciaa.ciaddrb = 0x00;    /* set all signals to input */
  261.  
  262.     while (length--) {
  263.     ciab.ciapra &= ~POUT;    /* drop the -FLAG to low */
  264.     while (ack == (BUSY & ciab.ciapra));    /* wait for BUSY to change */
  265.     ciab.ciapra |= POUT;    /* raise -FLAG again */
  266.     data = ciaa.ciaprb & 0x0f;    /* read the low nybble */
  267.  
  268.     ciab.ciapra &= ~POUT;    /* drop the -FLAG to low */
  269.     while (ack != (BUSY & ciab.ciapra));    /* wait for BUSY to change */
  270.  
  271.     ciab.ciapra |= POUT;    /* raise -FLAG again */
  272.     data |= (ciaa.ciaprb & 0x0f) << 4;    /* read the high nybble */
  273.  
  274.     *buffer++ = data;
  275.     }
  276. }
  277.  
  278. #endif                /* PRLINK88 */
  279.  
  280. #else                /* TRANSNIB */
  281.  
  282. /*-
  283.  *  TransNib is a cable that has only 6 bits connected:
  284.  *
  285.  *  0-3:    data i/o
  286.  *  6:        handshake in
  287.  *  7:        handshake out
  288.  *
  289.  *  Because the cable is straight-through, bits 6 and 7 are swapped
  290.  *  at the PET/C-64/VIC-20 side.
  291.  *
  292.  *  The protocol is provided for people who made a cable for
  293.  *  TransNib V1.00 Devised by Matt Francis (m.p.francis@newcastle.ac.uk).
  294.  *  Because the cable is a subset of the prlink cable it will also work
  295.  *  with that.
  296.  *
  297.  *  Note that this protocol is not compatible with the TransNib programs!
  298. -*/
  299.  
  300. void
  301. send(unsigned char *buffer, unsigned length)
  302. {
  303.     register unsigned char data;
  304.  
  305.     /*
  306.      * $40 is DRCV (input), $80 is DRDY (output) Note that the names are
  307.      * swapped from receiving but the data direction isn't!
  308.      */
  309.     ciaa.ciaddrb = 0x8f;    /* set the bidirectional signals to output */
  310.  
  311.     while (length--) {
  312.     register unsigned char nibble;
  313.  
  314.     data = *buffer++;
  315.     nibble = data >> 4;
  316.  
  317.     ciaa.ciaprb = nibble;    /* set DRDY low */
  318.     while (ciaa.ciaprb & 0x40);    /* wait for DRCV to go low */
  319.     ciaa.ciaprb = nibble | 0x80;    /* set DRDY high */
  320.     while (!(ciaa.ciaprb & 0x40));    /* wait for DRCV to go high */
  321.  
  322.     nibble = data & 0x0F;
  323.  
  324.     ciaa.ciaprb = nibble;    /* set DRDY low */
  325.     while (ciaa.ciaprb & 0x40);    /* wait for DRCV to go low */
  326.     ciaa.ciaprb = nibble | 0x80;    /* set DRDY high */
  327.     while (!(ciaa.ciaprb & 0x40));    /* wait for DRCV to go high */
  328.     }
  329. }
  330.  
  331. void
  332. receive(unsigned char *buffer, unsigned length)
  333. {
  334.     register unsigned char data;
  335.  
  336.     /*
  337.      * $80 is DRCV (output), $40 is DRDY (input)
  338.      */
  339.     ciaa.ciaddrb = 0x80;    /* set the bidirectional signals to input */
  340.  
  341.     while (length--) {
  342.     while (ciaa.ciaprb & 0x40);    /* wait for DRDY to go low */
  343.     data = (ciaa.ciaprb & 0x0f) << 4;    /* read the high nybble */
  344.     ciaa.ciaprb = data & ~0x80;    /* set DRCV low */
  345.     while (!(ciaa.ciaprb & 0x40));    /* wait for DRDY to go high */
  346.     ciaa.ciaprb = data | 0x80;    /* set DRCV high */
  347.  
  348.     while (ciaa.ciaprb & 0x40);    /* wait for DRDY to go low */
  349.     data |= ciaa.ciaprb & 0x0f;    /* read the low nybble */
  350.     ciaa.ciaprb = data & ~0x80;    /* set DRCV low */
  351.     while (!(ciaa.ciaprb & 0x40));    /* wait for DRDY to go high */
  352.     ciaa.ciaprb = data | 0x80;    /* set DRCV high */
  353.  
  354.     *buffer++ = data;
  355.     }
  356. }
  357.  
  358. #endif                /* TRANSNIB */
  359.