home *** CD-ROM | disk | FTP | other *** search
- #include "prtrans.h"
-
- /*
- * Note that for the Amiga only the pramiga cable is supported. This is
- * because nobody would/could use the pc64 or 64net cables, because they
- * are for compatibility with pc software. To make up for this, we can use
- * the same prlink cable to its full potential by using all 8 data lines
- * bidirectionally.
- *
- * To enable this, define PRLINK88 (in the Makefile below), and don't forget
- * to set the cable type to prlink88 in the pet/vic/64 side programs as
- * well.
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
-
- #include <exec/exec.h>
- #include <resources/misc.h>
- #include <hardware/cia.h>
- #include <clib/exec_protos.h>
- #include <clib/misc_protos.h>
-
- /*
- * The CIAs are volatile, otherwise the while loop waiting for ACK to
- * change is "optimized".
- */
- extern volatile struct CIA ciaa;
- extern volatile struct CIA ciab;
-
- struct Library *MiscBase;
- static unsigned long MiscAllocated;
- static unsigned char ack;
- int bounce;
- char myname[] = "pramiga.c";
-
- #define BUSY (1 << CIAB_PRTRBUSY) /* == 0x01 */
- #define POUT (1 << CIAB_PRTRPOUT) /* == 0x02 */
- #define NO_ASM 1
-
- int
- prinit(void)
- {
- atexit(prclose);
-
- MiscBase = OpenResource("misc.resource");
- if (MiscBase == NULL) {
- printf("Can't open misc.resource\n");
- return -1;
- } {
- const char *user;
-
- user = AllocMiscResource(MR_PARALLELPORT, myname);
- if (user != NULL && user != myname) {
- printf("Printer data lines already in use by %s.\n", user);
- return -2;
- }
- MiscAllocated = 1 << MR_PARALLELPORT;
- #ifndef TRANSNIB
- user = AllocMiscResource(MR_PARALLELBITS, myname);
- if (user != NULL && user != myname) {
- printf("Printer control lines already in use by %s.\n", user);
- return -3;
- }
- MiscAllocated |= 1 << MR_PARALLELBITS;
- #endif
- }
-
- #ifndef TRANSNIB
- /* turn POUT into output (BUSY is input) */
- ciab.ciaddra = (ciab.ciaddra | POUT) & ~BUSY;
- ciab.ciapra |= POUT; /* and set it high */
- ack = ciab.ciapra & BUSY; /* get the current state of the BUSY line */
- #endif
- ciaa.ciaddrb = 0xFF; /* set all lines to output */
- ciaa.ciaprb = 0xFF; /* and high */
-
- return 0;
- }
-
- void
- prclose(void)
- {
- if (bounce != 0) {
- printf("*** bounce, bounce! (%d times)\n", bounce);
- bounce = 0;
- }
- #ifndef TRANSNIB
- if (MiscAllocated & (1 << MR_PARALLELBITS)) {
- ciab.ciaddra &= ~POUT; /* turn POUT back into input */
- FreeMiscResource(MR_PARALLELBITS);
- }
- #endif
- if (MiscAllocated & (1 << MR_PARALLELPORT)) {
- ciaa.ciaprb = 0xFF;
- ciaa.ciaddrb = 0xFF; /* set all data lines to output */
- FreeMiscResource(MR_PARALLELPORT);
- }
- MiscAllocated = 0;
- /* There is no CloseResource() function, really! */
- }
-
- void
- output(unsigned char byte)
- {
- send(&byte, 1);
- }
-
- unsigned
- input(void)
- {
- unsigned char byte;
-
- receive(&byte, 1);
- return byte;
- }
-
- unsigned
- wait_input(void)
- {
- #ifdef TRANSNIB
- while (ciaa.ciaprb & 0x40) /* wait for DRDY to go low */
- usleep (SLEEP_TIME);
- #else
- ciab.ciapra &= ~POUT; /* drop the -FLAG to low */
- while (ack == (BUSY & ciab.ciapra)) /* wait for BUSY to change */
- usleep (SLEEP_TIME);
- #endif
- return input();
- }
-
- #ifndef TRANSNIB
- void
- send(unsigned char *buffer, unsigned length)
- {
- ciaa.ciaddrb = 0xFF; /* set all lines to output */
-
- #if defined(__GNUC__) && !NO_ASM
- /* INDENT OFF */
- asm("
- subql #1,%1
- moveq #-1,d0
- cmpl %1,d0
- jeq .send
- .sbyteloop:
- moveb %2@+,%4@
- andb %6,%5@
- .sackloop:
- moveb %5@,d0
- andb %7,d0
- cmpb %3,d0
- jeq .sackloop
-
- orb %8,%5@
- eorb %7,%3
- dbra %1,.sbyteloop
- clrw %1
- subql #1,%1
- jcc .sbyteloop
- .send:
- " : "=d" (ack) /* 0 output */
- : "d" (length), /* 1 input */
- "a" (buffer), /* 2 */
- "0" (ack), /* 3 */
- "a" (&ciaa.ciaprb), /* 4 */
- "a" (&ciab.ciapra), /* 5 */
- "g" (~POUT), /* 6 */
- "g" (BUSY), /* 7 */
- "g" (POUT) /* 8 */
- : "d0" /* clobbered */
- );
- /* INDENT ON */
- #else
- while (length--) {
- ciaa.ciaprb = *buffer++;
- ciab.ciapra &= ~POUT; /* drop the -FLAG to low */
- while (ack == (BUSY & ciab.ciapra)); /* wait for BUSY to change */
- ciab.ciapra |= POUT; /* raise -FLAG again */
- ack ^= BUSY; /* store the new state of -BUSY */
- }
- #endif
- }
-
- #ifdef PRLINK88
- void
- receive(unsigned char *buffer, unsigned length)
- {
-
- ciaa.ciaddrb = 0x00; /* set the bidirectional signals to input */
-
- #if defined(__GNUC__) && !NO_ASM
- /* INDENT OFF */
- asm("
- subql #1,%1
- moveq #-1,d0
- cmpl %1,d0
- jeq .rend
-
- .rbyteloop:
- andb %6,%5@
- .rackloop:
- moveb %5@,d0
- andb %7,d0
- cmpb %3,d0
- jeq .rackloop
-
- orb %8,%5@
- moveb %4@,%2@+
-
- eorb %7,%3
- dbra %1,.rbyteloop
- clrw %1
- subql #1,%1
- jcc .rbyteloop
-
- .rend:
- " : "=d" (ack) /* 0 output */
- : "d" (length), /* 1 input */
- "a" (buffer), /* 2 */
- "0" (ack), /* 3 */
- "a" (&ciaa.ciaprb), /* 4 data */
- "a" (&ciab.ciapra), /* 5 ctl */
- "g" (~POUT), /* 6 */
- "g" (BUSY), /* 7 */
- "g" (POUT) /* 8 */
- : "d0" /* clobbered */
- );
- /* INDENT ON */
- #else
- while (length--) {
- ciab.ciapra &= ~POUT; /* drop the -FLAG to low */
- bounced:
- while (ack == (BUSY & ciab.ciapra)); /* wait for BUSY to change */
- *buffer++ = ciaa.ciaprb;/* read the byte */
- ciab.ciapra |= POUT; /* raise -FLAG again */
- /* debounce */
- {
- int bouncecount;
-
- for (bouncecount = 0; bouncecount < 2; bouncecount++) {
- if (ack == (BUSY & ciab.ciapra) || buffer[-1] != ciaa.ciaprb) {
- buffer--;
- bounce++;
- goto bounced;
- }
- }
- }
- ack ^= BUSY; /* store the new state of -BUSY */
- }
- #endif
- }
-
- #else /* not PRLINK88 */
-
- void
- receive(unsigned char *buffer, unsigned length)
- {
- register unsigned char data;
-
- ciaa.ciaddrb = 0x00; /* set all signals to input */
-
- while (length--) {
- ciab.ciapra &= ~POUT; /* drop the -FLAG to low */
- while (ack == (BUSY & ciab.ciapra)); /* wait for BUSY to change */
- ciab.ciapra |= POUT; /* raise -FLAG again */
- data = ciaa.ciaprb & 0x0f; /* read the low nybble */
-
- ciab.ciapra &= ~POUT; /* drop the -FLAG to low */
- while (ack != (BUSY & ciab.ciapra)); /* wait for BUSY to change */
-
- ciab.ciapra |= POUT; /* raise -FLAG again */
- data |= (ciaa.ciaprb & 0x0f) << 4; /* read the high nybble */
-
- *buffer++ = data;
- }
- }
-
- #endif /* PRLINK88 */
-
- #else /* TRANSNIB */
-
- /*-
- * TransNib is a cable that has only 6 bits connected:
- *
- * 0-3: data i/o
- * 6: handshake in
- * 7: handshake out
- *
- * Because the cable is straight-through, bits 6 and 7 are swapped
- * at the PET/C-64/VIC-20 side.
- *
- * The protocol is provided for people who made a cable for
- * TransNib V1.00 Devised by Matt Francis (m.p.francis@newcastle.ac.uk).
- * Because the cable is a subset of the prlink cable it will also work
- * with that.
- *
- * Note that this protocol is not compatible with the TransNib programs!
- -*/
-
- void
- send(unsigned char *buffer, unsigned length)
- {
- register unsigned char data;
-
- /*
- * $40 is DRCV (input), $80 is DRDY (output) Note that the names are
- * swapped from receiving but the data direction isn't!
- */
- ciaa.ciaddrb = 0x8f; /* set the bidirectional signals to output */
-
- while (length--) {
- register unsigned char nibble;
-
- data = *buffer++;
- nibble = data >> 4;
-
- ciaa.ciaprb = nibble; /* set DRDY low */
- while (ciaa.ciaprb & 0x40); /* wait for DRCV to go low */
- ciaa.ciaprb = nibble | 0x80; /* set DRDY high */
- while (!(ciaa.ciaprb & 0x40)); /* wait for DRCV to go high */
-
- nibble = data & 0x0F;
-
- ciaa.ciaprb = nibble; /* set DRDY low */
- while (ciaa.ciaprb & 0x40); /* wait for DRCV to go low */
- ciaa.ciaprb = nibble | 0x80; /* set DRDY high */
- while (!(ciaa.ciaprb & 0x40)); /* wait for DRCV to go high */
- }
- }
-
- void
- receive(unsigned char *buffer, unsigned length)
- {
- register unsigned char data;
-
- /*
- * $80 is DRCV (output), $40 is DRDY (input)
- */
- ciaa.ciaddrb = 0x80; /* set the bidirectional signals to input */
-
- while (length--) {
- while (ciaa.ciaprb & 0x40); /* wait for DRDY to go low */
- data = (ciaa.ciaprb & 0x0f) << 4; /* read the high nybble */
- ciaa.ciaprb = data & ~0x80; /* set DRCV low */
- while (!(ciaa.ciaprb & 0x40)); /* wait for DRDY to go high */
- ciaa.ciaprb = data | 0x80; /* set DRCV high */
-
- while (ciaa.ciaprb & 0x40); /* wait for DRDY to go low */
- data |= ciaa.ciaprb & 0x0f; /* read the low nybble */
- ciaa.ciaprb = data & ~0x80; /* set DRCV low */
- while (!(ciaa.ciaprb & 0x40)); /* wait for DRDY to go high */
- ciaa.ciaprb = data | 0x80; /* set DRCV high */
-
- *buffer++ = data;
- }
- }
-
- #endif /* TRANSNIB */
-