grtwo.c revision 1.8 1 /* $NetBSD: grtwo.c,v 1.8 2006/12/28 22:10:05 rumble 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.8 2006/12/28 22:10:05 rumble 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 <dev/wscons/wsconsio.h>
46 #include <dev/wscons/wsdisplayvar.h>
47 #include <dev/wsfont/wsfont.h>
48
49 #include <sgimips/gio/giovar.h>
50 #include <sgimips/gio/grtwovar.h>
51 #include <sgimips/gio/grtworeg.h>
52
53 #include <sgimips/dev/int2var.h>
54
55 struct grtwo_softc {
56 struct device sc_dev;
57
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(struct device *, struct cfdata *, void *);
86 static void grtwo_attach(struct device *, struct device *, void *);
87
88 CFATTACH_DECL(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, caddr_t, 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 static const u_int16_t grtwo_cursor_data[128] = {
160 /* Bit 0 */
161 0xff00, 0x0000,
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 0x0000, 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
194 /* Bit 1 */
195 0x0000, 0x0000,
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 };
228
229 static const u_int8_t grtwo_defcmap[8 * 3] = {
230 /* Normal colors */
231 0x00, 0x00, 0x00, /* black */
232 0x7f, 0x00, 0x00, /* red */
233 0x00, 0x7f, 0x00, /* green */
234 0x7f, 0x7f, 0x00, /* brown */
235 0x00, 0x00, 0x7f, /* blue */
236 0x7f, 0x00, 0x7f, /* magenta */
237 0x00, 0x7f, 0x7f, /* cyan */
238 0xc7, 0xc7, 0xc7, /* white - XXX too dim? */
239 };
240
241 static void
242 grtwo_wait_gfifo(struct grtwo_devconfig * dc)
243 {
244 int2_wait_fifo(1);
245 }
246
247 static inline void
248 grtwo_set_color(bus_space_tag_t iot, bus_space_handle_t ioh, int color)
249 {
250 bus_space_write_4(iot, ioh, GR2_FIFO_COLOR, color);
251 }
252
253 /* Helper functions */
254 static void
255 grtwo_fill_rectangle(struct grtwo_devconfig * dc, int x1, int y1, int x2,
256 int y2, u_int8_t color)
257 {
258 int remaining;
259 int from_y;
260 int to_y;
261
262 /* gr2 sees coordinate 0,0 as the lower left corner, and 1279,1023
263 as the upper right. To keep things consistent, we shall flip the
264 y axis. */
265
266 /* There appears to be a limit to the number of vertical lines that we
267 can run through the the graphics engine at one go. This probably has
268 something to do with vertical refresh. Single-row fills are okay,
269 multiple-row screw up the board in exciting ways. The copy_rectangle
270 workaround doesn't work for fills. */
271
272 /* Coordinates, not length. Remember that! */
273
274 to_y = min(dc->yres - 1 - y1, dc->yres - 1 - y2);
275 from_y = max(dc->yres - 1 - y1, dc->yres - 1 - y2);
276
277 remaining = to_y - from_y;
278
279 grtwo_wait_gfifo(dc);
280 grtwo_set_color(dc->iot, dc->ioh, color);
281
282 while (remaining) {
283 if (remaining <= 32)
284 {
285 delay(10000);
286 grtwo_wait_gfifo(dc);
287 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_RECTI2D, x1);
288 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, from_y);
289 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x2);
290 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, from_y + remaining);
291 break;
292 } else {
293 delay(100000);
294 grtwo_wait_gfifo(dc);
295 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_RECTI2D, x1);
296 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, from_y);
297 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x2);
298 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, from_y + remaining);
299 from_y += 32;
300 remaining -=32;
301 }
302 }
303 }
304
305 static void
306 grtwo_copy_rectangle(struct grtwo_devconfig * dc, int x1, int y1, int x2,
307 int y2, int width, int height)
308 {
309 int length = (width + 3) >> 2;
310 int lines = 4864 / length;
311 int from_y;
312 int to_y;
313 int temp_height;
314
315 if ((y2 <= y1) || (height < lines)) {
316 grtwo_wait_gfifo(dc);
317 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_RECTCOPY, length);
318 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, lines);
319 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x1);
320 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, y1);
321 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, width);
322 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, height);
323 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x2);
324 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, y2);
325 } else {
326 from_y = y1 + height - lines;
327 to_y = y2 + height - lines;
328 temp_height = MIN(height, lines);
329
330 while (temp_height) {
331 grtwo_wait_gfifo(dc);
332 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_RECTCOPY, length);
333 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, lines);
334 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x1);
335 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, from_y);
336 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, width);
337 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, temp_height);
338 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x2);
339 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, to_y);
340 height -= temp_height;
341 height = MIN(height, lines);
342 from_y -= temp_height;
343 to_y -= temp_height;
344 }
345 }
346 }
347
348 static void
349 grtwo_cmap_setrgb(struct grtwo_devconfig * dc, int index, u_int8_t r, u_int8_t g, u_int8_t b)
350 {
351 grtwo_wait_gfifo(dc);
352 bus_space_write_1(dc->iot, dc->ioh, XMAPALL_ADDRHI,
353 ((index & 0x1f00) >> 8) );
354 bus_space_write_1(dc->iot, dc->ioh, XMAPALL_ADDRLO,
355 (index & 0xff));
356 bus_space_write_1(dc->iot, dc->ioh, XMAPALL_CLUT, r);
357 bus_space_write_1(dc->iot, dc->ioh, XMAPALL_CLUT, g);
358 bus_space_write_1(dc->iot, dc->ioh, XMAPALL_CLUT, b);
359 }
360
361 static void
362 grtwo_setup_hw(struct grtwo_devconfig * dc)
363 {
364 int i = 0;
365
366 /* Get various revisions */
367 dc->boardrev = (~(bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD0))) & GR2_REVISION_RD0_VERSION_MASK;
368
369 /*
370 * boards prior to rev 4 have a pretty whacky config scheme.
371 * what is doubly weird is that i have a rev 2 board, but the rev 4
372 * probe routines work just fine.
373 * we'll trust SGI, though, and separate things a bit. it's only
374 * critical for the display depth calculation.
375 */
376
377 if (dc->boardrev < 4) {
378 dc->backendrev = ~(bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD2) & GR2_REVISION_RD2_BACKEND_REV) >> 2;
379 if (dc->backendrev == 0)
380 return;
381 dc->zbuffer = !(bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1) & GR2_REVISION_RD1_ZBUFFER);
382 if ( (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD3) & GR2_REVISION_RD3_VMA) != 3)
383 i++;
384 if ( (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD3) & GR2_REVISION_RD3_VMB) != 0x0c)
385 i++;
386 if ( (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD3) & GR2_REVISION_RD3_VMC) != 0x30)
387 i++;
388 dc->depth = 8 * i;
389 dc->monitor =
390 ((bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD2) & 0x03) << 1) |
391 (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1) & 0x01);
392 } else {
393 dc->backendrev = ~(bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1)) & 0x03;
394 if (dc->backendrev == 0)
395 return;
396 dc->zbuffer = bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1) & GR2_REVISION4_RD1_ZBUFFER;
397 dc->depth = ((bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1) & GR2_REVISION4_RD1_24BPP) >> 4) ? 24 : 8;
398 dc->monitor = (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD0) & GR2_REVISION4_RD0_MONITOR_MASK) >> 4;
399 }
400
401 dc->hq2rev = (bus_space_read_4(dc->iot, dc->ioh, HQ2_VERSION) & HQ2_VERSION_MASK) >> HQ2_VERSION_SHIFT;
402 dc->ge7rev = (bus_space_read_4(dc->iot, dc->ioh, GE7_REVISION) & GE7_REVISION_MASK) >> 5;
403 /* dc->vc1rev = vc1_read_ireg(dc, 5) & 0x07; */
404
405 /* gr2 supports 1280x1024 only */
406 dc->xres = 1280;
407 dc->yres = 1024;
408
409 #if 0
410 /* Setup cursor glyph */
411
412 bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRHI,
413 (VC1_SRAM_CURSOR0_BASE >> 8) & 0xff);
414 bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRLO,
415 VC1_SRAM_CURSOR0_BASE & 0xff);
416 for (i = 0; i < 128; i++)
417 bus_space_write_4(dc->iot, dc->ioh, VC1_SRAM, grtwo_cursor_data[i]);
418
419 bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRHI,
420 (VC1_CURSOR_EP >> 8) & 0xff);
421 bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRLO,
422 VC1_CURSOR_EP & 0xff);
423 bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, VC1_SRAM_CURSOR0_BASE);
424 bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, 0);
425 bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, 0);
426 bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, 0);
427
428 /* Turn on cursor function, display, DID */
429 bus_space_write_4(dc->iot, dc->ioh, VC1_SYSCTL,
430 VC1_SYSCTL_VC1 | VC1_SYSCTL_DID |
431 VC1_SYSCTL_CURSOR | VC1_SYSCTL_CURSOR_DISPLAY);
432 #endif
433
434 /* Setup CMAP */
435 for (i = 0; i < 8; i++)
436 grtwo_cmap_setrgb(dc, i, grtwo_defcmap[i * 3],
437 grtwo_defcmap[i * 3 + 1], grtwo_defcmap[i * 3 + 2]);
438 }
439
440 /* Attach routines */
441 static int
442 grtwo_match(struct device * parent, struct cfdata * self, void *aux)
443 {
444 struct gio_attach_args *ga = aux;
445
446 if (ga->ga_addr != 0x1f000000 && ga->ga_addr != 0x1f400000 &&
447 ga->ga_addr != 0x1f600000)
448 return (0);
449
450 /*
451 * grtwo doesn't have anything that even vaguely resembles a product
452 * ID. Instead, we determine presence by looking at the HQ2 "mystery"
453 * register, which contains a magic number.
454 */
455 if ( badaddr((void *) (ga->ga_ioh + HQ2_MYSTERY), sizeof(u_int32_t)) )
456 return 0;
457
458 if ( (bus_space_read_4(ga->ga_iot, ga->ga_ioh, HQ2_MYSTERY)) != 0xdeadbeef)
459 return 0;
460
461 return 1;
462 }
463
464 static void
465 grtwo_attach_common(struct grtwo_devconfig * dc, struct gio_attach_args * ga)
466 {
467 dc->dc_addr = ga->ga_addr;
468
469 dc->iot = ga->ga_iot;
470 dc->ioh = ga->ga_ioh;
471 int i = 0;
472
473 wsfont_init();
474
475 dc->dc_font = wsfont_find(NULL, 8, 16, 0, WSDISPLAY_FONTORDER_L2R,
476 WSDISPLAY_FONTORDER_L2R);
477
478 if (dc->dc_font < 0)
479 panic("grtwo_attach_common: no suitable fonts");
480
481 if (wsfont_lock(dc->dc_font, &dc->dc_fontdata))
482 panic("grtwo_attach_common: unable to lock font data");
483
484 grtwo_setup_hw(dc);
485
486 /* Large fills are broken. For now, clear the screen line-by-line. */
487 for (i = 0; i < 64; i++)
488 grtwo_eraserows(dc, i, 1, 0);
489
490 /* If large fills worked, we'd do this instead:
491 grtwo_fill_rectangle(dc, 0, 0, dc->xres - 1, dc->yres - 1, 0);
492 */
493 }
494
495 static void
496 grtwo_attach(struct device * parent, struct device * self, void *aux)
497 {
498 struct gio_attach_args *ga = aux;
499 struct grtwo_softc *sc = (void *) self;
500 struct wsemuldisplaydev_attach_args wa;
501
502 if (grtwo_is_console && ga->ga_addr == grtwo_console_dc.dc_addr) {
503 wa.console = 1;
504 sc->sc_dc = &grtwo_console_dc;
505 } else {
506 wa.console = 0;
507 sc->sc_dc = malloc(sizeof(struct grtwo_devconfig),
508 M_DEVBUF, M_WAITOK | M_ZERO);
509 if (sc->sc_dc == NULL)
510 panic("grtwo_attach: out of memory");
511
512 grtwo_attach_common(sc->sc_dc, ga);
513 }
514
515 aprint_naive(": Display adapter\n");
516
517 aprint_normal(": GR2 (board rev %x, monitor %d, depth %d)\n",
518 sc->sc_dc->boardrev, sc->sc_dc->monitor, sc->sc_dc->depth);
519
520 wa.scrdata = &grtwo_screenlist;
521 wa.accessops = &grtwo_accessops;
522 wa.accesscookie = sc->sc_dc;
523
524 if ((cpu_intr_establish(0, IPL_TTY, grtwo_intr0, sc)) == NULL)
525 printf(": unable to establish interrupt!\n");
526
527 if ((cpu_intr_establish(6, IPL_TTY, grtwo_intr6, sc)) == NULL)
528 printf(": unable to establish interrupt!\n");
529
530 config_found(&sc->sc_dev, &wa, wsemuldisplaydevprint);
531 }
532
533 int
534 grtwo_cnattach(struct gio_attach_args * ga)
535 {
536 long defattr = GR2_ATTR_ENCODE(WSCOL_WHITE, WSCOL_BLACK);
537
538 if (!grtwo_match(NULL, NULL, ga)) {
539 return ENXIO;
540 }
541
542 grtwo_attach_common(&grtwo_console_dc, ga);
543 wsdisplay_cnattach(&grtwo_screen, &grtwo_console_dc, 0, 0, defattr);
544
545 grtwo_is_console = 1;
546
547 return 0;
548 }
549
550 /* wsdisplay textops */
551 static void
552 grtwo_cursor(void *c, int on, int row, int col)
553 {
554 struct grtwo_devconfig *dc = (void *) c;
555 u_int32_t control;
556 control = bus_space_read_4(dc->iot, dc->ioh, VC1_SYSCTL);
557
558 if (!on) {
559 bus_space_write_4(dc->iot, dc->ioh, VC1_SYSCTL,
560 control & ~VC1_SYSCTL_CURSOR_DISPLAY);
561 } else {
562 bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRHI, (VC1_CURSOR_XL & 0xff00) >> 8
563 );
564 bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRLO, VC1_CURSOR_XL & 0xff);
565 bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND,
566 col * dc->dc_fontdata->fontwidth);
567 bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND,
568 row * dc->dc_fontdata->fontheight);
569 bus_space_write_4(dc->iot, dc->ioh, VC1_SYSCTL,
570 control | VC1_SYSCTL_CURSOR_DISPLAY);
571 }
572 }
573
574 static int
575 grtwo_mapchar(void *c, int ch, unsigned int *cp)
576 {
577 struct grtwo_devconfig *dc = (void *) c;
578
579 if (dc->dc_fontdata->encoding != WSDISPLAY_FONTENC_ISO) {
580 ch = wsfont_map_unichar(dc->dc_fontdata, ch);
581
582 if (ch < 0)
583 goto fail;
584 }
585 if (ch < dc->dc_fontdata->firstchar ||
586 ch >= dc->dc_fontdata->firstchar + dc->dc_fontdata->numchars)
587 goto fail;
588
589 *cp = ch;
590 return 5;
591
592 fail:
593 *cp = ' ';
594 return 0;
595 }
596
597 static void
598 grtwo_putchar(void *c, int row, int col, u_int ch, long attr)
599 {
600 struct grtwo_devconfig *dc = (void *) c;
601 struct wsdisplay_font *font = dc->dc_fontdata;
602 u_int8_t *bitmap = (u_int8_t *) font->data + (ch - font->firstchar + 1) * font->fontheight * font->stride;
603 u_int32_t pattern;
604 int i;
605 int x = col * font->fontwidth;
606 int y = dc->yres - ( (row + 1) * font->fontheight);
607
608 /* Set the drawing color */
609 grtwo_wait_gfifo(dc);
610 grtwo_set_color(dc->iot, dc->ioh, (((attr) >> 8) & 0xff));
611 grtwo_wait_gfifo(dc);
612
613 /* Set drawing coordinates */
614 grtwo_wait_gfifo(dc);
615 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_CMOV2I, x);
616 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, y);
617
618 /* This works for font sizes < 18 */
619 grtwo_wait_gfifo(dc);
620 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DRAWCHAR, font->fontwidth);
621 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, font->fontheight);
622 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 2);
623 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0); /* x offset */
624 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0); /* y offset */
625 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0);
626 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0);
627
628 for (i = 0; i < font->fontheight; i++) {
629 /* It appears that writes have to be 16 bits. An "I tell you
630 two times" sort of thing? Thanks, SGI */
631 pattern = *bitmap | (*bitmap << 8);
632 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, pattern);
633 bitmap -= font->stride;
634 }
635
636 /* pad up to 18 */
637 for (i = font->fontheight; i < 18; i++)
638 bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0x0000);
639 }
640
641 static void
642 grtwo_copycols(void *c, int row, int srccol, int dstcol, int ncols)
643 {
644 #if 1
645 printf("grtwo_copycols: %i %i %i %i\n", row, srccol, dstcol, ncols);
646 #else
647 struct grtwo_devconfig *dc = (void *) c;
648 struct wsdisplay_font *font = dc->dc_fontdata;
649 grtwo_copy_rectangle(dc,
650 srccol * font->fontwidth, /* x1 */
651 0, /* y1 */
652 dstcol * font->fontwidth, /* x2 */
653 0, /* y2 */
654 ncols * font->fontwidth, /* dx */
655 dc->yres ); /* dy */
656 #endif
657 }
658
659 static void
660 grtwo_erasecols(void *c, int row, int startcol, int ncols, long attr)
661 {
662 struct grtwo_devconfig *dc = (void *) c;
663 struct wsdisplay_font *font = dc->dc_fontdata;
664
665 grtwo_fill_rectangle(dc,
666 startcol * font->fontwidth, /* x1 */
667 0, /* y1 */
668 (startcol * font->fontwidth) + ncols * font->fontwidth, /* x2 */
669 dc->yres, /* y2 */
670 GR2_ATTR_BG(attr));
671 }
672
673 static void
674 grtwo_copyrows(void *c, int srcrow, int dstrow, int nrows)
675 {
676 struct grtwo_devconfig *dc = (void *) c;
677 struct wsdisplay_font *font = dc->dc_fontdata;
678
679 grtwo_copy_rectangle(dc,
680 0, /* x1 */
681 srcrow * font->fontheight, /* y1 */
682 0, /* x2 */
683 dstrow * font->fontheight, /* y2 */
684 dc->xres, /* dx */
685 nrows * font->fontheight);
686 }
687
688 static void
689 grtwo_eraserows(void *c, int startrow, int nrows, long attr)
690 {
691 struct grtwo_devconfig *dc = (void *) c;
692 struct wsdisplay_font *font = dc->dc_fontdata;
693 grtwo_fill_rectangle(dc,
694 0, /* x1 */
695 startrow * font->fontheight, /* y1 */
696 dc->xres, /* x2 */
697 (startrow * font->fontheight) + nrows * font->fontheight, /* y2 */
698 GR2_ATTR_BG(attr));
699 }
700
701 static int
702 grtwo_allocattr(void *c, int fg, int bg, int flags, long *attr)
703 {
704 if (flags & WSATTR_BLINK)
705 return EINVAL;
706
707 if ((flags & WSATTR_WSCOLORS) == 0) {
708 fg = WSCOL_WHITE;
709 bg = WSCOL_BLACK;
710 }
711 if (flags & WSATTR_HILIT)
712 fg += 8;
713
714 if (flags & WSATTR_REVERSE) {
715 int tmp = fg;
716 fg = bg;
717 bg = tmp;
718 }
719 *attr = GR2_ATTR_ENCODE(fg, bg);
720
721 return 0;
722 }
723
724 /* wsdisplay accessops */
725
726 static int
727 grtwo_ioctl(void *c, void *vs, u_long cmd, caddr_t data, int flag,
728 struct lwp *l)
729 {
730 struct grtwo_softc *sc = c;
731
732 #define FBINFO (*(struct wsdisplay_fbinfo*)data)
733
734 switch (cmd) {
735 case WSDISPLAYIO_GINFO:
736 FBINFO.width = sc->sc_dc->xres;
737 FBINFO.height = sc->sc_dc->yres;
738 FBINFO.depth = sc->sc_dc->depth;
739 FBINFO.cmsize = 1 << FBINFO.depth;
740 return 0;
741 case WSDISPLAYIO_GTYPE:
742 *(u_int *) data = WSDISPLAY_TYPE_GR2;
743 return 0;
744 }
745 return EPASSTHROUGH;
746 }
747
748 static paddr_t
749 grtwo_mmap(void *c, void *vs, off_t offset, int prot)
750 {
751 struct grtwo_devconfig *dc = c;
752
753 if (offset >= 0xfffff)
754 return -1;
755
756 return mips_btop(dc->dc_addr + offset);
757 }
758
759 static int
760 grtwo_alloc_screen(void *c, const struct wsscreen_descr * type, void **cookiep,
761 int *cursxp, int *cursyp, long *attrp)
762 {
763 /*
764 * This won't get called for console screen and we don't support
765 * virtual screens
766 */
767
768 return ENOMEM;
769 }
770
771 static void
772 grtwo_free_screen(void *c, void *cookie)
773 {
774 panic("grtwo_free_screen");
775 }
776 static int
777 grtwo_show_screen(void *c, void *cookie, int waitok,
778 void (*cb) (void *, int, int), void *cbarg)
779 {
780 return 0;
781 }
782
783 static int
784 grtwo_intr0(void *arg)
785 {
786 /* struct grtwo_devconfig *dc = arg; */
787 return 1;
788 }
789
790
791 static int
792 grtwo_intr6(void *arg)
793 {
794 /* struct grtwo_devconfig *dc = arg; */
795 return 1;
796 }
797
798