grtwo.c revision 1.1 1 1.1 sekiya /* $NetBSD: grtwo.c,v 1.1 2004/03/18 08:52:04 sekiya Exp $ */
2 1.1 sekiya
3 1.1 sekiya /*
4 1.1 sekiya * Copyright (c) 2004 Christopher SEKIYA
5 1.1 sekiya * All rights reserved.
6 1.1 sekiya *
7 1.1 sekiya * Redistribution and use in source and binary forms, with or without
8 1.1 sekiya * modification, are permitted provided that the following conditions
9 1.1 sekiya * are met:
10 1.1 sekiya * 1. Redistributions of source code must retain the above copyright
11 1.1 sekiya * notice, this list of conditions and the following disclaimer.
12 1.1 sekiya * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 sekiya * notice, this list of conditions and the following disclaimer in the
14 1.1 sekiya * documentation and/or other materials provided with the distribution.
15 1.1 sekiya * 3. The name of the author may not be used to endorse or promote products
16 1.1 sekiya * derived from this software without specific prior written permission.
17 1.1 sekiya *
18 1.1 sekiya * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 1.1 sekiya * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 1.1 sekiya * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 1.1 sekiya * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 1.1 sekiya * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 1.1 sekiya * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 1.1 sekiya * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 1.1 sekiya * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 1.1 sekiya * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 1.1 sekiya * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 1.1 sekiya *
29 1.1 sekiya * <<Id: LICENSE_GC,v 1.1 2001/10/01 23:24:05 cgd Exp>>
30 1.1 sekiya */
31 1.1 sekiya
32 1.1 sekiya /* wscons driver for SGI GR2 family of framebuffers
33 1.1 sekiya *
34 1.1 sekiya * Heavily based on the newport wscons driver.
35 1.1 sekiya */
36 1.1 sekiya
37 1.1 sekiya #include <sys/cdefs.h>
38 1.1 sekiya __KERNEL_RCSID(0, "$NetBSD: grtwo.c,v 1.1 2004/03/18 08:52:04 sekiya Exp $");
39 1.1 sekiya
40 1.1 sekiya #include <sys/param.h>
41 1.1 sekiya #include <sys/systm.h>
42 1.1 sekiya #include <sys/device.h>
43 1.1 sekiya #include <sys/malloc.h>
44 1.1 sekiya
45 1.1 sekiya #include <dev/wscons/wsconsio.h>
46 1.1 sekiya #include <dev/wscons/wsdisplayvar.h>
47 1.1 sekiya #include <dev/wsfont/wsfont.h>
48 1.1 sekiya
49 1.1 sekiya #include <sgimips/gio/giovar.h>
50 1.1 sekiya #include <sgimips/gio/grtwovar.h>
51 1.1 sekiya #include <sgimips/gio/grtworeg.h>
52 1.1 sekiya
53 1.1 sekiya #include <sgimips/dev/int2var.h>
54 1.1 sekiya
55 1.1 sekiya struct grtwo_softc {
56 1.1 sekiya struct device sc_dev;
57 1.1 sekiya
58 1.1 sekiya struct grtwo_devconfig *sc_dc;
59 1.1 sekiya };
60 1.1 sekiya
61 1.1 sekiya struct grtwo_devconfig {
62 1.1 sekiya u_int32_t dc_addr;
63 1.1 sekiya
64 1.1 sekiya bus_space_tag_t iot;
65 1.1 sekiya bus_space_handle_t ioh;
66 1.1 sekiya
67 1.1 sekiya u_int8_t boardrev;
68 1.1 sekiya u_int8_t backendrev;
69 1.1 sekiya int hq2rev;
70 1.1 sekiya int ge7rev;
71 1.1 sekiya int vc1rev;
72 1.1 sekiya int zbuffer;
73 1.1 sekiya int cmaprev;
74 1.1 sekiya int xmaprev;
75 1.1 sekiya int rexrev;
76 1.1 sekiya int xres;
77 1.1 sekiya int yres;
78 1.1 sekiya int depth;
79 1.1 sekiya int monitor;
80 1.1 sekiya
81 1.1 sekiya int dc_font;
82 1.1 sekiya struct wsdisplay_font *dc_fontdata;
83 1.1 sekiya };
84 1.1 sekiya
85 1.1 sekiya static int grtwo_match(struct device *, struct cfdata *, void *);
86 1.1 sekiya static void grtwo_attach(struct device *, struct device *, void *);
87 1.1 sekiya
88 1.1 sekiya CFATTACH_DECL(grtwo, sizeof(struct grtwo_softc),
89 1.1 sekiya grtwo_match, grtwo_attach, NULL, NULL);
90 1.1 sekiya
91 1.1 sekiya /* textops */
92 1.1 sekiya static void grtwo_cursor(void *, int, int, int);
93 1.1 sekiya static int grtwo_mapchar(void *, int, unsigned int *);
94 1.1 sekiya static void grtwo_putchar(void *, int, int, u_int, long);
95 1.1 sekiya static void grtwo_copycols(void *, int, int, int, int);
96 1.1 sekiya static void grtwo_erasecols(void *, int, int, int, long);
97 1.1 sekiya static void grtwo_copyrows(void *, int, int, int);
98 1.1 sekiya static void grtwo_eraserows(void *, int, int, long);
99 1.1 sekiya static int grtwo_allocattr(void *, int, int, int, long *);
100 1.1 sekiya
101 1.1 sekiya /* accessops */
102 1.1 sekiya static int grtwo_ioctl(void *, u_long, caddr_t, int, struct proc *);
103 1.1 sekiya static paddr_t grtwo_mmap(void *, off_t, int);
104 1.1 sekiya static int
105 1.1 sekiya grtwo_alloc_screen(void *, const struct wsscreen_descr *,
106 1.1 sekiya void **, int *, int *, long *);
107 1.1 sekiya static void grtwo_free_screen(void *, void *);
108 1.1 sekiya static int
109 1.1 sekiya grtwo_show_screen(void *, void *, int, void (*) (void *, int, int), void *);
110 1.1 sekiya
111 1.1 sekiya static const struct wsdisplay_emulops grtwo_textops = {
112 1.1 sekiya .cursor = grtwo_cursor,
113 1.1 sekiya .mapchar = grtwo_mapchar,
114 1.1 sekiya .putchar = grtwo_putchar,
115 1.1 sekiya .copycols = grtwo_copycols,
116 1.1 sekiya .erasecols = grtwo_erasecols,
117 1.1 sekiya .copyrows = grtwo_copyrows,
118 1.1 sekiya .eraserows = grtwo_eraserows,
119 1.1 sekiya .allocattr = grtwo_allocattr
120 1.1 sekiya };
121 1.1 sekiya
122 1.1 sekiya static const struct wsdisplay_accessops grtwo_accessops = {
123 1.1 sekiya .ioctl = grtwo_ioctl,
124 1.1 sekiya .mmap = grtwo_mmap,
125 1.1 sekiya .alloc_screen = grtwo_alloc_screen,
126 1.1 sekiya .free_screen = grtwo_free_screen,
127 1.1 sekiya .show_screen = grtwo_show_screen,
128 1.1 sekiya };
129 1.1 sekiya
130 1.1 sekiya static const struct wsscreen_descr grtwo_screen = {
131 1.1 sekiya .name = "1280x1024",
132 1.1 sekiya .ncols = 160,
133 1.1 sekiya .nrows = 64,
134 1.1 sekiya .textops = &grtwo_textops,
135 1.1 sekiya .fontwidth = 8,
136 1.1 sekiya .fontheight = 16,
137 1.1 sekiya .capabilities = WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_REVERSE
138 1.1 sekiya };
139 1.1 sekiya
140 1.1 sekiya static const struct wsscreen_descr *_grtwo_screenlist[] = {
141 1.1 sekiya &grtwo_screen
142 1.1 sekiya };
143 1.1 sekiya
144 1.1 sekiya static const struct wsscreen_list grtwo_screenlist = {
145 1.1 sekiya sizeof(_grtwo_screenlist) / sizeof(struct wsscreen_descr *),
146 1.1 sekiya _grtwo_screenlist
147 1.1 sekiya };
148 1.1 sekiya
149 1.1 sekiya static struct grtwo_devconfig grtwo_console_dc;
150 1.1 sekiya static int grtwo_is_console = 0;
151 1.1 sekiya
152 1.1 sekiya #define GR2_ATTR_ENCODE(fg,bg) (((fg) << 8) | (bg))
153 1.1 sekiya #define GR2_ATTR_BG(a) ((a) & 0xff)
154 1.1 sekiya #define GR2_ATTR_FG(a) (((a) >> 8) & 0xff)
155 1.1 sekiya
156 1.1 sekiya static const u_int16_t grtwo_cursor_data[128] = {
157 1.1 sekiya /* Bit 0 */
158 1.1 sekiya 0xff00, 0x0000,
159 1.1 sekiya 0xff00, 0x0000,
160 1.1 sekiya 0xff00, 0x0000,
161 1.1 sekiya 0xff00, 0x0000,
162 1.1 sekiya 0xff00, 0x0000,
163 1.1 sekiya 0xff00, 0x0000,
164 1.1 sekiya 0xff00, 0x0000,
165 1.1 sekiya 0xff00, 0x0000,
166 1.1 sekiya 0xff00, 0x0000,
167 1.1 sekiya 0xff00, 0x0000,
168 1.1 sekiya 0xff00, 0x0000,
169 1.1 sekiya 0xff00, 0x0000,
170 1.1 sekiya 0xff00, 0x0000,
171 1.1 sekiya 0xff00, 0x0000,
172 1.1 sekiya 0xff00, 0x0000,
173 1.1 sekiya 0xff00, 0x0000,
174 1.1 sekiya 0x0000, 0x0000,
175 1.1 sekiya 0x0000, 0x0000,
176 1.1 sekiya 0x0000, 0x0000,
177 1.1 sekiya 0x0000, 0x0000,
178 1.1 sekiya 0x0000, 0x0000,
179 1.1 sekiya 0x0000, 0x0000,
180 1.1 sekiya 0x0000, 0x0000,
181 1.1 sekiya 0x0000, 0x0000,
182 1.1 sekiya 0x0000, 0x0000,
183 1.1 sekiya 0x0000, 0x0000,
184 1.1 sekiya 0x0000, 0x0000,
185 1.1 sekiya 0x0000, 0x0000,
186 1.1 sekiya 0x0000, 0x0000,
187 1.1 sekiya 0x0000, 0x0000,
188 1.1 sekiya 0x0000, 0x0000,
189 1.1 sekiya 0x0000, 0x0000,
190 1.1 sekiya
191 1.1 sekiya /* Bit 1 */
192 1.1 sekiya 0x0000, 0x0000,
193 1.1 sekiya 0x0000, 0x0000,
194 1.1 sekiya 0x0000, 0x0000,
195 1.1 sekiya 0x0000, 0x0000,
196 1.1 sekiya 0x0000, 0x0000,
197 1.1 sekiya 0x0000, 0x0000,
198 1.1 sekiya 0x0000, 0x0000,
199 1.1 sekiya 0x0000, 0x0000,
200 1.1 sekiya 0x0000, 0x0000,
201 1.1 sekiya 0x0000, 0x0000,
202 1.1 sekiya 0x0000, 0x0000,
203 1.1 sekiya 0x0000, 0x0000,
204 1.1 sekiya 0x0000, 0x0000,
205 1.1 sekiya 0x0000, 0x0000,
206 1.1 sekiya 0x0000, 0x0000,
207 1.1 sekiya 0x0000, 0x0000,
208 1.1 sekiya 0x0000, 0x0000,
209 1.1 sekiya 0x0000, 0x0000,
210 1.1 sekiya 0x0000, 0x0000,
211 1.1 sekiya 0x0000, 0x0000,
212 1.1 sekiya 0x0000, 0x0000,
213 1.1 sekiya 0x0000, 0x0000,
214 1.1 sekiya 0x0000, 0x0000,
215 1.1 sekiya 0x0000, 0x0000,
216 1.1 sekiya 0x0000, 0x0000,
217 1.1 sekiya 0x0000, 0x0000,
218 1.1 sekiya 0x0000, 0x0000,
219 1.1 sekiya 0x0000, 0x0000,
220 1.1 sekiya 0x0000, 0x0000,
221 1.1 sekiya 0x0000, 0x0000,
222 1.1 sekiya 0x0000, 0x0000,
223 1.1 sekiya 0x0000, 0x0000,
224 1.1 sekiya };
225 1.1 sekiya
226 1.1 sekiya static const u_int8_t grtwo_defcmap[8 * 3] = {
227 1.1 sekiya /* Normal colors */
228 1.1 sekiya 0x00, 0x00, 0x00, /* black */
229 1.1 sekiya 0x7f, 0x00, 0x00, /* red */
230 1.1 sekiya 0x00, 0x7f, 0x00, /* green */
231 1.1 sekiya 0x7f, 0x7f, 0x00, /* brown */
232 1.1 sekiya 0x00, 0x00, 0x7f, /* blue */
233 1.1 sekiya 0x7f, 0x00, 0x7f, /* magenta */
234 1.1 sekiya 0x00, 0x7f, 0x7f, /* cyan */
235 1.1 sekiya 0xc7, 0xc7, 0xc7, /* white - XXX too dim? */
236 1.1 sekiya };
237 1.1 sekiya
238 1.1 sekiya static void
239 1.1 sekiya grtwo_wait_gfifo(struct grtwo_devconfig * dc)
240 1.1 sekiya {
241 1.1 sekiya int2_wait_fifo(1);
242 1.1 sekiya }
243 1.1 sekiya
244 1.1 sekiya /* Helper functions */
245 1.1 sekiya static void
246 1.1 sekiya grtwo_fill_rectangle(struct grtwo_devconfig * dc, int x1, int y1, int x2,
247 1.1 sekiya int y2, u_int8_t color)
248 1.1 sekiya {
249 1.1 sekiya /* gr2 sees coordinate 0,0 as the lower left corner of the screen */
250 1.1 sekiya y1 = dc->yres - y1;
251 1.1 sekiya y2 = dc->yres - y2;
252 1.1 sekiya
253 1.1 sekiya grtwo_wait_gfifo(dc);
254 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_COLOR, color);
255 1.1 sekiya grtwo_wait_gfifo(dc);
256 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_RECTI2D, x1);
257 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, y1);
258 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x2);
259 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, y2);
260 1.1 sekiya }
261 1.1 sekiya
262 1.1 sekiya static void
263 1.1 sekiya grtwo_copy_rectangle(struct grtwo_devconfig * dc, int x1, int y1, int x2,
264 1.1 sekiya int y2, int dx, int dy)
265 1.1 sekiya {
266 1.1 sekiya int length = (dx + 3) >> 2;
267 1.1 sekiya int lines = 4864 / length;
268 1.1 sekiya int from_y;
269 1.1 sekiya int to_y;
270 1.1 sekiya int height;
271 1.1 sekiya
272 1.1 sekiya y1 = dc->yres - y1 - dy;
273 1.1 sekiya y2 = dc->yres - y2 - dy;
274 1.1 sekiya
275 1.1 sekiya if ((y2 <= y1) || (dy < lines)) {
276 1.1 sekiya grtwo_wait_gfifo(dc);
277 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_RECTCOPY, length);
278 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, lines);
279 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x1);
280 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, y1);
281 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, dx);
282 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, dy);
283 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x2);
284 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, y2);
285 1.1 sekiya } else {
286 1.1 sekiya from_y = y1 + dy - lines;
287 1.1 sekiya to_y = y2 + dy - lines;
288 1.1 sekiya height = MIN(dy, lines);
289 1.1 sekiya
290 1.1 sekiya while (height) {
291 1.1 sekiya grtwo_wait_gfifo(dc);
292 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_RECTCOPY, length);
293 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, lines);
294 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x1);
295 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, from_y);
296 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, dx);
297 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, height);
298 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x2);
299 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, to_y);
300 1.1 sekiya dy -= height;
301 1.1 sekiya height = MIN(dy, lines);
302 1.1 sekiya from_y -= height;
303 1.1 sekiya to_y -= height;
304 1.1 sekiya }
305 1.1 sekiya }
306 1.1 sekiya }
307 1.1 sekiya
308 1.1 sekiya static void
309 1.1 sekiya grtwo_cmap_setrgb(struct grtwo_devconfig * dc, int index, u_int8_t r, u_int8_t g, u_int8_t b)
310 1.1 sekiya {
311 1.1 sekiya /* index += 0x1000; */
312 1.1 sekiya
313 1.1 sekiya grtwo_wait_gfifo(dc);
314 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, XMAPALL_ADDRHI,
315 1.1 sekiya (index & 0x1f00) >> 8);
316 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, XMAPALL_ADDRLO,
317 1.1 sekiya (index & 0xff));
318 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, XMAPALL_CLUT, r);
319 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, XMAPALL_CLUT, g);
320 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, XMAPALL_CLUT, b);
321 1.1 sekiya }
322 1.1 sekiya
323 1.1 sekiya static void
324 1.1 sekiya grtwo_setup_hw(struct grtwo_devconfig * dc)
325 1.1 sekiya {
326 1.1 sekiya int i = 0;
327 1.1 sekiya
328 1.1 sekiya /* Get various revisions */
329 1.1 sekiya dc->boardrev = (~(bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD0))) & GR2_REVISION_RD0_VERSION_MASK;
330 1.1 sekiya
331 1.1 sekiya /*
332 1.1 sekiya * boards prior to rev 4 have a pretty whacky config scheme.
333 1.1 sekiya * what is doubly weird is that i have a rev 2 board, but the rev 4
334 1.1 sekiya * probe routines work just fine.
335 1.1 sekiya * we'll trust SGI, though, and separate things a bit. it's only
336 1.1 sekiya * critical for the display depth calculation.
337 1.1 sekiya */
338 1.1 sekiya
339 1.1 sekiya if (dc->boardrev < 4) {
340 1.1 sekiya dc->backendrev = ~(bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD2) & GR2_REVISION_RD2_BACKEND_REV) >> 2;
341 1.1 sekiya if (dc->backendrev == 0)
342 1.1 sekiya return;
343 1.1 sekiya dc->zbuffer = !(bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1) & GR2_REVISION_RD1_ZBUFFER);
344 1.1 sekiya if ( (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD3) & GR2_REVISION_RD3_VMA) != 3)
345 1.1 sekiya i++;
346 1.1 sekiya if ( (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD3) & GR2_REVISION_RD3_VMB) != 0x0c)
347 1.1 sekiya i++;
348 1.1 sekiya if ( (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD3) & GR2_REVISION_RD3_VMC) != 0x30)
349 1.1 sekiya i++;
350 1.1 sekiya dc->depth = 8 * i;
351 1.1 sekiya dc->monitor =
352 1.1 sekiya ((bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD2) & 0x03) << 1) |
353 1.1 sekiya (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1) & 0x01);
354 1.1 sekiya } else {
355 1.1 sekiya dc->backendrev = ~(bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1)) & 0x03;
356 1.1 sekiya if (dc->backendrev == 0)
357 1.1 sekiya return;
358 1.1 sekiya dc->zbuffer = bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1) & GR2_REVISION4_RD1_ZBUFFER;
359 1.1 sekiya dc->depth = ((bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1) & GR2_REVISION4_RD1_24BPP) >> 4) ? 24 : 8;
360 1.1 sekiya dc->monitor = (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD0) & GR2_REVISION4_RD0_MONITOR_MASK) >> 4;
361 1.1 sekiya }
362 1.1 sekiya
363 1.1 sekiya dc->hq2rev = (bus_space_read_4(dc->iot, dc->ioh, HQ2_VERSION) & HQ2_VERSION_MASK) >> HQ2_VERSION_SHIFT;
364 1.1 sekiya dc->ge7rev = (bus_space_read_4(dc->iot, dc->ioh, GE7_REVISION) & GE7_REVISION_MASK) >> 5;
365 1.1 sekiya /* dc->vc1rev = vc1_read_ireg(dc, 5) & 0x07; */
366 1.1 sekiya
367 1.1 sekiya /* gr2 supports 1280x1024 only */
368 1.1 sekiya dc->xres = 1280;
369 1.1 sekiya dc->yres = 1024;
370 1.1 sekiya
371 1.1 sekiya #if 0
372 1.1 sekiya /* Setup cursor glyph */
373 1.1 sekiya
374 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRHI,
375 1.1 sekiya (VC1_SRAM_CURSOR0_BASE >> 8) & 0xff);
376 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRLO,
377 1.1 sekiya VC1_SRAM_CURSOR0_BASE & 0xff);
378 1.1 sekiya for (i = 0; i < 128; i++)
379 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, VC1_SRAM, grtwo_cursor_data[i]);
380 1.1 sekiya
381 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRHI,
382 1.1 sekiya (VC1_CURSOR_EP >> 8) & 0xff);
383 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRLO,
384 1.1 sekiya VC1_CURSOR_EP & 0xff);
385 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, VC1_SRAM_CURSOR0_BASE);
386 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, 0);
387 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, 0);
388 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, 0);
389 1.1 sekiya
390 1.1 sekiya /* Turn on cursor function, display, DID */
391 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, VC1_SYSCTL,
392 1.1 sekiya VC1_SYSCTL_VC1 | VC1_SYSCTL_DID |
393 1.1 sekiya VC1_SYSCTL_CURSOR | VC1_SYSCTL_CURSOR_DISPLAY);
394 1.1 sekiya #endif
395 1.1 sekiya
396 1.1 sekiya /* Setup CMAP */
397 1.1 sekiya for (i = 0; i < 8; i++)
398 1.1 sekiya grtwo_cmap_setrgb(dc, i, grtwo_defcmap[i * 3],
399 1.1 sekiya grtwo_defcmap[i * 3 + 1], grtwo_defcmap[i * 3 + 2]);
400 1.1 sekiya }
401 1.1 sekiya
402 1.1 sekiya /* Attach routines */
403 1.1 sekiya static int
404 1.1 sekiya grtwo_match(struct device * parent, struct cfdata * self, void *aux)
405 1.1 sekiya {
406 1.1 sekiya struct gio_attach_args *ga = aux;
407 1.1 sekiya
408 1.1 sekiya /*
409 1.1 sekiya * grtwo doesn't have anything that even vaguely resembles a product
410 1.1 sekiya * ID. Instead, we determine presence by looking at the HQ2 "mystery"
411 1.1 sekiya * register, which contains a magic number.
412 1.1 sekiya */
413 1.1 sekiya if ( badaddr((void *) (ga->ga_ioh + HQ2_MYSTERY), sizeof(u_int32_t)) )
414 1.1 sekiya return 0;
415 1.1 sekiya
416 1.1 sekiya if ( (bus_space_read_4(ga->ga_iot, ga->ga_ioh, HQ2_MYSTERY)) != 0xdeadbeef)
417 1.1 sekiya return 0;
418 1.1 sekiya
419 1.1 sekiya return 1;
420 1.1 sekiya }
421 1.1 sekiya
422 1.1 sekiya static void
423 1.1 sekiya grtwo_attach_common(struct grtwo_devconfig * dc, struct gio_attach_args * ga)
424 1.1 sekiya {
425 1.1 sekiya dc->dc_addr = ga->ga_addr;
426 1.1 sekiya
427 1.1 sekiya dc->iot = ga->ga_iot;
428 1.1 sekiya dc->ioh = ga->ga_ioh;
429 1.1 sekiya
430 1.1 sekiya wsfont_init();
431 1.1 sekiya
432 1.1 sekiya dc->dc_font = wsfont_find(NULL, 8, 16, 0, WSDISPLAY_FONTORDER_L2R,
433 1.1 sekiya WSDISPLAY_FONTORDER_L2R);
434 1.1 sekiya
435 1.1 sekiya if (dc->dc_font < 0)
436 1.1 sekiya panic("grtwo_attach_common: no suitable fonts");
437 1.1 sekiya
438 1.1 sekiya if (wsfont_lock(dc->dc_font, &dc->dc_fontdata))
439 1.1 sekiya panic("grtwo_attach_common: unable to lock font data");
440 1.1 sekiya
441 1.1 sekiya grtwo_setup_hw(dc);
442 1.1 sekiya
443 1.1 sekiya grtwo_fill_rectangle(dc, 0, 0, dc->xres, dc->yres, 0);
444 1.1 sekiya }
445 1.1 sekiya
446 1.1 sekiya static void
447 1.1 sekiya grtwo_attach(struct device * parent, struct device * self, void *aux)
448 1.1 sekiya {
449 1.1 sekiya struct gio_attach_args *ga = aux;
450 1.1 sekiya struct grtwo_softc *sc = (void *) self;
451 1.1 sekiya struct wsemuldisplaydev_attach_args wa;
452 1.1 sekiya
453 1.1 sekiya if (grtwo_is_console && ga->ga_addr == grtwo_console_dc.dc_addr) {
454 1.1 sekiya wa.console = 1;
455 1.1 sekiya sc->sc_dc = &grtwo_console_dc;
456 1.1 sekiya } else {
457 1.1 sekiya wa.console = 0;
458 1.1 sekiya sc->sc_dc = malloc(sizeof(struct grtwo_devconfig),
459 1.1 sekiya M_DEVBUF, M_WAITOK | M_ZERO);
460 1.1 sekiya if (sc->sc_dc == NULL)
461 1.1 sekiya panic("grtwo_attach: out of memory");
462 1.1 sekiya
463 1.1 sekiya grtwo_attach_common(sc->sc_dc, ga);
464 1.1 sekiya }
465 1.1 sekiya
466 1.1 sekiya aprint_naive(": Display adapter\n");
467 1.1 sekiya
468 1.1 sekiya aprint_normal(": SGI GR2 (board rev %x, monitor %d, depth %d)\n",
469 1.1 sekiya sc->sc_dc->boardrev, sc->sc_dc->monitor, sc->sc_dc->depth);
470 1.1 sekiya
471 1.1 sekiya wa.scrdata = &grtwo_screenlist;
472 1.1 sekiya wa.accessops = &grtwo_accessops;
473 1.1 sekiya wa.accesscookie = sc->sc_dc;
474 1.1 sekiya
475 1.1 sekiya config_found(&sc->sc_dev, &wa, wsemuldisplaydevprint);
476 1.1 sekiya }
477 1.1 sekiya
478 1.1 sekiya int
479 1.1 sekiya grtwo_cnattach(struct gio_attach_args * ga)
480 1.1 sekiya {
481 1.1 sekiya long defattr = GR2_ATTR_ENCODE(WSCOL_WHITE, WSCOL_BLACK);
482 1.1 sekiya const struct wsscreen_descr *screen;
483 1.1 sekiya
484 1.1 sekiya if (!grtwo_match(NULL, NULL, ga)) {
485 1.1 sekiya return ENXIO;
486 1.1 sekiya }
487 1.1 sekiya
488 1.1 sekiya grtwo_attach_common(&grtwo_console_dc, ga);
489 1.1 sekiya
490 1.1 sekiya screen = &grtwo_screen;
491 1.1 sekiya
492 1.1 sekiya wsdisplay_cnattach(screen, &grtwo_console_dc, 0, 0, defattr);
493 1.1 sekiya
494 1.1 sekiya grtwo_is_console = 1;
495 1.1 sekiya
496 1.1 sekiya return 0;
497 1.1 sekiya }
498 1.1 sekiya
499 1.1 sekiya /* wsdisplay textops */
500 1.1 sekiya static void
501 1.1 sekiya grtwo_cursor(void *c, int on, int row, int col)
502 1.1 sekiya {
503 1.1 sekiya struct grtwo_devconfig *dc = (void *) c;
504 1.1 sekiya u_int32_t control;
505 1.1 sekiya control = bus_space_read_4(dc->iot, dc->ioh, VC1_SYSCTL);
506 1.1 sekiya
507 1.1 sekiya if (!on) {
508 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, VC1_SYSCTL,
509 1.1 sekiya control & ~VC1_SYSCTL_CURSOR_DISPLAY);
510 1.1 sekiya } else {
511 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRHI, (VC1_CURSOR_XL & 0xff00) >> 8
512 1.1 sekiya );
513 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRLO, VC1_CURSOR_XL & 0xff);
514 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND,
515 1.1 sekiya col * dc->dc_fontdata->fontwidth);
516 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND,
517 1.1 sekiya row * dc->dc_fontdata->fontheight);
518 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, VC1_SYSCTL,
519 1.1 sekiya control | VC1_SYSCTL_CURSOR_DISPLAY);
520 1.1 sekiya }
521 1.1 sekiya }
522 1.1 sekiya
523 1.1 sekiya static int
524 1.1 sekiya grtwo_mapchar(void *c, int ch, unsigned int *cp)
525 1.1 sekiya {
526 1.1 sekiya struct grtwo_devconfig *dc = (void *) c;
527 1.1 sekiya
528 1.1 sekiya if (dc->dc_fontdata->encoding != WSDISPLAY_FONTENC_ISO) {
529 1.1 sekiya ch = wsfont_map_unichar(dc->dc_fontdata, ch);
530 1.1 sekiya
531 1.1 sekiya if (ch < 0)
532 1.1 sekiya goto fail;
533 1.1 sekiya }
534 1.1 sekiya if (ch < dc->dc_fontdata->firstchar ||
535 1.1 sekiya ch >= dc->dc_fontdata->firstchar + dc->dc_fontdata->numchars)
536 1.1 sekiya goto fail;
537 1.1 sekiya
538 1.1 sekiya *cp = ch;
539 1.1 sekiya return 5;
540 1.1 sekiya
541 1.1 sekiya fail:
542 1.1 sekiya *cp = ' ';
543 1.1 sekiya return 0;
544 1.1 sekiya }
545 1.1 sekiya
546 1.1 sekiya static void
547 1.1 sekiya grtwo_putchar(void *c, int row, int col, u_int ch, long attr)
548 1.1 sekiya {
549 1.1 sekiya struct grtwo_devconfig *dc = (void *) c;
550 1.1 sekiya struct wsdisplay_font *font = dc->dc_fontdata;
551 1.1 sekiya u_int8_t *bitmap = (u_int8_t *) font->data + (ch - font->firstchar) * font->fontheight * font->stride;
552 1.1 sekiya u_int32_t pattern;
553 1.1 sekiya int i;
554 1.1 sekiya int x = col * font->fontwidth;
555 1.1 sekiya int y = dc->yres - ( (row + 1) * font->fontheight);
556 1.1 sekiya
557 1.1 sekiya /* Set the drawing color */
558 1.1 sekiya grtwo_wait_gfifo(dc);
559 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_COLOR, attr);
560 1.1 sekiya
561 1.1 sekiya /* Set drawing coordinates */
562 1.1 sekiya grtwo_wait_gfifo(dc);
563 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_CMOV2I, x);
564 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, y);
565 1.1 sekiya
566 1.1 sekiya grtwo_wait_gfifo(dc);
567 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DRAWCHAR, font->fontwidth);
568 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, font->fontheight);
569 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 1);
570 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0); /* x offset */
571 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0); /* y offset */
572 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0);
573 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0);
574 1.1 sekiya
575 1.1 sekiya for (i = 0; i < font->fontheight; i++) {
576 1.1 sekiya /* It appears that writes have to be 16 bits. An "I tell you
577 1.1 sekiya two times" sort of thing? Thanks, SGI */
578 1.1 sekiya pattern = *bitmap | (*bitmap << 8);
579 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, pattern);
580 1.1 sekiya bitmap += font->stride;
581 1.1 sekiya }
582 1.1 sekiya
583 1.1 sekiya /* pad up to 18 */
584 1.1 sekiya for (i = font->fontheight; i < 18; i++)
585 1.1 sekiya bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0x0000);
586 1.1 sekiya }
587 1.1 sekiya
588 1.1 sekiya static void
589 1.1 sekiya grtwo_copycols(void *c, int row, int srccol, int dstcol, int ncols)
590 1.1 sekiya {
591 1.1 sekiya struct grtwo_devconfig *dc = (void *) c;
592 1.1 sekiya struct wsdisplay_font *font = dc->dc_fontdata;
593 1.1 sekiya
594 1.1 sekiya grtwo_copy_rectangle(dc,
595 1.1 sekiya srccol * font->fontwidth, /* x1 */
596 1.1 sekiya row * font->fontheight, /* y1 */
597 1.1 sekiya (srccol + ncols + 1) * font->fontwidth - 1, /* x2 */
598 1.1 sekiya (row + 1) * font->fontheight - 1, /* y2 */
599 1.1 sekiya dstcol * font->fontheight, /* dx */
600 1.1 sekiya row * font->fontheight); /* dy */
601 1.1 sekiya }
602 1.1 sekiya
603 1.1 sekiya static void
604 1.1 sekiya grtwo_erasecols(void *c, int row, int startcol, int ncols, long attr)
605 1.1 sekiya {
606 1.1 sekiya struct grtwo_devconfig *dc = (void *) c;
607 1.1 sekiya struct wsdisplay_font *font = dc->dc_fontdata;
608 1.1 sekiya
609 1.1 sekiya grtwo_fill_rectangle(dc,
610 1.1 sekiya startcol * font->fontwidth, /* x1 */
611 1.1 sekiya row * font->fontheight, /* y1 */
612 1.1 sekiya (startcol + ncols + 1) * font->fontwidth - 1, /* x2 */
613 1.1 sekiya (row + 1) * font->fontheight - 1, /* y2 */
614 1.1 sekiya GR2_ATTR_BG(attr));
615 1.1 sekiya }
616 1.1 sekiya
617 1.1 sekiya static void
618 1.1 sekiya grtwo_copyrows(void *c, int srcrow, int dstrow, int nrows)
619 1.1 sekiya {
620 1.1 sekiya struct grtwo_devconfig *dc = (void *) c;
621 1.1 sekiya struct wsdisplay_font *font = dc->dc_fontdata;
622 1.1 sekiya
623 1.1 sekiya grtwo_copy_rectangle(dc,
624 1.1 sekiya 0, /* x1 */
625 1.1 sekiya srcrow * font->fontheight, /* y1 */
626 1.1 sekiya dc->xres, /* x2 */
627 1.1 sekiya (srcrow + nrows + 1) * font->fontheight - 1, /* y2 */
628 1.1 sekiya 0, /* dx */
629 1.1 sekiya dstrow * font->fontheight); /* dy */
630 1.1 sekiya }
631 1.1 sekiya
632 1.1 sekiya static void
633 1.1 sekiya grtwo_eraserows(void *c, int startrow, int nrows, long attr)
634 1.1 sekiya {
635 1.1 sekiya struct grtwo_devconfig *dc = (void *) c;
636 1.1 sekiya struct wsdisplay_font *font = dc->dc_fontdata;
637 1.1 sekiya
638 1.1 sekiya grtwo_fill_rectangle(dc,
639 1.1 sekiya 0, /* x1 */
640 1.1 sekiya startrow * font->fontheight, /* y1 */
641 1.1 sekiya dc->xres, /* x2 */
642 1.1 sekiya (startrow + nrows + 1) * font->fontheight - 1, /* y2 */
643 1.1 sekiya GR2_ATTR_BG(attr));
644 1.1 sekiya }
645 1.1 sekiya
646 1.1 sekiya static int
647 1.1 sekiya grtwo_allocattr(void *c, int fg, int bg, int flags, long *attr)
648 1.1 sekiya {
649 1.1 sekiya if (flags & WSATTR_BLINK)
650 1.1 sekiya return EINVAL;
651 1.1 sekiya
652 1.1 sekiya if ((flags & WSATTR_WSCOLORS) == 0) {
653 1.1 sekiya fg = WSCOL_WHITE;
654 1.1 sekiya bg = WSCOL_BLACK;
655 1.1 sekiya }
656 1.1 sekiya if (flags & WSATTR_HILIT)
657 1.1 sekiya fg += 8;
658 1.1 sekiya
659 1.1 sekiya if (flags & WSATTR_REVERSE) {
660 1.1 sekiya int tmp = fg;
661 1.1 sekiya fg = bg;
662 1.1 sekiya bg = tmp;
663 1.1 sekiya }
664 1.1 sekiya *attr = GR2_ATTR_ENCODE(fg, bg);
665 1.1 sekiya
666 1.1 sekiya return 0;
667 1.1 sekiya }
668 1.1 sekiya
669 1.1 sekiya /* wsdisplay accessops */
670 1.1 sekiya
671 1.1 sekiya static int
672 1.1 sekiya grtwo_ioctl(void *c, u_long cmd, caddr_t data, int flag, struct proc * p)
673 1.1 sekiya {
674 1.1 sekiya struct grtwo_softc *sc = c;
675 1.1 sekiya
676 1.1 sekiya #define FBINFO (*(struct wsdisplay_fbinfo*)data)
677 1.1 sekiya
678 1.1 sekiya switch (cmd) {
679 1.1 sekiya case WSDISPLAYIO_GINFO:
680 1.1 sekiya FBINFO.width = sc->sc_dc->xres;
681 1.1 sekiya FBINFO.height = sc->sc_dc->yres;
682 1.1 sekiya FBINFO.depth = sc->sc_dc->depth;
683 1.1 sekiya FBINFO.cmsize = 1 << FBINFO.depth;
684 1.1 sekiya return 0;
685 1.1 sekiya case WSDISPLAYIO_GTYPE:
686 1.1 sekiya *(u_int *) data = WSDISPLAY_TYPE_GR2;
687 1.1 sekiya return 0;
688 1.1 sekiya }
689 1.1 sekiya return EPASSTHROUGH;
690 1.1 sekiya }
691 1.1 sekiya
692 1.1 sekiya static paddr_t
693 1.1 sekiya grtwo_mmap(void *c, off_t offset, int prot)
694 1.1 sekiya {
695 1.1 sekiya struct grtwo_devconfig *dc = c;
696 1.1 sekiya
697 1.1 sekiya if (offset >= 0xfffff)
698 1.1 sekiya return -1;
699 1.1 sekiya
700 1.1 sekiya return mips_btop(dc->dc_addr + offset);
701 1.1 sekiya }
702 1.1 sekiya
703 1.1 sekiya static int
704 1.1 sekiya grtwo_alloc_screen(void *c, const struct wsscreen_descr * type, void **cookiep,
705 1.1 sekiya int *cursxp, int *cursyp, long *attrp)
706 1.1 sekiya {
707 1.1 sekiya /*
708 1.1 sekiya * This won't get called for console screen and we don't support
709 1.1 sekiya * virtual screens
710 1.1 sekiya */
711 1.1 sekiya
712 1.1 sekiya return ENOMEM;
713 1.1 sekiya }
714 1.1 sekiya
715 1.1 sekiya static void
716 1.1 sekiya grtwo_free_screen(void *c, void *cookie)
717 1.1 sekiya {
718 1.1 sekiya panic("grtwo_free_screen");
719 1.1 sekiya }
720 1.1 sekiya static int
721 1.1 sekiya grtwo_show_screen(void *c, void *cookie, int waitok,
722 1.1 sekiya void (*cb) (void *, int, int), void *cbarg)
723 1.1 sekiya {
724 1.1 sekiya return 0;
725 1.1 sekiya }
726