m-chrzan.xyz
aboutsummaryrefslogtreecommitdiff
path: root/harddoomdev.c
blob: e4f6e800df0e67b0c4f9f82f588dcca2a9fb3667 (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
#include "harddoomdev.h"

#include "harddoom.h"
#include "doomcode.h"
#include "pci.h"
#include "private_data.h"
#include "util.h"

void doomdev_write(void __iomem *iomem, size_t addr, uint32_t data)
{
	iowrite32(data, iomem + addr);
}

uint32_t doomdev_read(void __iomem *iomem, size_t addr)
{
	return ioread32(iomem + addr);
}

void write_command(void __iomem *iomem, uint32_t command)
{
	doomdev_write(iomem, HARDDOOM_FIFO_SEND, command);
}

void send_command(void __iomem *iomem, uint32_t command)
{
	while (doomdev_read(iomem, HARDDOOM_FIFO_FREE) == 0) {}

	write_command(iomem, command);
}

uint32_t get_interrupts(void __iomem *iomem)
{
	return doomdev_read(iomem, HARDDOOM_INTR);
}

void deactivate_intr(void __iomem *iomem, uint32_t intr)
{
	doomdev_write(iomem, HARDDOOM_INTR, intr);
}

void ping_sync(void __iomem *iomem)
{
	send_command(iomem, HARDDOOM_CMD_PING_SYNC);
}

void set_surf_dst_pt(void __iomem *iomem, dma_addr_t page_table)
{
	send_command(iomem, HARDDOOM_CMD_SURF_DST_PT(page_table));
}

void set_surf_dims(void __iomem *iomem, uint32_t width, uint32_t height)
{
	send_command(iomem, HARDDOOM_CMD_SURF_DIMS(width, height));
}

void set_xy_a(void __iomem *iomem, uint16_t x, uint16_t y)
{
	send_command(iomem, HARDDOOM_CMD_XY_A(x, y));
}

void set_xy_b(void __iomem *iomem, uint16_t x, uint16_t y)
{
	send_command(iomem, HARDDOOM_CMD_XY_B(x, y));
}

void set_fill_color(void __iomem *iomem, uint8_t color)
{
	send_command(iomem, HARDDOOM_CMD_FILL_COLOR(color));
}

void draw_line(struct surface_data *surface_data, struct doomdev_line line)
{
	void __iomem *iomem;

	iomem = surface_data->doom_data->iomem;

	set_surf_dst_pt(iomem, surface_data->page_table_dev);
	set_surf_dims(iomem, surface_data->width, surface_data->height);
	set_xy_a(iomem, line.pos_a_x, line.pos_a_y);
	set_xy_b(iomem, line.pos_b_x, line.pos_b_y);
	set_fill_color(iomem, line.color);

	send_command(iomem, HARDDOOM_CMD_DRAW_LINE);
}

uint32_t doomdev_read_stat(void __iomem *iomem, size_t stat)
{
	return doomdev_read(iomem, HARDDOOM_STATS(stat));
}

void load_microcode(void __iomem *iomem)
{
	int i;

	doomdev_write(iomem, HARDDOOM_FE_CODE_ADDR, 0);
	for (i = 0; i < ARRAY_SIZE(doomcode); i++) {
		doomdev_write(iomem, HARDDOOM_FE_CODE_WINDOW, doomcode[i]);
	}
}

void start_dev(struct pci_dev *dev)
{
	struct doom_data *data;
	void __iomem *iomem;

	data = pci_get_drvdata(dev);
	iomem = data->iomem;

	load_microcode(iomem);
	doomdev_write(iomem, HARDDOOM_RESET, 0xffffffe);
	doomdev_write(iomem, HARDDOOM_INTR, HARDDOOM_INTR_MASK);
	doomdev_write(iomem, HARDDOOM_INTR_ENABLE, HARDDOOM_INTR_MASK);
	doomdev_write(iomem, HARDDOOM_ENABLE,
			HARDDOOM_ENABLE_ALL ^ HARDDOOM_ENABLE_FETCH_CMD);
}

void shutdown_dev(struct pci_dev *dev)
{
	struct doom_data *data;
	void __iomem *iomem;

	data = pci_get_drvdata(dev);
	iomem = data->iomem;

	doomdev_write(iomem, HARDDOOM_ENABLE, 0);
	doomdev_write(iomem, HARDDOOM_INTR_ENABLE, 0);
	doomdev_read(iomem, 0);
}