newport.c revision 1.1 1 /* $NetBSD: newport.c,v 1.1 2003/12/15 05:24:51 lonewolf Exp $ */
2
3 /*
4 * Copyright (c) 2003 Ilpo Ruotsalainen
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 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: newport.c,v 1.1 2003/12/15 05:24:51 lonewolf Exp $");
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/device.h>
38 #include <sys/malloc.h>
39
40 #include <dev/wscons/wsconsio.h>
41 #include <dev/wscons/wsdisplayvar.h>
42 #include <dev/wsfont/wsfont.h>
43
44 #include <sgimips/gio/giovar.h>
45 #include <sgimips/gio/newportvar.h>
46 #include <sgimips/gio/newportreg.h>
47
48 struct newport_softc {
49 struct device sc_dev;
50
51 struct newport_devconfig *sc_dc;
52 };
53
54 struct newport_devconfig {
55 uint32_t dc_addr;
56
57 bus_space_tag_t dc_st;
58 bus_space_handle_t dc_sh;
59
60 int dc_boardrev;
61 int dc_xres;
62 int dc_yres;
63
64 int dc_screens;
65
66 int dc_font;
67 struct wsdisplay_font *dc_fontdata;
68 };
69
70 static int newport_match(struct device *, struct cfdata *, void *);
71 static void newport_attach(struct device *, struct device *, void *);
72
73 CFATTACH_DECL(newport, sizeof(struct newport_softc),
74 newport_match, newport_attach, NULL, NULL);
75
76 /* textops */
77 static void newport_cursor(void *, int, int, int);
78 static int newport_mapchar(void *, int, unsigned int *);
79 static void newport_putchar(void *, int, int, u_int, long);
80 static void newport_copycols(void *, int, int, int, int);
81 static void newport_erasecols(void *, int, int, int, long);
82 static void newport_copyrows(void *, int, int, int);
83 static void newport_eraserows(void *, int, int, long);
84 static int newport_allocattr(void *, int, int, int, long *);
85
86 /* accessops */
87 static int newport_ioctl(void *, u_long, caddr_t, int, struct proc *);
88 static paddr_t newport_mmap(void *, off_t, int);
89 static int newport_alloc_screen(void *, const struct wsscreen_descr *,
90 void **, int *, int *, long *);
91 static void newport_free_screen(void *, void *);
92 static int newport_show_screen(void *, void *, int,
93 void (*)(void *, int, int), void *);
94
95 static const struct wsdisplay_emulops newport_textops = {
96 .cursor = newport_cursor,
97 .mapchar = newport_mapchar,
98 .putchar = newport_putchar,
99 .copycols = newport_copycols,
100 .erasecols = newport_erasecols,
101 .copyrows = newport_copyrows,
102 .eraserows = newport_eraserows,
103 .allocattr = newport_allocattr
104 };
105
106 static const struct wsdisplay_accessops newport_accessops = {
107 .ioctl = newport_ioctl,
108 .mmap = newport_mmap,
109 .alloc_screen = newport_alloc_screen,
110 .free_screen = newport_free_screen,
111 .show_screen = newport_show_screen,
112 };
113
114 static const struct wsscreen_descr newport_screen_1024x768 = {
115 .name = "1024x768",
116 .ncols = 128,
117 .nrows = 48,
118 .textops = &newport_textops,
119 .fontwidth = 8,
120 .fontheight = 16,
121 .capabilities = WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_REVERSE
122 };
123
124 static const struct wsscreen_descr newport_screen_1280x1024 = {
125 .name = "1280x1024",
126 .ncols = 160,
127 .nrows = 64,
128 .textops = &newport_textops,
129 .fontwidth = 8,
130 .fontheight = 16,
131 .capabilities = WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_REVERSE
132 };
133
134 static const struct wsscreen_descr *_newport_screenlist[] = {
135 &newport_screen_1024x768,
136 &newport_screen_1280x1024
137 };
138
139 static const struct wsscreen_list newport_screenlist = {
140 sizeof(_newport_screenlist) / sizeof(struct wsscreen_descr *),
141 _newport_screenlist
142 };
143
144 static struct newport_devconfig newport_console_dc;
145 static int newport_is_console = 0;
146
147 #define NEWPORT_ATTR_ENCODE(fg,bg) (((fg) << 8) | (bg))
148 #define NEWPORT_ATTR_BG(a) ((a) & 0xff)
149 #define NEWPORT_ATTR_FG(a) (((a) >> 8) & 0xff)
150
151 static const uint16_t newport_cursor_data[128] = {
152 /* Bit 0 */
153 0xff00, 0x0000,
154 0xff00, 0x0000,
155 0xff00, 0x0000,
156 0xff00, 0x0000,
157 0xff00, 0x0000,
158 0xff00, 0x0000,
159 0xff00, 0x0000,
160 0xff00, 0x0000,
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 0x0000, 0x0000,
170 0x0000, 0x0000,
171 0x0000, 0x0000,
172 0x0000, 0x0000,
173 0x0000, 0x0000,
174 0x0000, 0x0000,
175 0x0000, 0x0000,
176 0x0000, 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
186 /* Bit 1 */
187 0x0000, 0x0000,
188 0x0000, 0x0000,
189 0x0000, 0x0000,
190 0x0000, 0x0000,
191 0x0000, 0x0000,
192 0x0000, 0x0000,
193 0x0000, 0x0000,
194 0x0000, 0x0000,
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 };
220
221 static const uint8_t newport_defcmap[16*3] = {
222 /* Normal colors */
223 0x00, 0x00, 0x00, /* black */
224 0x7f, 0x00, 0x00, /* red */
225 0x00, 0x7f, 0x00, /* green */
226 0x7f, 0x7f, 0x00, /* brown */
227 0x00, 0x00, 0x7f, /* blue */
228 0x7f, 0x00, 0x7f, /* magenta */
229 0x00, 0x7f, 0x7f, /* cyan */
230 0xc7, 0xc7, 0xc7, /* white - XXX too dim? */
231
232 /* Hilite colors */
233 0x7f, 0x7f, 0x7f, /* black */
234 0xff, 0x00, 0x00, /* red */
235 0x00, 0xff, 0x00, /* green */
236 0xff, 0xff, 0x00, /* brown */
237 0x00, 0x00, 0xff, /* blue */
238 0xff, 0x00, 0xff, /* magenta */
239 0x00, 0xff, 0xff, /* cyan */
240 0xff, 0xff, 0xff, /* white */
241 };
242
243 /**** Low-level hardware register groveling functions ****/
244 static void
245 rex3_write(struct newport_devconfig *dc, bus_size_t rexreg, uint32_t val)
246 {
247 bus_space_write_4(dc->dc_st, dc->dc_sh, NEWPORT_REX3_OFFSET + rexreg,
248 val);
249 }
250
251 static void
252 rex3_write_go(struct newport_devconfig *dc, bus_size_t rexreg, uint32_t val)
253 {
254 rex3_write(dc, rexreg + REX3_REG_GO, val);
255 }
256
257 static uint32_t
258 rex3_read(struct newport_devconfig *dc, bus_size_t rexreg)
259 {
260 return bus_space_read_4(dc->dc_st, dc->dc_sh, NEWPORT_REX3_OFFSET +
261 rexreg);
262 }
263
264 static void
265 rex3_wait_gfifo(struct newport_devconfig *dc)
266 {
267 while (rex3_read(dc, REX3_REG_STATUS) & REX3_STATUS_GFXBUSY)
268 ;
269 }
270
271 static void
272 vc2_write_ireg(struct newport_devconfig *dc, uint8_t ireg, uint16_t val)
273 {
274 rex3_write(dc, REX3_REG_DCBMODE,
275 REX3_DCBMODE_DW_3 |
276 REX3_DCBMODE_ENCRSINC |
277 (NEWPORT_DCBADDR_VC2 << REX3_DCBMODE_DCBADDR_SHIFT) |
278 (VC2_DCBCRS_INDEX << REX3_DCBMODE_DCBCRS_SHIFT) |
279 REX3_DCBMODE_ENASYNCACK |
280 (1 << REX3_DCBMODE_CSSETUP_SHIFT));
281
282 rex3_write(dc, REX3_REG_DCBDATA0, (ireg << 24) | (val << 8));
283 }
284
285 static uint16_t
286 vc2_read_ireg(struct newport_devconfig *dc, uint8_t ireg)
287 {
288 rex3_write(dc, REX3_REG_DCBMODE,
289 REX3_DCBMODE_DW_1 |
290 REX3_DCBMODE_ENCRSINC |
291 (NEWPORT_DCBADDR_VC2 << REX3_DCBMODE_DCBADDR_SHIFT) |
292 (VC2_DCBCRS_INDEX << REX3_DCBMODE_DCBCRS_SHIFT) |
293 REX3_DCBMODE_ENASYNCACK |
294 (1 << REX3_DCBMODE_CSSETUP_SHIFT));
295
296 rex3_write(dc, REX3_REG_DCBDATA0, ireg << 24);
297
298 rex3_write(dc, REX3_REG_DCBMODE,
299 REX3_DCBMODE_DW_2 |
300 REX3_DCBMODE_ENCRSINC |
301 (NEWPORT_DCBADDR_VC2 << REX3_DCBMODE_DCBADDR_SHIFT) |
302 (VC2_DCBCRS_IREG << REX3_DCBMODE_DCBCRS_SHIFT) |
303 REX3_DCBMODE_ENASYNCACK |
304 (1 << REX3_DCBMODE_CSSETUP_SHIFT));
305
306 return (uint16_t)(rex3_read(dc, REX3_REG_DCBDATA0) >> 16);
307 }
308
309 static uint16_t
310 vc2_read_ram(struct newport_devconfig *dc, uint16_t addr)
311 {
312 vc2_write_ireg(dc, VC2_IREG_RAM_ADDRESS, addr);
313
314 rex3_write(dc, REX3_REG_DCBMODE,
315 REX3_DCBMODE_DW_2 |
316 (NEWPORT_DCBADDR_VC2 << REX3_DCBMODE_DCBADDR_SHIFT) |
317 (VC2_DCBCRS_RAM << REX3_DCBMODE_DCBCRS_SHIFT) |
318 REX3_DCBMODE_ENASYNCACK |
319 (1 << REX3_DCBMODE_CSSETUP_SHIFT));
320
321 return (uint16_t)(rex3_read(dc, REX3_REG_DCBDATA0) >> 16);
322 }
323
324 static void
325 vc2_write_ram(struct newport_devconfig *dc, uint16_t addr, uint16_t val)
326 {
327 vc2_write_ireg(dc, VC2_IREG_RAM_ADDRESS, addr);
328
329 rex3_write(dc, REX3_REG_DCBMODE,
330 REX3_DCBMODE_DW_2 |
331 (NEWPORT_DCBADDR_VC2 << REX3_DCBMODE_DCBADDR_SHIFT) |
332 (VC2_DCBCRS_RAM << REX3_DCBMODE_DCBCRS_SHIFT) |
333 REX3_DCBMODE_ENASYNCACK |
334 (1 << REX3_DCBMODE_CSSETUP_SHIFT));
335
336 rex3_write(dc, REX3_REG_DCBDATA0, val << 16);
337 }
338
339 static void
340 xmap9_write(struct newport_devconfig *dc, int crs, uint8_t val)
341 {
342 rex3_write(dc, REX3_REG_DCBMODE,
343 REX3_DCBMODE_DW_1 |
344 (NEWPORT_DCBADDR_XMAP_BOTH << REX3_DCBMODE_DCBADDR_SHIFT) |
345 (crs << REX3_DCBMODE_DCBCRS_SHIFT) |
346 (3 << REX3_DCBMODE_CSWIDTH_SHIFT) |
347 (2 << REX3_DCBMODE_CSHOLD_SHIFT) |
348 (1 << REX3_DCBMODE_CSSETUP_SHIFT));
349
350 rex3_write(dc, REX3_REG_DCBDATA0, val << 24);
351 }
352
353 static void
354 xmap9_write_mode(struct newport_devconfig *dc, uint8_t index, uint32_t mode)
355 {
356 rex3_write(dc, REX3_REG_DCBMODE,
357 REX3_DCBMODE_DW_4 |
358 (NEWPORT_DCBADDR_XMAP_BOTH << REX3_DCBMODE_DCBADDR_SHIFT) |
359 (XMAP9_DCBCRS_MODE_SETUP << REX3_DCBMODE_DCBCRS_SHIFT) |
360 (3 << REX3_DCBMODE_CSWIDTH_SHIFT) |
361 (2 << REX3_DCBMODE_CSHOLD_SHIFT) |
362 (1 << REX3_DCBMODE_CSSETUP_SHIFT));
363
364 rex3_write(dc, REX3_REG_DCBDATA0, (index << 24) | mode);
365 }
366
367 /**** Helper functions ****/
368 static void
369 newport_fill_rectangle(struct newport_devconfig *dc, int x1, int y1, int x2,
370 int y2, uint8_t color)
371 {
372 rex3_wait_gfifo(dc);
373
374 rex3_write(dc, REX3_REG_DRAWMODE0, REX3_DRAWMODE0_OPCODE_DRAW |
375 REX3_DRAWMODE0_ADRMODE_BLOCK | REX3_DRAWMODE0_DOSETUP |
376 REX3_DRAWMODE0_STOPONX | REX3_DRAWMODE0_STOPONY);
377 rex3_write(dc, REX3_REG_WRMASK, 0xff);
378 rex3_write(dc, REX3_REG_COLORI, color);
379 rex3_write(dc, REX3_REG_XYSTARTI, (x1 << REX3_XYSTARTI_XSHIFT) | y1);
380
381 rex3_write_go(dc, REX3_REG_XYENDI, (x2 << REX3_XYENDI_XSHIFT) | y2);
382 }
383
384 static void
385 newport_copy_rectangle(struct newport_devconfig *dc, int x1, int y1, int x2,
386 int y2, int dx, int dy)
387 {
388 uint32_t tmp;
389
390 rex3_wait_gfifo(dc);
391
392 rex3_write(dc, REX3_REG_DRAWMODE0, REX3_DRAWMODE0_OPCODE_SCR2SCR |
393 REX3_DRAWMODE0_ADRMODE_BLOCK | REX3_DRAWMODE0_DOSETUP |
394 REX3_DRAWMODE0_STOPONX | REX3_DRAWMODE0_STOPONY);
395 rex3_write(dc, REX3_REG_XYSTARTI, (x1 << REX3_XYSTARTI_XSHIFT) | y1);
396 rex3_write(dc, REX3_REG_XYENDI, (x2 << REX3_XYENDI_XSHIFT) | y2);
397
398 tmp = (dy - y1) & 0xffff;
399 tmp |= (dx - x1) << REX3_XYMOVE_XSHIFT;
400
401 rex3_write_go(dc, REX3_REG_XYMOVE, tmp);
402 }
403
404 static void
405 newport_cmap_setrgb(struct newport_devconfig *dc, int index, uint8_t r,
406 uint8_t g, uint8_t b)
407 {
408 rex3_write(dc, REX3_REG_DCBMODE,
409 REX3_DCBMODE_DW_2 |
410 REX3_DCBMODE_ENCRSINC |
411 (NEWPORT_DCBADDR_CMAP_BOTH << REX3_DCBMODE_DCBADDR_SHIFT) |
412 (CMAP_DCBCRS_ADDRESS_LOW << REX3_DCBMODE_DCBCRS_SHIFT) |
413 (1 << REX3_DCBMODE_CSWIDTH_SHIFT) |
414 (1 << REX3_DCBMODE_CSHOLD_SHIFT) |
415 (1 << REX3_DCBMODE_CSSETUP_SHIFT) |
416 REX3_DCBMODE_SWAPENDIAN);
417
418 rex3_write(dc, REX3_REG_DCBDATA0, index << 16);
419
420 rex3_write(dc, REX3_REG_DCBMODE,
421 REX3_DCBMODE_DW_3 |
422 (NEWPORT_DCBADDR_CMAP_BOTH << REX3_DCBMODE_DCBADDR_SHIFT) |
423 (CMAP_DCBCRS_PALETTE << REX3_DCBMODE_DCBCRS_SHIFT) |
424 (1 << REX3_DCBMODE_CSWIDTH_SHIFT) |
425 (1 << REX3_DCBMODE_CSHOLD_SHIFT) |
426 (1 << REX3_DCBMODE_CSSETUP_SHIFT));
427
428 rex3_write(dc, REX3_REG_DCBDATA0, (r << 24) + (g << 16) + (b << 8));
429 }
430
431 static void
432 newport_get_resolution(struct newport_devconfig *dc)
433 {
434 uint16_t vep,lines;
435 uint16_t linep,cols;
436 uint16_t data;
437
438 vep = vc2_read_ireg(dc, VC2_IREG_VIDEO_ENTRY);
439
440 dc->dc_xres = 0;
441 dc->dc_yres = 0;
442
443 for (;;) {
444 /* Iterate over runs in video timing table */
445
446 cols = 0;
447
448 linep = vc2_read_ram(dc, vep++);
449 lines = vc2_read_ram(dc, vep++);
450
451 if (lines == 0)
452 break;
453
454 do {
455 /* Iterate over state runs in line sequence table */
456
457 data = vc2_read_ram(dc, linep++);
458
459 if ((data & 0x0001) == 0)
460 cols += (data >> 7) & 0xfe;
461
462 if ((data & 0x0080) == 0)
463 data = vc2_read_ram(dc, linep++);
464 } while ((data & 0x8000) == 0);
465
466 if (cols != 0) {
467 if (cols > dc->dc_xres)
468 dc->dc_xres = cols;
469
470 dc->dc_yres += lines;
471 }
472 }
473 }
474
475 static void
476 newport_setup_hw(struct newport_devconfig *dc)
477 {
478 uint16_t curp,tmp;
479 int i;
480
481 /* Get newport board revision */
482 rex3_write(dc, REX3_REG_DCBMODE,
483 REX3_DCBMODE_DW_1 |
484 (NEWPORT_DCBADDR_CMAP_0 << REX3_DCBMODE_DCBADDR_SHIFT) |
485 (CMAP_DCBCRS_REVISION << REX3_DCBMODE_DCBCRS_SHIFT) |
486 (1 << REX3_DCBMODE_CSWIDTH_SHIFT) |
487 (1 << REX3_DCBMODE_CSHOLD_SHIFT) |
488 (1 << REX3_DCBMODE_CSSETUP_SHIFT));
489
490 dc->dc_boardrev = (rex3_read(dc, REX3_REG_DCBDATA0) >> 4) & 0x07;
491
492 /* Setup cursor glyph */
493 curp = vc2_read_ireg(dc, VC2_IREG_CURSOR_ENTRY);
494
495 for (i=0; i<128; i++)
496 vc2_write_ram(dc, curp + i, newport_cursor_data[i]);
497
498 /* Setup VC2 to a known state */
499 tmp = vc2_read_ireg(dc, VC2_IREG_CONTROL) & VC2_CONTROL_INTERLACE;
500 vc2_write_ireg(dc, VC2_IREG_CONTROL, tmp |
501 VC2_CONTROL_DISPLAY_ENABLE |
502 VC2_CONTROL_VTIMING_ENABLE |
503 VC2_CONTROL_DID_ENABLE |
504 VC2_CONTROL_CURSORFUNC_ENABLE |
505 VC2_CONTROL_CURSOR_ENABLE);
506
507 /* Setup XMAP9s */
508 xmap9_write(dc, XMAP9_DCBCRS_CONFIG,
509 XMAP9_CONFIG_8BIT_SYSTEM | XMAP9_CONFIG_RGBMAP_CI);
510
511 xmap9_write(dc, XMAP9_DCBCRS_CURSOR_CMAP, 0);
512
513 xmap9_write_mode(dc, 0,
514 XMAP9_MODE_GAMMA_BYPASS |
515 XMAP9_MODE_PIXSIZE_8BPP);
516 xmap9_write(dc, XMAP9_DCBCRS_MODE_SELECT, 0);
517
518 /* Setup REX3 */
519 rex3_write(dc, REX3_REG_DRAWMODE1,
520 REX3_DRAWMODE1_PLANES_CI |
521 REX3_DRAWMODE1_DD_DD8 |
522 REX3_DRAWMODE1_RWPACKED |
523 REX3_DRAWMODE1_HD_HD8 |
524 REX3_DRAWMODE1_COMPARE_LT |
525 REX3_DRAWMODE1_COMPARE_EQ |
526 REX3_DRAWMODE1_COMPARE_GT |
527 REX3_DRAWMODE1_LO_SRC);
528 rex3_write(dc, REX3_REG_XYWIN, (4096 << 16) | 4096);
529 rex3_write(dc, REX3_REG_TOPSCAN, 0x3ff); /* XXX Why? XXX */
530
531 /* Setup CMAP */
532 for (i=0; i<16; i++)
533 newport_cmap_setrgb(dc, i, newport_defcmap[i*3],
534 newport_defcmap[i*3 + 1], newport_defcmap[i*3 + 2]);
535 }
536
537 /**** Attach routines ****/
538 static int
539 newport_match(struct device *parent, struct cfdata *self, void *aux)
540 {
541 struct gio_attach_args *ga = aux;
542
543 /* newport doesn't decode all addresses */
544 if (ga->ga_addr != 0x1f000000 && ga->ga_addr != 0x1f400000 &&
545 ga->ga_addr != 0x1f800000 && ga->ga_addr != 0x1fc00000)
546 return 0;
547
548 /* newport doesn't respond with correct product id, empirically
549 * both empty slots and newports seem to yield this result */
550 if (ga->ga_product != 0x04)
551 return 0;
552
553 /* Don't do the destructive probe if we're already attached */
554 if (newport_is_console && ga->ga_addr == newport_console_dc.dc_addr)
555 return 1;
556
557 /* Ugly, this probe is destructive, blame SGI... */
558 /* XXX Should be bus_space_peek/bus_space_poke XXX */
559 bus_space_write_4(ga->ga_iot, ga->ga_ioh,
560 NEWPORT_REX3_OFFSET + REX3_REG_XSTARTI, 0x12345678);
561 if (bus_space_read_4(ga->ga_iot, ga->ga_ioh,
562 NEWPORT_REX3_OFFSET + REX3_REG_XSTART)
563 != ((0x12345678 & 0xffff) << 11))
564 return 0;
565
566 return 1;
567 }
568
569 static void
570 newport_attach_common(struct newport_devconfig *dc, struct gio_attach_args *ga)
571 {
572 dc->dc_addr = ga->ga_addr;
573
574 dc->dc_screens = 0;
575
576 dc->dc_st = ga->ga_iot;
577 dc->dc_sh = ga->ga_ioh;
578
579 wsfont_init();
580
581 dc->dc_font = wsfont_find(NULL, 8, 16, 0, WSDISPLAY_FONTORDER_L2R,
582 WSDISPLAY_FONTORDER_L2R);
583 if (dc->dc_font < 0)
584 panic("newport_attach_common: no suitable fonts");
585
586 if (wsfont_lock(dc->dc_font, &dc->dc_fontdata))
587 panic("newport_attach_common: unable to lock font data");
588
589 newport_setup_hw(dc);
590
591 newport_get_resolution(dc);
592
593 newport_fill_rectangle(dc, 0, 0, dc->dc_xres, dc->dc_yres, 0);
594 }
595
596 static void
597 newport_attach(struct device *parent, struct device *self, void *aux)
598 {
599 struct gio_attach_args *ga = aux;
600 struct newport_softc *sc = (void *)self;
601 struct wsemuldisplaydev_attach_args wa;
602
603 if (newport_is_console && ga->ga_addr == newport_console_dc.dc_addr) {
604 wa.console = 1;
605 sc->sc_dc = &newport_console_dc;
606 } else {
607 wa.console = 0;
608 sc->sc_dc = malloc(sizeof(struct newport_devconfig),
609 M_DEVBUF, M_WAITOK | M_ZERO);
610 if (sc->sc_dc == NULL)
611 panic("newport_attach: out of memory");
612
613 newport_attach_common(sc->sc_dc, ga);
614 }
615
616 aprint_naive(": Display adapter\n");
617
618 aprint_normal(": SGI NG1 (board revision %d)\n",
619 sc->sc_dc->dc_boardrev);
620
621 wa.scrdata = &newport_screenlist;
622 wa.accessops = &newport_accessops;
623 wa.accesscookie = sc->sc_dc;
624
625 config_found(&sc->sc_dev, &wa, wsemuldisplaydevprint);
626 }
627
628 int
629 newport_cnattach(struct gio_attach_args *ga)
630 {
631 long defattr = NEWPORT_ATTR_ENCODE(WSCOL_WHITE, WSCOL_BLACK);
632 const struct wsscreen_descr *screen;
633
634 if (!newport_match(NULL, NULL, ga)) {
635 return ENXIO;
636 }
637
638 newport_attach_common(&newport_console_dc, ga);
639
640 if (newport_console_dc.dc_xres >= 1280 &&
641 newport_console_dc.dc_yres >= 1024)
642 screen = &newport_screen_1280x1024;
643 else
644 screen = &newport_screen_1024x768;
645
646 wsdisplay_cnattach(screen, &newport_console_dc, 0, 0, defattr);
647
648 newport_is_console = 1;
649
650 return 0;
651 }
652
653 /**** wsdisplay textops ****/
654 static void
655 newport_cursor(void *c, int on, int row, int col)
656 {
657 struct newport_devconfig *dc = (void *)c;
658 uint16_t control;
659 int x_offset;
660
661 control = vc2_read_ireg(dc, VC2_IREG_CONTROL);
662
663 if (!on) {
664 vc2_write_ireg(dc, VC2_IREG_CONTROL,
665 control & ~VC2_CONTROL_CURSOR_ENABLE);
666 } else {
667 /* Work around bug in some board revisions */
668 if (dc->dc_boardrev < 6)
669 x_offset = 21;
670 else
671 x_offset = 31;
672
673 vc2_write_ireg(dc, VC2_IREG_CURSOR_X,
674 col * dc->dc_fontdata->fontwidth + x_offset);
675 vc2_write_ireg(dc, VC2_IREG_CURSOR_Y,
676 row * dc->dc_fontdata->fontheight + 31);
677
678 vc2_write_ireg(dc, VC2_IREG_CONTROL,
679 control | VC2_CONTROL_CURSOR_ENABLE);
680 }
681 }
682
683 static int
684 newport_mapchar(void *c, int ch, unsigned int *cp)
685 {
686 struct newport_devconfig *dc = (void *)c;
687
688 if (dc->dc_fontdata->encoding != WSDISPLAY_FONTENC_ISO) {
689 ch = wsfont_map_unichar(dc->dc_fontdata, ch);
690
691 if (ch < 0)
692 goto fail;
693 }
694
695 if (ch < dc->dc_fontdata->firstchar ||
696 ch >= dc->dc_fontdata->firstchar + dc->dc_fontdata->numchars)
697 goto fail;
698
699 *cp = ch;
700 return 5;
701
702 fail:
703 *cp = ' ';
704 return 0;
705 }
706
707 static void
708 newport_putchar(void *c, int row, int col, u_int ch, long attr)
709 {
710 struct newport_devconfig *dc = (void *)c;
711 struct wsdisplay_font *font = dc->dc_fontdata;
712 uint8_t *bitmap = (u_int8_t *)font->data + (ch - font->firstchar) *
713 font->fontheight * font->stride;
714 uint32_t pattern;
715 int i;
716 int x = col * font->fontwidth;
717 int y = row * font->fontheight;
718
719 rex3_wait_gfifo(dc);
720
721 rex3_write(dc, REX3_REG_DRAWMODE0, REX3_DRAWMODE0_OPCODE_DRAW |
722 REX3_DRAWMODE0_ADRMODE_BLOCK | REX3_DRAWMODE0_STOPONX |
723 REX3_DRAWMODE0_ENZPATTERN | REX3_DRAWMODE0_ZPOPAQUE);
724
725 rex3_write(dc, REX3_REG_XYSTARTI, (x << REX3_XYSTARTI_XSHIFT) | y);
726 rex3_write(dc, REX3_REG_XYENDI,
727 (x + font->fontwidth - 1) << REX3_XYENDI_XSHIFT);
728
729 rex3_write(dc, REX3_REG_COLORI, NEWPORT_ATTR_FG(attr));
730 rex3_write(dc, REX3_REG_COLORBACK, NEWPORT_ATTR_BG(attr));
731
732 rex3_write(dc, REX3_REG_WRMASK, 0xff);
733
734 for (i=0; i<font->fontheight; i++) {
735 /* XXX Works only with font->fontwidth == 8 XXX */
736 pattern = *bitmap << 24;
737
738 rex3_write_go(dc, REX3_REG_ZPATTERN, pattern);
739
740 bitmap += font->stride;
741 }
742 }
743
744 static void
745 newport_copycols(void *c, int row, int srccol, int dstcol, int ncols)
746 {
747 struct newport_devconfig *dc = (void *)c;
748 struct wsdisplay_font *font = dc->dc_fontdata;
749
750 newport_copy_rectangle(dc,
751 srccol * font->fontwidth, /* x1 */
752 row * font->fontheight, /* y1 */
753 (srccol + ncols + 1) * font->fontwidth - 1, /* x2 */
754 (row + 1) * font->fontheight - 1, /* y2 */
755 dstcol * font->fontheight, /* dx */
756 row * font->fontheight); /* dy */
757 }
758
759 static void
760 newport_erasecols(void *c, int row, int startcol, int ncols,
761 long attr)
762 {
763 struct newport_devconfig *dc = (void *)c;
764 struct wsdisplay_font *font = dc->dc_fontdata;
765
766 newport_fill_rectangle(dc,
767 startcol * font->fontwidth, /* x1 */
768 row * font->fontheight, /* y1 */
769 (startcol + ncols + 1) * font->fontwidth - 1, /* x2 */
770 (row + 1) * font->fontheight - 1, /* y2 */
771 NEWPORT_ATTR_BG(attr));
772 }
773
774 static void
775 newport_copyrows(void *c, int srcrow, int dstrow, int nrows)
776 {
777 struct newport_devconfig *dc = (void *)c;
778 struct wsdisplay_font *font = dc->dc_fontdata;
779
780 newport_copy_rectangle(dc,
781 0, /* x1 */
782 srcrow * font->fontheight, /* y1 */
783 dc->dc_xres, /* x2 */
784 (srcrow + nrows + 1) * font->fontheight - 1, /* y2 */
785 0, /* dx */
786 dstrow * font->fontheight); /* dy */
787 }
788
789 static void
790 newport_eraserows(void *c, int startrow, int nrows, long attr)
791 {
792 struct newport_devconfig *dc = (void *)c;
793 struct wsdisplay_font *font = dc->dc_fontdata;
794
795 newport_fill_rectangle(dc,
796 0, /* x1 */
797 startrow * font->fontheight, /* y1 */
798 dc->dc_xres, /* x2 */
799 (startrow + nrows + 1) * font->fontheight - 1, /* y2 */
800 NEWPORT_ATTR_BG(attr));
801 }
802
803 static int
804 newport_allocattr(void *c, int fg, int bg, int flags, long *attr)
805 {
806 if (flags & WSATTR_BLINK)
807 return EINVAL;
808
809 if ((flags & WSATTR_WSCOLORS) == 0) {
810 fg = WSCOL_WHITE;
811 bg = WSCOL_BLACK;
812 }
813
814 if (flags & WSATTR_HILIT)
815 fg += 8;
816
817 if (flags & WSATTR_REVERSE) {
818 int tmp = fg;
819 fg = bg;
820 bg = tmp;
821 }
822
823 *attr = NEWPORT_ATTR_ENCODE(fg, bg);
824
825 return 0;
826 }
827
828 /**** wsdisplay accessops ****/
829
830 static int
831 newport_ioctl(void *c, u_long cmd, caddr_t data, int flag, struct proc *p)
832 {
833 return EPASSTHROUGH;
834 }
835
836 static paddr_t
837 newport_mmap(void *c, off_t offset, int prot)
838 {
839 return -1;
840 }
841
842 static int
843 newport_alloc_screen(void *c, const struct wsscreen_descr *type, void **cookiep,
844 int *cursxp, int *cursyp, long *attrp)
845 {
846 /* This won't get called for console screen and we don't support
847 * virtual screens */
848
849 return ENOMEM;
850 }
851
852 static void
853 newport_free_screen(void *c, void *cookie)
854 {
855 panic("newport_free_screen");
856 }
857 static int
858 newport_show_screen(void *c, void *cookie, int waitok,
859 void (*cb)(void *, int, int), void *cbarg)
860 {
861 return 0;
862 }
863