1 /*
2  *  Copyright (C) 2004-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: Brooktree BT431, used by TURBOchannel graphics cards
29  *
30  *  TODO.
31  */
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 
37 #include "devices.h"
38 #include "memory.h"
39 #include "misc.h"
40 
41 #include "thirdparty/bt431reg.h"
42 
43 
44 struct bt431_data {
45 	uint32_t	bt431_reg[DEV_BT431_NREGS];
46 
47 	unsigned char	cur_addr_hi;
48 	unsigned char	cur_addr_lo;
49 
50 	int		planes;
51 	int		cursor_on;
52 	int		cursor_x;
53 	int		cursor_y;
54 	int		cursor_xsize;
55 	int		cursor_ysize;
56 
57 	struct vfb_data *vfb_data;
58 };
59 
60 
DEVICE_ACCESS(bt431)61 DEVICE_ACCESS(bt431)
62 {
63 	struct bt431_data *d = (struct bt431_data *) extra;
64 	uint64_t idata = 0, odata = 0;
65 	int btaddr;
66 #if 0
67 	int on, new_cursor_x, new_cursor_y;
68 #endif
69 
70 	if (writeflag == MEM_WRITE)
71 		idata = memory_readmax64(cpu, data, len);
72 
73 	btaddr = ((d->cur_addr_hi << 8) + d->cur_addr_lo) % DEV_BT431_NREGS;
74 
75 /*  TODO  */
76 
77 	/*  Read from/write to the bt431:  */
78 	switch (relative_addr) {
79 	case 0x00:		/*  Low byte of address:  */
80 		if (writeflag == MEM_WRITE) {
81 			debug("[ bt431: write to Low Address Byte, "
82 			    "0x%02x ]\n", (int)idata);
83 			d->cur_addr_lo = idata;
84 		} else {
85 			odata = d->cur_addr_lo;
86 			debug("[ bt431: read from Low Address Byte: "
87 			    "0x%0x ]\n", (int)odata);
88 		}
89 		break;
90 	case 0x04:		/*  High byte of address:  */
91 		if (writeflag == MEM_WRITE) {
92 			debug("[ bt431: write to High Address Byte, "
93 			    "0x%02x ]\n", (int)idata);
94 			d->cur_addr_hi = idata;
95 		} else {
96 			odata = d->cur_addr_hi;
97 			debug("[ bt431: read from High Address Byte: "
98 			    "0x%0x ]\n", (int)odata);
99 		}
100 		break;
101 	case 0x08:		/*  Register access:  */
102 		if (writeflag == MEM_WRITE) {
103 			debug("[ bt431: write to BT431 register 0x%04x, "
104 			    "value 0x%02x ]\n", btaddr, (int)idata);
105 			d->bt431_reg[btaddr] = idata;
106 
107 #if 0
108 			/*  Write to cursor bitmap:  */
109 			if (btaddr >= 0x400)
110 				bt431_sync_xysize(d);
111 #endif
112 		} else {
113 			odata = d->bt431_reg[btaddr];
114 			debug("[ bt431: read from BT431 register 0x%04x, "
115 			    "value 0x%02x ]\n", btaddr, (int)odata);
116 		}
117 
118 		/*  Go to next register:  */
119 		d->cur_addr_lo ++;
120 		if (d->cur_addr_lo == 0)
121 			d->cur_addr_hi ++;
122 		break;
123 	default:
124 		if (writeflag == MEM_WRITE) {
125 			debug("[ bt431: unimplemented write to address "
126 			    "0x%x, data=0x%02x ]\n", (int)relative_addr,
127 			    (int)idata);
128 		} else {
129 			debug("[ bt431: unimplemented read from address "
130 			    "0x%x ]\n", (int)relative_addr);
131 		}
132 	}
133 
134 #if 0
135 
136 TODO: This is from bt459!
137 
138 	/*  NetBSD uses 370,37 as magic values.  */
139 	new_cursor_x = (d->bt431_reg[BT431_REG_CXLO] & 255) +
140 	    ((d->bt431_reg[BT431_REG_CXHI] & 255) << 8) - 370;
141 	new_cursor_y = (d->bt431_reg[BT431_REG_CYLO] & 255) +
142 	    ((d->bt431_reg[BT431_REG_CYHI] & 255) << 8) - 37;
143 
144 	/*  TODO: what do the bits in the CCR do?  */
145 	on = d->bt431_reg[BT431_REG_CCR] ? 1 : 0;
146 
147 on = 1;
148 
149 	if (new_cursor_x != d->cursor_x || new_cursor_y != d->cursor_y ||
150 	    on != d->cursor_on) {
151 		int ysize_mul = 1;
152 
153 		d->cursor_x = new_cursor_x;
154 		d->cursor_y = new_cursor_y;
155 		d->cursor_on = on;
156 
157 		/*
158 		 *  Ugly hack for Ultrix:
159 		 *
160 		 *  Ultrix and NetBSD assume that the cursor works differently.
161 		 *  Ultrix uses the 370,38 coordinates, but draws the cursor
162 		 *  upwards. NetBSD draws it downwards.  Ultrix also makes the
163 		 *  cursor smaller (?).
164 		 *
165 		 *  TODO:  This actually depends on which ultrix kernel you use.
166 		 *  Clearly, the BT459 emulation is not implemented well
167 		 *  enough yet.
168 		 *
169 		 *  TODO:  Find out why? Is it because of special BT459
170 		 *  commands?
171 		 *
172 		 *  TODO: Is the above text even valid anymore? :-)
173 		 */
174 		if (!(d->bt431_reg[BT431_REG_CCR] & 1)) {
175 /*			ysize_mul = 4; */
176 			d->cursor_y += 5 - (d->cursor_ysize * ysize_mul);
177 		}
178 
179 		debug("[ bt431: cursor = %03i,%03i ]\n", d->cursor_x,
180 		    d->cursor_y);
181 		dev_fb_setcursor(d->vfb_data, d->cursor_x, d->cursor_y, on,
182 		    d->cursor_xsize, d->cursor_ysize * ysize_mul);
183 	}
184 #endif
185 
186 	if (writeflag == MEM_READ)
187 		memory_writemax64(cpu, data, len, odata);
188 
189 	return 1;
190 }
191 
192 
193 /*
194  *  dev_bt431_init():
195  */
dev_bt431_init(struct memory * mem,uint64_t baseaddr,struct vfb_data * vfb_data,int planes)196 void dev_bt431_init(struct memory *mem, uint64_t baseaddr,
197 	struct vfb_data *vfb_data, int planes)
198 {
199 	struct bt431_data *d;
200 
201 	CHECK_ALLOCATION(d = (struct bt431_data *) malloc(sizeof(struct bt431_data)));
202 	memset(d, 0, sizeof(struct bt431_data));
203 
204 	d->vfb_data     = vfb_data;
205 	d->planes       = planes;
206 	d->cursor_x     = -1;
207 	d->cursor_y     = -1;
208 	d->cursor_xsize = d->cursor_ysize = 8;	/*  anything  */
209 
210 	memory_device_register(mem, "bt431", baseaddr, DEV_BT431_LENGTH,
211 	    dev_bt431_access, (void *)d, DM_DEFAULT, NULL);
212 }
213 
214