summaryrefslogtreecommitdiff
path: root/extrautils/mmioify.c
blob: bd63406d841787e45e0111d94cf7c4452c513463 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
 * mmioify turns vbtracetool nvidia io logs into mmiotrace logs:
 *
 * Copyright 2007 Stuart Bennett <sb476@cam.ac.uk>
 *
 * This program is released under the terms of the GNU General Public License, version 2
 *
 * output file log-mmt can be parsed with mmio-parse as normal
 * output file *should not* be run with mmio-replay, as the mappings are made up
 */

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define PCIO0	0x00601000

void cheesy_io_parser(char rw, long lineno, int size, uint16_t port, uint32_t data, FILE *outf)
{
	static uint32_t address = 0;

	if (address) {
		if (size == 2) {
			static int bottom = -1;
			if (bottom >= 0) {
				if (port == 0x3d2) {
					fprintf(outf, "%c 4 %ld 1 0x%08x 0x%08x 0x0 0\n", rw, lineno, address, data << 16 | bottom);
					address = 0;
				}
				bottom = -1;
			}
			if (port == 0x3d0)
				bottom = data;
		}
		if (size == 4 && (port == 0x3d0 || port == 0xe80c)) {
			fprintf(outf, "%c 4 %ld 1 0x%08x 0x%08x 0x0 0\n", rw, lineno, address, data);
			address = 0;
		}
	}
	if (rw == 'W' && !address) {
		if (size == 2) {
			static int top = -1;
			if (top >= 0) {
				if (port == 0x3d0)
					address = top | data;
				top = -1;
			}
			if (port == 0x3d2)
				top = data << 16;
		}
		if (size == 4 && (port == 0x3d0 || port == 0xe808))
			address = data;
	}
}

int main(int argc, char *argv[])
{
	FILE *tracef, *outf;
	long lineno = 0;

	char outname[1024];
	strcpy(outname, argv[1]);
	strcat(outname, "-mmt");
	if (!(tracef = fopen(argv[1], "r"))) {
		printf("File open failed\n");
		exit(EXIT_FAILURE);
	}
	if (!(outf = fopen(outname, "w"))) {
		printf("File open failed\n");
		exit(EXIT_FAILURE);
	}

	fprintf(outf, "PCIDEV 0000 10de0000 0 00000000 0 0 0 0 0 0 1000000 0 0 0 0 0 0\n");
	fprintf(outf, "MAP 0 1 0x00000000 0x00000000 0x1000000 0x0 0\n");

	while (!feof(tracef)) {
		char line[180];
		char rw;
		int size = 0;
		uint16_t port;
		uint32_t data;

		if (!fgets(line, 180, tracef))
			break;
		lineno += 1;

		if (strncmp(line, "c000", 4))	/* ignore in-built cheesy io parser's output */
			continue;

		rw = line[10];
		switch (line[11]) {
		case '8':
			size = 1;
			break;
		case '1':
			size = 2;
			break;
		case '3':
			size = 4;
			break;
		}
		port = strtoul(&line[20], NULL, 16);
		data = strtoul(&line[31], NULL, 16);

		if (port == 0x3d0 || port == 0x3d2 || port == 0xe808 || port == 0xe80c) {
			cheesy_io_parser(rw, lineno, size, port, data, outf);
			continue;
		}

		switch (size) {
		case 1:
			fprintf(outf, "%c 1 %ld 1 0x%08x 0x%02x 0x0 0\n", rw, lineno, PCIO0 + port, data);
			break;
		case 2:
			fprintf(outf, "%c 1 %ld 1 0x%08x 0x%02x 0x0 0\n", rw, lineno, PCIO0 + port, data & 0xff);
			fprintf(outf, "%c 1 %ld 1 0x%08x 0x%02x 0x0 0\n", rw, lineno, PCIO0 + port + 1, (data & 0xff00) >> 8);
			break;
		case 4:
			fprintf(outf, "%c 1 %ld 1 0x%08x 0x%02x 0x0 0\n", rw, lineno, PCIO0 + port, data & 0xff);
			fprintf(outf, "%c 1 %ld 1 0x%08x 0x%02x 0x0 0\n", rw, lineno, PCIO0 + port + 1, (data & 0xff00) >> 8);
			fprintf(outf, "%c 1 %ld 1 0x%08x 0x%02x 0x0 0\n", rw, lineno, PCIO0 + port + 2, (data & 0xff0000) >> 16);
			fprintf(outf, "%c 1 %ld 1 0x%08x 0x%02x 0x0 0\n", rw, lineno, PCIO0 + port + 3, (data & 0xff000000) >> 24);
			break;
		case 0:
			printf("size 0!?\n");
			return 1;
		}
	}

	fclose(tracef);
	fclose(outf);

	return 0;
}