]> git.sesse.net Git - pistorm/blob - buptest.c
Add Meson build files.
[pistorm] / buptest.c
1 // SPDX-License-Identifier: MIT
2
3 #include <assert.h>
4 #include <dirent.h>
5 #include <endian.h>
6 #include <fcntl.h>
7 #include <pthread.h>
8 #include <sched.h>
9 #include <signal.h>
10 #include <stdint.h>
11 #include <stdio.h>
12 #include <time.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <sys/mman.h>
16 #include <sys/stat.h>
17 #include <sys/types.h>
18 #include <unistd.h>
19 #include <sys/ioctl.h>
20 #include "emulator.h"
21 #include "gpio/ps_protocol.h"
22
23 #define SIZE_KILO 1024
24 #define SIZE_MEGA (1024 * 1024)
25 #define SIZE_GIGA (1024 * 1024 * 1024)
26
27 uint8_t *garbege_datas;
28 extern volatile unsigned int *gpio;
29
30 struct timespec f2;
31
32 uint8_t gayle_int;
33 uint32_t mem_fd;
34 uint32_t errors = 0;
35 uint8_t loop_tests = 0, total_errors = 0;
36
37 void sigint_handler(int sig_num) {
38   printf("Received sigint %d, exiting.\n", sig_num);
39   printf("Total number of transaction errors occured: %d\n", total_errors);
40   if (mem_fd)
41     close(mem_fd);
42
43   exit(0);
44 }
45
46 void ps_reinit() {
47     ps_reset_state_machine();
48     ps_pulse_reset();
49
50     usleep(1500);
51
52     write8(0xbfe201, 0x0101);       //CIA OVL
53         write8(0xbfe001, 0x0000);       //CIA OVL LOW
54 }
55
56 unsigned int dump_read_8(unsigned int address) {
57     uint32_t bwait = 0;
58
59     *(gpio + 0) = GPFSEL0_OUTPUT;
60     *(gpio + 1) = GPFSEL1_OUTPUT;
61     *(gpio + 2) = GPFSEL2_OUTPUT;
62
63     *(gpio + 7) = ((address & 0xffff) << 8) | (REG_ADDR_LO << PIN_A0);
64     *(gpio + 7) = 1 << PIN_WR;
65     *(gpio + 10) = 1 << PIN_WR;
66     *(gpio + 10) = 0xffffec;
67
68     *(gpio + 7) = ((0x0300 | (address >> 16)) << 8) | (REG_ADDR_HI << PIN_A0);
69     *(gpio + 7) = 1 << PIN_WR;
70     *(gpio + 10) = 1 << PIN_WR;
71     *(gpio + 10) = 0xffffec;
72
73     *(gpio + 0) = GPFSEL0_INPUT;
74     *(gpio + 1) = GPFSEL1_INPUT;
75     *(gpio + 2) = GPFSEL2_INPUT;
76
77     *(gpio + 7) = (REG_DATA << PIN_A0);
78     *(gpio + 7) = 1 << PIN_RD;
79
80
81     while (bwait < 10000 && (*(gpio + 13) & (1 << PIN_TXN_IN_PROGRESS))) {
82         bwait++;
83     }
84
85     unsigned int value = *(gpio + 13);
86
87     *(gpio + 10) = 0xffffec;
88
89     value = (value >> 8) & 0xffff;
90
91     if (bwait == 10000) {
92         ps_reinit();
93     }
94
95     if ((address & 1) == 0)
96         return (value >> 8) & 0xff;  // EVEN, A0=0,UDS
97     else
98         return value & 0xff;  // ODD , A0=1,LDS
99 }
100
101 int main(int argc, char *argv[]) {
102     uint32_t test_size = 512 * SIZE_KILO, cur_loop = 0;
103
104     clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &f2);
105     srand((unsigned int)f2.tv_nsec);
106
107     signal(SIGINT, sigint_handler);
108
109     ps_setup_protocol();
110     ps_reset_state_machine();
111     ps_pulse_reset();
112
113     usleep(1500);
114
115     write8(0xbfe201, 0x0101);       //CIA OVL
116         write8(0xbfe001, 0x0000);       //CIA OVL LOW
117
118     if (argc > 1) {
119         if (strcmp(argv[1], "dumpkick") == 0) {
120             printf ("Dumping onboard Amiga kickstart from $F80000 to file kick.rom.\n");
121             printf ("Note that this will always dump 512KB of data, even if your Kickstart is 256KB.\n");
122             FILE *out = fopen("kick.rom", "wb+");
123             if (out == NULL) {
124                 printf ("Failed to open kick.rom for writing.\nKickstart has not been dumped.\n");
125                 return 1;
126             }
127
128             for (int i = 0; i < 512 * SIZE_KILO; i++) {
129                 unsigned char in = read8(0xF80000 + i);
130                 fputc(in, out);
131             }
132
133             fclose(out);
134             printf ("Amiga Kickstart ROM dumped.\n");
135             return 0;
136         }
137
138         if (strcmp(argv[1], "dump") == 0) {
139             printf ("Dumping EVERYTHING to dump.bin.\n");
140             FILE *out = fopen("dump.bin", "wb+");
141             if (out == NULL) {
142                 printf ("Failed to open dump.bin for writing.\nEverything has not been dumped.\n");
143                 return 1;
144             }
145
146             for (int i = 0; i < 16 * SIZE_MEGA; i++) {
147                 unsigned char in = dump_read_8(i);
148                 fputc(in, out);
149                 if (!(i % 1024))
150                     printf (".");
151             }
152             printf ("\n");
153
154             fclose(out);
155             printf ("Dumped everything.\n");
156             return 0;
157         }
158
159         test_size = atoi(argv[1]) * SIZE_KILO;
160         if (test_size == 0 || test_size > 2 * SIZE_MEGA) {
161             test_size = 512 * SIZE_KILO;
162         }
163         printf("Testing %d KB of memory.\n", test_size / SIZE_KILO);
164         if (argc > 2) {
165             if (strcmp(argv[2], "l") == 0) {
166                 printf("Looping tests.\n");
167                 loop_tests = 1;
168             }
169         }
170     }
171
172     garbege_datas = malloc(test_size);
173     if (!garbege_datas) {
174         printf ("Failed to allocate memory for garbege datas.\n");
175         return 1;
176     }
177
178 test_loop:;
179     printf("Writing garbege datas.\n");
180     for (uint32_t i = 0; i < test_size; i++) {
181         while(garbege_datas[i] == 0x00)
182             garbege_datas[i] = (uint8_t)(rand() % 0xFF);
183         write8(i, (uint32_t)garbege_datas[i]);
184     }
185
186     printf("Reading back garbege datas, read8()...\n");
187     for (uint32_t i = 0; i < test_size; i++) {
188         uint32_t c = read8(i);
189         if (c != garbege_datas[i]) {
190             if (errors < 512)
191                 printf("READ8: Garbege data mismatch at $%.6X: %.2X should be %.2X.\n", i, c, garbege_datas[i]);
192             errors++;
193         }
194     }
195     printf("read8 errors total: %d.\n", errors);
196     total_errors += errors;
197     errors = 0;
198     sleep (1);
199
200     printf("Reading back garbege datas, read16(), even addresses...\n");
201     for (uint32_t i = 0; i < (test_size) - 2; i += 2) {
202         uint32_t c = be16toh(read16(i));
203         if (c != *((uint16_t *)&garbege_datas[i])) {
204             if (errors < 512)
205                 printf("READ16_EVEN: Garbege data mismatch at $%.6X: %.4X should be %.4X.\n", i, c, *((uint16_t *)&garbege_datas[i]));
206             errors++;
207         }
208     }
209     printf("read16 even errors total: %d.\n", errors);
210     total_errors += errors;
211     errors = 0;
212     sleep (1);
213
214     printf("Reading back garbege datas, read16(), odd addresses...\n");
215     for (uint32_t i = 1; i < (test_size) - 2; i += 2) {
216         uint32_t c = be16toh((read8(i) << 8) | read8(i + 1));
217         if (c != *((uint16_t *)&garbege_datas[i])) {
218             if (errors < 512)
219                 printf("READ16_ODD: Garbege data mismatch at $%.6X: %.4X should be %.4X.\n", i, c, *((uint16_t *)&garbege_datas[i]));
220             errors++;
221         }
222     }
223     printf("read16 odd errors total: %d.\n", errors);
224     errors = 0;
225     sleep (1);
226
227     printf("Reading back garbege datas, read32(), even addresses...\n");
228     for (uint32_t i = 0; i < (test_size) - 4; i += 2) {
229         uint32_t c = be32toh(read32(i));
230         if (c != *((uint32_t *)&garbege_datas[i])) {
231             if (errors < 512)
232                 printf("READ32_EVEN: Garbege data mismatch at $%.6X: %.8X should be %.8X.\n", i, c, *((uint32_t *)&garbege_datas[i]));
233             errors++;
234         }
235     }
236     printf("read32 even errors total: %d.\n", errors);
237     total_errors += errors;
238     errors = 0;
239     sleep (1);
240
241     printf("Reading back garbege datas, read32(), odd addresses...\n");
242     for (uint32_t i = 1; i < (test_size) - 4; i += 2) {
243         uint32_t c = read8(i);
244         c |= (be16toh(read16(i + 1)) << 8);
245         c |= (read8(i + 3) << 24);
246         if (c != *((uint32_t *)&garbege_datas[i])) {
247             if (errors < 512)
248                 printf("READ32_ODD: Garbege data mismatch at $%.6X: %.8X should be %.8X.\n", i, c, *((uint32_t *)&garbege_datas[i]));
249             errors++;
250         }
251     }
252     printf("read32 odd errors total: %d.\n", errors);
253     total_errors += errors;
254     errors = 0;
255     sleep (1);
256
257     printf("Clearing %d KB of Chip again\n", test_size / SIZE_KILO);
258     for (uint32_t i = 0; i < test_size; i++) {
259         write8(i, (uint32_t)0x0);
260     }
261
262     printf("[WORD] Writing garbege datas to Chip, unaligned...\n");
263     for (uint32_t i = 1; i < (test_size) - 2; i += 2) {
264         uint16_t v = *((uint16_t *)&garbege_datas[i]);
265         write8(i, (v & 0x00FF));
266         write8(i + 1, (v >> 8));
267     }
268
269     sleep (1);
270     printf("Reading back garbege datas, read16(), odd addresses...\n");
271     for (uint32_t i = 1; i < (test_size) - 2; i += 2) {
272         uint32_t c = be16toh((read8(i) << 8) | read8(i + 1));
273         if (c != *((uint16_t *)&garbege_datas[i])) {
274             if (errors < 512)
275                 printf("READ16_ODD: Garbege data mismatch at $%.6X: %.4X should be %.4X.\n", i, c, *((uint16_t *)&garbege_datas[i]));
276             errors++;
277         }
278     }
279     printf("read16 odd errors total: %d.\n", errors);
280     total_errors += errors;
281     errors = 0;
282
283     printf("Clearing %d KB of Chip again\n", test_size / SIZE_KILO);
284     for (uint32_t i = 0; i < test_size; i++) {
285         write8(i, (uint32_t)0x0);
286     }
287
288     printf("[LONG] Writing garbege datas to Chip, unaligned...\n");
289     for (uint32_t i = 1; i < (test_size) - 4; i += 4) {
290         uint32_t v = *((uint32_t *)&garbege_datas[i]);
291         write8(i , v & 0x0000FF);
292         write16(i + 1, htobe16(((v & 0x00FFFF00) >> 8)));
293         write8(i + 3 , (v & 0xFF000000) >> 24);
294     }
295
296     sleep (1);
297     printf("Reading back garbege datas, read32(), odd addresses...\n");
298     for (uint32_t i = 1; i < (test_size) - 4; i += 4) {
299         uint32_t c = read8(i);
300         c |= (be16toh(read16(i + 1)) << 8);
301         c |= (read8(i + 3) << 24);
302         if (c != *((uint32_t *)&garbege_datas[i])) {
303             if (errors < 512)
304                 printf("READ32_ODD: Garbege data mismatch at $%.6X: %.8X should be %.8X.\n", i, c, *((uint32_t *)&garbege_datas[i]));
305             errors++;
306         }
307     }
308     printf("read32 odd errors total: %d.\n", errors);
309     total_errors += errors;
310     errors = 0;
311
312     if (loop_tests) {
313         printf ("Loop %d done. Begin loop %d.\n", cur_loop + 1, cur_loop + 2);
314         printf ("Current total errors: %d.\n", total_errors);
315         goto test_loop;
316     }
317
318     return 0;
319 }
320
321 void m68k_set_irq(unsigned int level) {
322 }