1 /*
2 * Copyright (C) 2006-2018 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * COMMENT: Framebuffer controller device (control's dev_fb in test machines)
29 *
30 * A "framebuffer control" device. It can be used to manipulate the
31 * framebuffer device in testmachines.
32 */
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 #include "cpu.h"
39 #include "device.h"
40 #include "devices.h"
41 #include "machine.h"
42 #include "memory.h"
43 #include "misc.h"
44
45 #include "testmachine/dev_fb.h"
46
47
48 struct fbctrl_data {
49 struct vfb_data *vfb_data;
50 int current_port;
51 int port[DEV_FBCTRL_NPORTS];
52 };
53
54
55 /*
56 * fbctrl_command():
57 *
58 * Execute a framebuffer control command.
59 */
fbctrl_command(struct cpu * cpu,struct fbctrl_data * d)60 static void fbctrl_command(struct cpu *cpu, struct fbctrl_data *d)
61 {
62 int cmd = d->port[DEV_FBCTRL_PORT_COMMAND];
63 int x1, y1, i;
64
65 switch (cmd) {
66
67 case DEV_FBCTRL_COMMAND_NOP:
68 break;
69
70 case DEV_FBCTRL_COMMAND_SET_RESOLUTION:
71 /*
72 * Change the framebuffer resolution to X1 x Y1 pixels.
73 */
74 x1 = d->port[DEV_FBCTRL_PORT_X1];
75 y1 = d->port[DEV_FBCTRL_PORT_Y1];
76 debug("[ dev_fbctrl: changing resolution to %i,%i ]\n", x1, y1);
77
78 dev_fb_resize(d->vfb_data, x1, y1);
79
80 /* Remember to invalidate all translations for anyone
81 who might have used the old framebuffer: */
82 for (i = 0; i < cpu->machine->ncpus; i++)
83 cpu->machine->cpus[i]->invalidate_translation_caches(
84 cpu->machine->cpus[i], 0, INVALIDATE_ALL);
85 break;
86
87 case DEV_FBCTRL_COMMAND_GET_RESOLUTION:
88 if (cpu->machine->x11_md.in_use) {
89 d->port[DEV_FBCTRL_PORT_X1] = d->vfb_data->xsize;
90 d->port[DEV_FBCTRL_PORT_Y1] = d->vfb_data->ysize;
91 } else {
92 // When not using X11 output, return 0x0 size.
93 d->port[DEV_FBCTRL_PORT_X1] = 0;
94 d->port[DEV_FBCTRL_PORT_Y1] = 0;
95 }
96 break;
97
98 /* TODO: Block copy and fill. */
99
100 default:fatal("fbctrl_command: Unimplemented command %i.\n", cmd);
101 exit(1);
102 }
103 }
104
105
DEVICE_ACCESS(fbctrl)106 DEVICE_ACCESS(fbctrl)
107 {
108 struct fbctrl_data *d = (struct fbctrl_data *) extra;
109 uint64_t idata = 0, odata = 0;
110
111 if (writeflag == MEM_WRITE)
112 idata = memory_readmax64(cpu, data, len);
113
114 switch (relative_addr) {
115
116 case DEV_FBCTRL_PORT:
117 if (writeflag == MEM_READ)
118 odata = d->current_port;
119 else {
120 d->current_port = idata;
121 if (idata >= DEV_FBCTRL_NPORTS)
122 fatal("[ WARNING: fbctrl port number is out"
123 " of range! ]\n");
124 }
125 break;
126
127 case DEV_FBCTRL_DATA:
128 if (d->current_port < 0 || d->current_port
129 >= DEV_FBCTRL_NPORTS) {
130 fatal("[ fbctrl port number is out of range! ]\n");
131 exit(1);
132 }
133
134 if (writeflag == MEM_READ)
135 odata = d->port[d->current_port];
136 else {
137 d->port[d->current_port] = idata;
138 if (d->current_port == DEV_FBCTRL_PORT_COMMAND)
139 fbctrl_command(cpu, d);
140 }
141
142 break;
143
144 default:
145 fatal("[ dev_fbctrl: unimplemented relative addr 0x%x ]\n",
146 (int)relative_addr);
147 exit(1);
148 }
149
150 if (writeflag == MEM_READ)
151 memory_writemax64(cpu, data, len, odata);
152
153 return 1;
154 }
155
156
DEVINIT(fbctrl)157 DEVINIT(fbctrl)
158 {
159 struct fbctrl_data *d;
160
161 CHECK_ALLOCATION(d = (struct fbctrl_data *) malloc(sizeof(struct fbctrl_data)));
162 memset(d, 0, sizeof(struct fbctrl_data));
163
164 d->vfb_data = dev_fb_init(devinit->machine, devinit->machine->memory,
165 DEV_FB_ADDRESS, VFB_GENERIC, 640, 480, 640, DEV_FBCTRL_MAXY(640),
166 24, "generic");
167
168 memory_device_register(devinit->machine->memory, devinit->name,
169 devinit->addr, DEV_FBCTRL_LENGTH, dev_fbctrl_access, d,
170 DM_DEFAULT, NULL);
171
172 return 1;
173 }
174
175