14 * BASE+1 ~ status: BAOSEI??
15 * /BUSY, ACK, PE, SLCT, ERROR, IRQ
16 * BASE+2 ~ control: ??MISIAS
17 * bidirrectMODE, IRQ_EN, /SLCT_IN, INIT, /AUTO_FD_XT, /STROBE
21 * TH, TR, TL, D3, D2, D1, D0
29 * 6 TL <-- 14 /AUTO_FD_XT
32 * 9 TR <-- 17 /SLCT_IN
34 * start: TH low/high, TL high
36 * TH low - lower nibble: MD ready to recv | MD sent to PC
37 * TL low - lower niblle: sent to MD | ready to recv from MD
38 * TH high - upper nibble: MD ready to recv | MD sent to PC
39 * TL high - upper nibble: sent | ready to recv from MD
42 #define ACK_TIMEOUT 2000000
45 #define PORT_STATUS 889
46 #define PORT_CONTROL 890
48 #define timediff(now, start) \
49 ((now.tv_sec - start.tv_sec) * 1000000 + now.tv_usec - start.tv_usec)
51 static void do_exit(const char *msg)
53 /* switch TL back to high */
54 outb(0xe0, PORT_CONTROL);
61 static void inthandler(int u)
66 static void wait_th_low(void)
68 struct timeval start, now;
70 gettimeofday(&start, NULL);
72 while (inb(PORT_STATUS) & 0x40) {
73 gettimeofday(&now, NULL);
74 if (timediff(now, start) > ACK_TIMEOUT)
75 do_exit("timeout waiting TH low\n");
79 static void wait_th_high(void)
81 struct timeval start, now;
83 gettimeofday(&start, NULL);
85 while (!(inb(PORT_STATUS) & 0x40)) {
86 gettimeofday(&now, NULL);
87 if (timediff(now, start) > ACK_TIMEOUT)
88 do_exit("timeout waiting TH high\n");
92 static unsigned int recv_byte(void)
96 outb(0xe2, PORT_CONTROL); /* TL low */
100 byte = inb(PORT_DATA) & 0x0f;
102 outb(0xe0, PORT_CONTROL); /* TL high */
106 byte |= inb(PORT_DATA) << 4;
111 static void send_byte(unsigned int byte)
115 outb(byte & 0x0f, PORT_DATA);
116 outb(0xc2, PORT_CONTROL); /* TL low */
120 outb((byte >> 4) & 0x0f, PORT_DATA);
121 outb(0xc0, PORT_CONTROL); /* TL high */
124 static void send_cmd(unsigned int cmd)
126 send_byte(CMD_PREFIX);
130 static void usage(const char *argv0)
132 fprintf(stderr, "usage:\n%s <cmd> [args]\n"
133 "\tsend <file> <addr> [size]\n"
134 "\trecv <file> <addr> <size>\n", argv0);
138 static unsigned int atoi_or_die(const char *a)
143 i = strtoul(a, &p, 0);
144 if (p == NULL || *p != 0) {
145 fprintf(stderr, "atoi: can't convert: %s\n", a);
152 int main(int argc, char *argv[])
154 unsigned int addr = 0, size = 0, i = 0;
162 data = malloc(0x1000000);
164 fprintf(stderr, "can't alloc %d bytes\n", 0x1000000);
168 /* parse args, read files.. */
169 if (strcmp(argv[1], "send") == 0)
171 if (argc != 4 && argc != 5)
174 file = fopen(argv[2], "rb");
176 fprintf(stderr, "can't open file: %s\n", argv[2]);
180 addr = atoi_or_die(argv[3]);
181 if (argv[4] == NULL) {
182 fseek(file, 0, SEEK_END);
184 fseek(file, 0, SEEK_SET);
187 size = atoi_or_die(argv[4]);
189 ret = fread(data, 1, size, file);
191 fprintf(stderr, "fread returned %d/%d\n", ret, size);
196 else if (strcmp(argv[1], "recv") == 0)
201 file = fopen(argv[2], "wb");
203 fprintf(stderr, "can't open file: %s\n", argv[2]);
207 addr = atoi_or_die(argv[3]);
208 size = atoi_or_die(argv[4]);
210 memset(data, 0, size);
215 ret = ioperm(PORT_DATA, 3, 1);
221 signal(SIGINT, inthandler);
223 printf("regs: %02x %02x %02x\n",
224 inb(PORT_DATA), inb(PORT_STATUS), inb(PORT_CONTROL));
225 outb(0xe8, PORT_CONTROL); /* TR low - request for transfer */
227 if (inb(PORT_STATUS) & 0x40)
228 printf("waiting for TH low..\n");
229 while (inb(PORT_STATUS) & 0x40)
232 outb(0xe0, PORT_CONTROL);
234 if (strcmp(argv[1], "send") == 0)
236 printf("send %06x %06x\n", addr, size);
237 send_cmd(CMD_MD_SEND);
238 send_byte((addr >> 16) & 0xff);
239 send_byte((addr >> 8) & 0xff);
240 send_byte((addr >> 0) & 0xff);
241 send_byte((size >> 16) & 0xff);
242 send_byte((size >> 8) & 0xff);
243 send_byte((size >> 0) & 0xff);
245 for (i = 0; i < size; i++)
247 if ((i & 0xff) == 0) {
248 printf("\b\b\b\b\b\b\b\b\b\b\b\b\b");
249 printf("%06x/%06x", i, size);
256 else if (strcmp(argv[1], "recv") == 0)
258 send_cmd(CMD_MD_RECV);
259 send_byte((addr >> 16) & 0xff);
260 send_byte((addr >> 8) & 0xff);
261 send_byte((addr >> 0) & 0xff);
262 send_byte((size >> 16) & 0xff);
263 send_byte((size >> 8) & 0xff);
264 send_byte((size >> 0) & 0xff);
265 outb(0xe0, PORT_CONTROL); /* TL high, recv mode */
267 for (i = 0; i < size; i++)
269 if ((i & 0xff) == 0) {
270 printf("\b\b\b\b\b\b\b\b\b\b\b\b\b");
271 printf("%06x/%06x", i, size);
275 data[i] = recv_byte();
278 fwrite(data, 1, size, file);
280 printf("\b\b\b\b\b\b\b\b\b\b\b\b\b");
281 printf("%06x/%06x\n", i, size);
284 /* switch TL back to high, disable outputs */
285 outb(0xe0, PORT_CONTROL);