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