Tools for working with Cidco Mailstations
at master 187 lines 3.0 kB view raw
1#include <stdio.h> 2#include <err.h> 3#include <unistd.h> 4#include <sys/types.h> 5 6#define INB inb 7 8#ifdef __OpenBSD__ 9#include <machine/sysarch.h> 10#include <machine/pio.h> 11#define OUTB outb 12 13#elif defined(__linux__) 14#include <sys/io.h> 15#define OUTB(port, byte) outb(byte, port) 16 17#else 18void 19OUTB(int port, int byte) 20{ 21 errx(1, "cannot write to parallel port"); 22} 23int 24inb(int port) 25{ 26 errx(1, "cannot read from parallel port"); 27} 28#endif 29 30#include "tribble.h" 31 32unsigned int tribble_port = PORTADDRESS; 33 34int tribble_debug = 0; 35 36void 37checkio(void) 38{ 39 if (geteuid() != 0) 40 errx(1, "must be run as root"); 41 42#ifdef __OpenBSD__ 43#ifdef __amd64__ 44 if (amd64_iopl(1) != 0) 45 errx(1, "amd64_iopl failed (is machdep.allowaperture=1?)"); 46#elif defined(__i386__) 47 if (i386_iopl(1) != 0) 48 errx(1, "i386_iopl failed (is machdep.allowaperture=1?)"); 49#endif 50#elif defined(__linux__) 51 iopl(3); 52#endif 53} 54 55unsigned int 56havetribble(void) 57{ 58 int tries; 59 60 /* drop busy */ 61 OUTB(tribble_port + DATA, 0); 62 63 /* wait for (inverted) strobe */ 64 for (tries = 0; tries < 1024; tries++) 65 if ((INB(tribble_port + STATUS) & stbin) == 0) 66 /* 67 * leave busy dropped, assume recvtribble() will deal 68 * with it 69 */ 70 return 1; 71 72 /* re-raise busy */ 73 OUTB(tribble_port + DATA, bsyout); 74 75 return 0; 76} 77 78int 79recvtribble(void) 80{ 81 unsigned char b; 82 unsigned int tries; 83 84 /* drop busy */ 85 OUTB(tribble_port + DATA, 0); 86 87 /* wait for (inverted) strobe */ 88 tries = 0; 89 while ((INB(tribble_port + STATUS) & stbin) != 0) { 90 if (++tries >= 500000) { 91 /* raise busy/ack */ 92 OUTB(tribble_port + DATA, bsyout); 93 return -1; 94 } 95 } 96 97 /* grab tribble */ 98 b = (INB(tribble_port + STATUS) >> 3) & tribmask; 99 100 /* raise busy/ack */ 101 OUTB(tribble_port + DATA, bsyout); 102 103 /* wait for (inverted) UNstrobe */ 104 tries = 0; 105 while ((INB(tribble_port + STATUS) & stbin) == 0) { 106 if (++tries >= 500000) 107 return -1; 108 } 109 110 return b; 111} 112 113int 114recvbyte(void) 115{ 116 char c, t; 117 118 if ((t = recvtribble()) == -1) 119 return -1; 120 c = t; 121 122 if ((t = recvtribble()) == -1) 123 return -1; 124 c += (t << 3); 125 126 if ((t = recvtribble()) == -1) 127 return -1; 128 c += ((t & dibmask) << 6); 129 130 return c; 131} 132 133int 134sendtribble(unsigned char b) 135{ 136 unsigned int tries; 137 int ret = 0; 138 139 /* raise busy */ 140 OUTB(tribble_port + DATA, bsyout); 141 142 /* wait for mailstation to drop busy */ 143 tries = 0; 144 while ((INB(tribble_port + STATUS) & bsyin) != 0) { 145 if (++tries >= 500000) { 146 ret = 1; 147 goto sendtribble_out; 148 } 149 } 150 151 /* send tribble */ 152 OUTB(tribble_port + DATA, b & tribmask); 153 154 /* strobe */ 155 OUTB(tribble_port + DATA, (b & tribmask) | stbout); 156 157 /* wait for ack */ 158 tries = 0; 159 while ((INB(tribble_port + STATUS) & bsyin) == 0) { 160 if (++tries >= 500000) { 161 ret = 1; 162 goto sendtribble_out; 163 } 164 } 165 166 /* unstrobe */ 167 OUTB(tribble_port + DATA, 0); 168 169sendtribble_out: 170 /* raise busy/ack */ 171 OUTB(tribble_port + DATA, bsyout); 172 173 return ret; 174} 175 176int 177sendbyte(unsigned char b) 178{ 179 if (sendtribble(b) != 0) 180 return 1; 181 if (sendtribble(b >> 3) != 0) 182 return 2; 183 if (sendtribble(b >> 6) != 0) 184 return 3; 185 186 return 0; 187}