1 /*
2 * Copyright (C) 2003-2009 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: DEC KN01 ("PMAX", DECstation type 1) control register and VDAC
29 *
30 * TODO: The CSR isn't really complete.
31 *
32 * One of the few usable bits in the csr would be KN01_CSR_MONO.
33 * If that bit is set, the framebuffer is treated as a monochrome
34 * one.
35 */
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40
41 #include "cpu.h"
42 #include "devices.h"
43 #include "memory.h"
44 #include "misc.h"
45
46 #include "thirdparty/dec_kn01.h"
47
48
49 struct kn01_data {
50 int color_fb;
51 uint32_t csr;
52 };
53
54
55 struct vdac_data {
56 unsigned char vdac_reg[DEV_VDAC_LENGTH];
57
58 int color_fb_flag;
59
60 unsigned char cur_read_addr;
61 unsigned char cur_write_addr;
62
63 int sub_color; /* subcolor. 0, 1, or 2 */
64 unsigned char cur_rgb[3];
65
66 unsigned char *rgb_palette; /* ptr to 256 * 3 (r,g,b) */
67
68 unsigned char cur_read_addr_overlay;
69 unsigned char cur_write_addr_overlay;
70
71 int sub_color_overlay; /* subcolor: 0, 1, or 2 */
72 unsigned char cur_rgb_overlay[3];
73
74 unsigned char rgb_palette_overlay[16 * 3]; /* 16 * 3 (r,g,b) */
75 };
76
77
DEVICE_ACCESS(kn01)78 DEVICE_ACCESS(kn01)
79 {
80 struct kn01_data *d = (struct kn01_data *) extra;
81 int csr;
82
83 if (writeflag == MEM_WRITE) {
84 /* TODO */
85 return 1;
86 }
87
88 /* Read: */
89 if (len != 2 || relative_addr != 0) {
90 fatal("[ kn01: trying to read something which is not "
91 "the first half-word of the csr ]");
92 }
93
94 csr = d->csr;
95
96 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
97 data[0] = csr & 0xff;
98 data[1] = (csr >> 8) & 0xff;
99 } else {
100 data[1] = csr & 0xff;
101 data[0] = (csr >> 8) & 0xff;
102 }
103
104 return 1;
105 }
106
107
108 /*
109 * dev_vdac_access():
110 */
DEVICE_ACCESS(vdac)111 DEVICE_ACCESS(vdac)
112 {
113 struct vdac_data *d = (struct vdac_data *) extra;
114
115 /* Read from/write to the vdac: */
116 switch (relative_addr) {
117 case DEV_VDAC_MAPWA:
118 if (writeflag == MEM_WRITE) {
119 d->cur_write_addr = data[0];
120 d->sub_color = 0;
121 } else {
122 debug("[ vdac: read from MAPWA ]\n");
123 data[0] = d->vdac_reg[relative_addr];
124 }
125 break;
126 case DEV_VDAC_MAP:
127 if (writeflag == MEM_WRITE) {
128 d->cur_rgb[d->sub_color] = data[0];
129 d->sub_color++;
130
131 if (d->sub_color > 2) {
132 /* (Only update for color, not mono mode) */
133 if (d->color_fb_flag)
134 memcpy(d->rgb_palette +
135 3*d->cur_write_addr, d->cur_rgb, 3);
136
137 d->sub_color = 0;
138 d->cur_write_addr ++;
139 }
140 } else {
141 if (d->sub_color == 0) {
142 memcpy(d->cur_rgb, d->rgb_palette +
143 3 * d->cur_read_addr, 3);
144 }
145 data[0] = d->cur_rgb[d->sub_color];
146 d->sub_color++;
147 if (d->sub_color > 2) {
148 d->sub_color = 0;
149 d->cur_read_addr ++;
150 }
151 }
152 break;
153 case DEV_VDAC_MAPRA:
154 if (writeflag == MEM_WRITE) {
155 d->cur_read_addr = data[0];
156 d->sub_color = 0;
157 } else {
158 debug("[ vdac: read from MAPRA ]\n");
159 data[0] = d->vdac_reg[relative_addr];
160 }
161 break;
162 case DEV_VDAC_OVERWA:
163 if (writeflag == MEM_WRITE) {
164 d->cur_write_addr_overlay = data[0];
165 d->sub_color_overlay = 0;
166 } else {
167 debug("[ vdac: read from OVERWA ]\n");
168 data[0] = d->vdac_reg[relative_addr];
169 }
170 break;
171 case DEV_VDAC_OVER:
172 if (writeflag == MEM_WRITE) {
173 d->cur_rgb_overlay[d->sub_color_overlay] = data[0];
174 d->sub_color_overlay++;
175
176 if (d->sub_color_overlay > 2) {
177 /* (Only update for color, not mono mode) */
178 if (d->color_fb_flag)
179 memcpy(d->rgb_palette_overlay +
180 3 * d->cur_write_addr_overlay,
181 d->cur_rgb_overlay, 3);
182
183 d->sub_color_overlay = 0;
184 d->cur_write_addr_overlay ++;
185 if (d->cur_write_addr_overlay > 15)
186 d->cur_write_addr_overlay = 0;
187 }
188 } else {
189 if (d->sub_color_overlay == 0) {
190 memcpy(d->cur_rgb_overlay,
191 d->rgb_palette_overlay +
192 3 * d->cur_read_addr_overlay, 3);
193 }
194 data[0] = d->cur_rgb_overlay[d->sub_color_overlay];
195 d->sub_color_overlay++;
196 if (d->sub_color_overlay > 2) {
197 d->sub_color_overlay = 0;
198 d->cur_read_addr_overlay ++;
199 if (d->cur_read_addr_overlay > 15)
200 d->cur_read_addr_overlay = 0;
201 }
202 }
203 break;
204 case DEV_VDAC_OVERRA:
205 if (writeflag == MEM_WRITE) {
206 d->cur_read_addr_overlay = data[0];
207 d->sub_color_overlay = 0;
208 } else {
209 debug("[ vdac: read from OVERRA ]\n");
210 data[0] = d->vdac_reg[relative_addr];
211 }
212 break;
213 default:
214 if (writeflag == MEM_WRITE) {
215 debug("[ vdac: unimplemented write to address 0x%x,"
216 " data=0x%02x ]\n", (int)relative_addr, data[0]);
217 d->vdac_reg[relative_addr] = data[0];
218 } else {
219 debug("[ vdac: unimplemented read from address 0x%x"
220 " ]\n", (int)relative_addr);
221 data[0] = d->vdac_reg[relative_addr];
222 }
223 }
224
225 /* Pretend it was ok: */
226 return 1;
227 }
228
229
230 /*
231 * dev_vdac_init():
232 */
dev_vdac_init(struct memory * mem,uint64_t baseaddr,unsigned char * rgb_palette,int color_fb_flag)233 void dev_vdac_init(struct memory *mem, uint64_t baseaddr,
234 unsigned char *rgb_palette, int color_fb_flag)
235 {
236 struct vdac_data *d;
237
238 CHECK_ALLOCATION(d = (struct vdac_data *) malloc(sizeof(struct vdac_data)));
239 memset(d, 0, sizeof(struct vdac_data));
240
241 d->rgb_palette = rgb_palette;
242 d->color_fb_flag = color_fb_flag;
243
244 memory_device_register(mem, "vdac", baseaddr, DEV_VDAC_LENGTH,
245 dev_vdac_access, (void *)d, DM_DEFAULT, NULL);
246 }
247
248
249 /*
250 * dev_kn01_init():
251 */
dev_kn01_init(struct memory * mem,uint64_t baseaddr,int color_fb)252 void dev_kn01_init(struct memory *mem, uint64_t baseaddr, int color_fb)
253 {
254 struct kn01_data *d;
255
256 CHECK_ALLOCATION(d = (struct kn01_data *) malloc(sizeof(struct kn01_data)));
257 memset(d, 0, sizeof(struct kn01_data));
258
259 d->color_fb = color_fb;
260 d->csr = 0;
261 d->csr |= (color_fb? 0 : KN01_CSR_MONO);
262
263 memory_device_register(mem, "kn01", baseaddr,
264 DEV_KN01_LENGTH, dev_kn01_access, d, DM_DEFAULT, NULL);
265 }
266
267