Tools for working with Cidco Mailstations
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}