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