newport.c revision 1.10.52.1 1 /* $NetBSD: newport.c,v 1.10.52.1 2009/03/03 18:29:14 skrll 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.10.52.1 2009/03/03 18:29:14 skrll 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 <machine/sysconf.h>
41
42 #include <dev/wscons/wsconsio.h>
43 #include <dev/wscons/wsdisplayvar.h>
44 #include <dev/wsfont/wsfont.h>
45 #include <dev/rasops/rasops.h>
46 #include <dev/wscons/wsdisplay_vconsvar.h>
47
48 #include <sgimips/gio/giovar.h>
49 #include <sgimips/gio/newportvar.h>
50 #include <sgimips/gio/newportreg.h>
51
52 struct newport_softc {
53 device_t sc_dev;
54
55 struct newport_devconfig *sc_dc;
56
57 };
58
59 struct newport_devconfig {
60 uint32_t dc_addr;
61
62 bus_space_tag_t dc_st;
63 bus_space_handle_t dc_sh;
64
65 int dc_boardrev;
66 int dc_vc2rev;
67 int dc_cmaprev;
68 int dc_xmaprev;
69 int dc_rexrev;
70 int dc_xres;
71 int dc_yres;
72 int dc_depth;
73
74 int dc_font;
75 struct wsscreen_descr *dc_screen;
76 struct wsdisplay_font *dc_fontdata;
77 struct vcons_data dc_vd;
78 };
79
80 static int newport_match(device_t, struct cfdata *, void *);
81 static void newport_attach(device_t, device_t, void *);
82
83 CFATTACH_DECL_NEW(newport, sizeof(struct newport_softc),
84 newport_match, newport_attach, NULL, NULL);
85
86 /* textops */
87 static void newport_cursor(void *, int, int, int);
88 static void newport_cursor_dummy(void *, int, int, int);
89 static int newport_mapchar(void *, int, unsigned int *);
90 static void newport_putchar(void *, int, int, u_int, long);
91 static void newport_copycols(void *, int, int, int, int);
92 static void newport_erasecols(void *, int, int, int, long);
93 static void newport_copyrows(void *, int, int, int);
94 static void newport_eraserows(void *, int, int, long);
95 static int newport_allocattr(void *, int, int, int, long *);
96
97 static void newport_init_screen(void *, struct vcons_screen *, int, long *);
98
99 /* accessops */
100 static int newport_ioctl(void *, void *, u_long, void *, int,
101 struct lwp *);
102 static paddr_t newport_mmap(void *, void *, off_t, int);
103
104 static struct wsdisplay_accessops newport_accessops = {
105 .ioctl = newport_ioctl,
106 .mmap = newport_mmap,
107 };
108
109 static struct wsdisplay_emulops newport_textops = {
110 .cursor = newport_cursor_dummy,
111 .mapchar = newport_mapchar,
112 .putchar = newport_putchar,
113 .copycols = newport_copycols,
114 .erasecols = newport_erasecols,
115 .copyrows = newport_copyrows,
116 .eraserows = newport_eraserows,
117 .allocattr = newport_allocattr
118 };
119
120 static struct wsscreen_descr newport_screen_1024x768 = {
121 .name = "1024x768",
122 .ncols = 128,
123 .nrows = 48,
124 .textops = &newport_textops,
125 .fontwidth = 8,
126 .fontheight = 16,
127 .capabilities = WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_REVERSE
128 };
129
130 static struct wsscreen_descr newport_screen_1280x1024 = {
131 .name = "1280x1024",
132 .ncols = 160,
133 .nrows = 64,
134 .textops = &newport_textops,
135 .fontwidth = 8,
136 .fontheight = 16,
137 .capabilities = WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_REVERSE
138 };
139
140 static const struct wsscreen_descr *_newport_screenlist[] = {
141 &newport_screen_1024x768,
142 &newport_screen_1280x1024
143 };
144
145 static const struct wsscreen_list newport_screenlist = {
146 sizeof(_newport_screenlist) / sizeof(struct wsscreen_descr *),
147 _newport_screenlist
148 };
149
150 static struct vcons_screen newport_console_screen;
151 static struct newport_devconfig newport_console_dc;
152 static int newport_is_console = 0;
153
154 #define NEWPORT_ATTR_ENCODE(fg,bg) (((fg) << 8) | (bg))
155 #define NEWPORT_ATTR_BG(a) ((a) & 0xff)
156 #define NEWPORT_ATTR_FG(a) (((a) >> 8) & 0xff)
157
158 extern const u_char rasops_cmap[768];
159
160 /**** Low-level hardware register groveling functions ****/
161 static void
162 rex3_write(struct newport_devconfig *dc, bus_size_t rexreg, uint32_t val)
163 {
164 bus_space_write_4(dc->dc_st, dc->dc_sh, NEWPORT_REX3_OFFSET + rexreg,
165 val);
166 }
167
168 static void
169 rex3_write_go(struct newport_devconfig *dc, bus_size_t rexreg, uint32_t val)
170 {
171 rex3_write(dc, rexreg + REX3_REG_GO, val);
172 }
173
174 static uint32_t
175 rex3_read(struct newport_devconfig *dc, bus_size_t rexreg)
176 {
177 return bus_space_read_4(dc->dc_st, dc->dc_sh, NEWPORT_REX3_OFFSET +
178 rexreg);
179 }
180
181 static void
182 rex3_wait_gfifo(struct newport_devconfig *dc)
183 {
184 while (rex3_read(dc, REX3_REG_STATUS) & REX3_STATUS_GFXBUSY)
185 ;
186 }
187
188 static void
189 vc2_write_ireg(struct newport_devconfig *dc, uint8_t ireg, uint16_t val)
190 {
191 rex3_write(dc, REX3_REG_DCBMODE,
192 REX3_DCBMODE_DW_3 |
193 REX3_DCBMODE_ENCRSINC |
194 (NEWPORT_DCBADDR_VC2 << REX3_DCBMODE_DCBADDR_SHIFT) |
195 (VC2_DCBCRS_INDEX << REX3_DCBMODE_DCBCRS_SHIFT) |
196 REX3_DCBMODE_ENASYNCACK |
197 (1 << REX3_DCBMODE_CSSETUP_SHIFT));
198
199 rex3_write(dc, REX3_REG_DCBDATA0, (ireg << 24) | (val << 8));
200 }
201
202 static uint16_t
203 vc2_read_ireg(struct newport_devconfig *dc, uint8_t ireg)
204 {
205 rex3_write(dc, REX3_REG_DCBMODE,
206 REX3_DCBMODE_DW_1 |
207 REX3_DCBMODE_ENCRSINC |
208 (NEWPORT_DCBADDR_VC2 << REX3_DCBMODE_DCBADDR_SHIFT) |
209 (VC2_DCBCRS_INDEX << REX3_DCBMODE_DCBCRS_SHIFT) |
210 REX3_DCBMODE_ENASYNCACK |
211 (1 << REX3_DCBMODE_CSSETUP_SHIFT));
212
213 rex3_write(dc, REX3_REG_DCBDATA0, ireg << 24);
214
215 rex3_write(dc, REX3_REG_DCBMODE,
216 REX3_DCBMODE_DW_2 |
217 REX3_DCBMODE_ENCRSINC |
218 (NEWPORT_DCBADDR_VC2 << REX3_DCBMODE_DCBADDR_SHIFT) |
219 (VC2_DCBCRS_IREG << REX3_DCBMODE_DCBCRS_SHIFT) |
220 REX3_DCBMODE_ENASYNCACK |
221 (1 << REX3_DCBMODE_CSSETUP_SHIFT));
222
223 return (uint16_t)(rex3_read(dc, REX3_REG_DCBDATA0) >> 16);
224 }
225
226 static uint16_t
227 vc2_read_ram(struct newport_devconfig *dc, uint16_t addr)
228 {
229 vc2_write_ireg(dc, VC2_IREG_RAM_ADDRESS, addr);
230
231 rex3_write(dc, REX3_REG_DCBMODE,
232 REX3_DCBMODE_DW_2 |
233 (NEWPORT_DCBADDR_VC2 << REX3_DCBMODE_DCBADDR_SHIFT) |
234 (VC2_DCBCRS_RAM << REX3_DCBMODE_DCBCRS_SHIFT) |
235 REX3_DCBMODE_ENASYNCACK |
236 (1 << REX3_DCBMODE_CSSETUP_SHIFT));
237
238 return (uint16_t)(rex3_read(dc, REX3_REG_DCBDATA0) >> 16);
239 }
240
241 #if 0
242 static void
243 vc2_write_ram(struct newport_devconfig *dc, uint16_t addr, uint16_t val)
244 {
245 vc2_write_ireg(dc, VC2_IREG_RAM_ADDRESS, addr);
246
247 rex3_write(dc, REX3_REG_DCBMODE,
248 REX3_DCBMODE_DW_2 |
249 (NEWPORT_DCBADDR_VC2 << REX3_DCBMODE_DCBADDR_SHIFT) |
250 (VC2_DCBCRS_RAM << REX3_DCBMODE_DCBCRS_SHIFT) |
251 REX3_DCBMODE_ENASYNCACK |
252 (1 << REX3_DCBMODE_CSSETUP_SHIFT));
253
254 rex3_write(dc, REX3_REG_DCBDATA0, val << 16);
255 }
256 #endif
257
258 static u_int32_t
259 xmap9_read(struct newport_devconfig *dc, int crs)
260 {
261 rex3_write(dc, REX3_REG_DCBMODE,
262 REX3_DCBMODE_DW_1 |
263 (NEWPORT_DCBADDR_XMAP_0 << REX3_DCBMODE_DCBADDR_SHIFT) |
264 (crs << REX3_DCBMODE_DCBCRS_SHIFT) |
265 (3 << REX3_DCBMODE_CSWIDTH_SHIFT) |
266 (2 << REX3_DCBMODE_CSHOLD_SHIFT) |
267 (1 << REX3_DCBMODE_CSSETUP_SHIFT));
268 return rex3_read(dc, REX3_REG_DCBDATA0);
269 }
270
271 static void
272 xmap9_write(struct newport_devconfig *dc, int crs, uint8_t val)
273 {
274 rex3_write(dc, REX3_REG_DCBMODE,
275 REX3_DCBMODE_DW_1 |
276 (NEWPORT_DCBADDR_XMAP_BOTH << REX3_DCBMODE_DCBADDR_SHIFT) |
277 (crs << REX3_DCBMODE_DCBCRS_SHIFT) |
278 (3 << REX3_DCBMODE_CSWIDTH_SHIFT) |
279 (2 << REX3_DCBMODE_CSHOLD_SHIFT) |
280 (1 << REX3_DCBMODE_CSSETUP_SHIFT));
281
282 rex3_write(dc, REX3_REG_DCBDATA0, val << 24);
283 }
284
285 static void
286 xmap9_write_mode(struct newport_devconfig *dc, uint8_t index, uint32_t mode)
287 {
288 rex3_write(dc, REX3_REG_DCBMODE,
289 REX3_DCBMODE_DW_4 |
290 (NEWPORT_DCBADDR_XMAP_BOTH << REX3_DCBMODE_DCBADDR_SHIFT) |
291 (XMAP9_DCBCRS_MODE_SETUP << REX3_DCBMODE_DCBCRS_SHIFT) |
292 (3 << REX3_DCBMODE_CSWIDTH_SHIFT) |
293 (2 << REX3_DCBMODE_CSHOLD_SHIFT) |
294 (1 << REX3_DCBMODE_CSSETUP_SHIFT));
295
296 rex3_write(dc, REX3_REG_DCBDATA0, (index << 24) | mode);
297 }
298
299 /**** Helper functions ****/
300 static void
301 newport_fill_rectangle(struct newport_devconfig *dc, int x1, int y1, int x2,
302 int y2, uint8_t color)
303 {
304 rex3_wait_gfifo(dc);
305
306 rex3_write(dc, REX3_REG_DRAWMODE0, REX3_DRAWMODE0_OPCODE_DRAW |
307 REX3_DRAWMODE0_ADRMODE_BLOCK | REX3_DRAWMODE0_DOSETUP |
308 REX3_DRAWMODE0_STOPONX | REX3_DRAWMODE0_STOPONY);
309 rex3_write(dc, REX3_REG_DRAWMODE1,
310 REX3_DRAWMODE1_PLANES_CI |
311 REX3_DRAWMODE1_DD_DD8 |
312 REX3_DRAWMODE1_RWPACKED |
313 REX3_DRAWMODE1_HD_HD8 |
314 REX3_DRAWMODE1_COMPARE_LT |
315 REX3_DRAWMODE1_COMPARE_EQ |
316 REX3_DRAWMODE1_COMPARE_GT |
317 REX3_DRAWMODE1_LO_SRC);
318 rex3_write(dc, REX3_REG_WRMASK, 0xffffffff);
319 rex3_write(dc, REX3_REG_COLORI, color);
320 rex3_write(dc, REX3_REG_XYSTARTI, (x1 << REX3_XYSTARTI_XSHIFT) | y1);
321
322 rex3_write_go(dc, REX3_REG_XYENDI, (x2 << REX3_XYENDI_XSHIFT) | y2);
323 }
324
325 static void
326 newport_bitblt(struct newport_devconfig *dc, int xs, int ys, int xd,
327 int yd, int wi, int he, int rop)
328 {
329 int xe, ye;
330 uint32_t tmp;
331
332 rex3_wait_gfifo(dc);
333 if (yd > ys) {
334 /* need to copy bottom up */
335 ye = ys;
336 yd += he - 1;
337 ys += he - 1;
338 } else
339 ye = ys + he - 1;
340
341 if (xd > xs) {
342 /* need to copy right to left */
343 xe = xs;
344 xd += wi - 1;
345 xs += wi - 1;
346 } else
347 xe = xs + wi - 1;
348
349 rex3_write(dc, REX3_REG_DRAWMODE0, REX3_DRAWMODE0_OPCODE_SCR2SCR |
350 REX3_DRAWMODE0_ADRMODE_BLOCK | REX3_DRAWMODE0_DOSETUP |
351 REX3_DRAWMODE0_STOPONX | REX3_DRAWMODE0_STOPONY);
352 rex3_write(dc, REX3_REG_DRAWMODE1,
353 REX3_DRAWMODE1_PLANES_CI |
354 REX3_DRAWMODE1_DD_DD8 |
355 REX3_DRAWMODE1_RWPACKED |
356 REX3_DRAWMODE1_HD_HD8 |
357 REX3_DRAWMODE1_COMPARE_LT |
358 REX3_DRAWMODE1_COMPARE_EQ |
359 REX3_DRAWMODE1_COMPARE_GT |
360 ((rop << 28) & REX3_DRAWMODE1_LOGICOP_MASK));
361 rex3_write(dc, REX3_REG_XYSTARTI, (xs << REX3_XYSTARTI_XSHIFT) | ys);
362 rex3_write(dc, REX3_REG_XYENDI, (xe << REX3_XYENDI_XSHIFT) | ye);
363
364 tmp = (yd - ys) & 0xffff;
365 tmp |= (xd - xs) << REX3_XYMOVE_XSHIFT;
366
367 rex3_write_go(dc, REX3_REG_XYMOVE, tmp);
368 }
369
370 static void
371 newport_cmap_setrgb(struct newport_devconfig *dc, int index, uint8_t r,
372 uint8_t g, uint8_t b)
373 {
374 rex3_write(dc, REX3_REG_DCBMODE,
375 REX3_DCBMODE_DW_2 |
376 REX3_DCBMODE_ENCRSINC |
377 (NEWPORT_DCBADDR_CMAP_BOTH << REX3_DCBMODE_DCBADDR_SHIFT) |
378 (CMAP_DCBCRS_ADDRESS_LOW << REX3_DCBMODE_DCBCRS_SHIFT) |
379 (1 << REX3_DCBMODE_CSWIDTH_SHIFT) |
380 (1 << REX3_DCBMODE_CSHOLD_SHIFT) |
381 (1 << REX3_DCBMODE_CSSETUP_SHIFT) |
382 REX3_DCBMODE_SWAPENDIAN);
383
384 rex3_write(dc, REX3_REG_DCBDATA0, index << 16);
385
386 rex3_write(dc, REX3_REG_DCBMODE,
387 REX3_DCBMODE_DW_3 |
388 (NEWPORT_DCBADDR_CMAP_BOTH << REX3_DCBMODE_DCBADDR_SHIFT) |
389 (CMAP_DCBCRS_PALETTE << REX3_DCBMODE_DCBCRS_SHIFT) |
390 (1 << REX3_DCBMODE_CSWIDTH_SHIFT) |
391 (1 << REX3_DCBMODE_CSHOLD_SHIFT) |
392 (1 << REX3_DCBMODE_CSSETUP_SHIFT));
393
394 rex3_write(dc, REX3_REG_DCBDATA0, (r << 24) + (g << 16) + (b << 8));
395 }
396
397 static void
398 newport_get_resolution(struct newport_devconfig *dc)
399 {
400 uint16_t vep,lines;
401 uint16_t linep,cols;
402 uint16_t data;
403
404 vep = vc2_read_ireg(dc, VC2_IREG_VIDEO_ENTRY);
405
406 dc->dc_xres = 0;
407 dc->dc_yres = 0;
408
409 for (;;) {
410 /* Iterate over runs in video timing table */
411
412 cols = 0;
413
414 linep = vc2_read_ram(dc, vep++);
415 lines = vc2_read_ram(dc, vep++);
416
417 if (lines == 0)
418 break;
419
420 do {
421 /* Iterate over state runs in line sequence table */
422
423 data = vc2_read_ram(dc, linep++);
424
425 if ((data & 0x0001) == 0)
426 cols += (data >> 7) & 0xfe;
427
428 if ((data & 0x0080) == 0)
429 data = vc2_read_ram(dc, linep++);
430 } while ((data & 0x8000) == 0);
431
432 if (cols != 0) {
433 if (cols > dc->dc_xres)
434 dc->dc_xres = cols;
435
436 dc->dc_yres += lines;
437 }
438 }
439 }
440
441 static void
442 newport_setup_hw(struct newport_devconfig *dc)
443 {
444 uint16_t curp,tmp;
445 int i;
446 uint32_t scratch;
447
448 /* Get various revisions */
449 rex3_write(dc, REX3_REG_DCBMODE,
450 REX3_DCBMODE_DW_1 |
451 (NEWPORT_DCBADDR_CMAP_0 << REX3_DCBMODE_DCBADDR_SHIFT) |
452 (CMAP_DCBCRS_REVISION << REX3_DCBMODE_DCBCRS_SHIFT) |
453 (1 << REX3_DCBMODE_CSWIDTH_SHIFT) |
454 (1 << REX3_DCBMODE_CSHOLD_SHIFT) |
455 (1 << REX3_DCBMODE_CSSETUP_SHIFT));
456
457 scratch = vc2_read_ireg(dc, VC2_IREG_CONFIG);
458 dc->dc_vc2rev = (scratch & VC2_IREG_CONFIG_REVISION) >> 5;
459
460 scratch = rex3_read(dc, REX3_REG_DCBDATA0);
461
462 dc->dc_boardrev = (scratch >> 28) & 0x07;
463 dc->dc_cmaprev = scratch & 0x07;
464 dc->dc_xmaprev = xmap9_read(dc, XMAP9_DCBCRS_REVISION) & 0x07;
465 dc->dc_depth = ( (dc->dc_boardrev > 1) && (scratch & 0x80)) ? 8 : 24;
466
467 /* Setup cursor glyph */
468 curp = vc2_read_ireg(dc, VC2_IREG_CURSOR_ENTRY);
469
470 /* Setup VC2 to a known state */
471 tmp = vc2_read_ireg(dc, VC2_IREG_CONTROL) & VC2_CONTROL_INTERLACE;
472 vc2_write_ireg(dc, VC2_IREG_CONTROL, tmp |
473 VC2_CONTROL_DISPLAY_ENABLE |
474 VC2_CONTROL_VTIMING_ENABLE |
475 VC2_CONTROL_DID_ENABLE |
476 VC2_CONTROL_CURSORFUNC_ENABLE /*|
477 VC2_CONTROL_CURSOR_ENABLE*/);
478
479 /* Setup XMAP9s */
480 xmap9_write(dc, XMAP9_DCBCRS_CONFIG,
481 XMAP9_CONFIG_8BIT_SYSTEM | XMAP9_CONFIG_RGBMAP_CI);
482
483 xmap9_write(dc, XMAP9_DCBCRS_CURSOR_CMAP, 0);
484
485 xmap9_write_mode(dc, 0,
486 XMAP9_MODE_GAMMA_BYPASS |
487 XMAP9_MODE_PIXSIZE_8BPP);
488 xmap9_write(dc, XMAP9_DCBCRS_MODE_SELECT, 0);
489
490 /* Setup REX3 */
491 rex3_write(dc, REX3_REG_XYWIN, (4096 << 16) | 4096);
492 rex3_write(dc, REX3_REG_TOPSCAN, 0x3ff); /* XXX Why? XXX */
493
494 /* Setup CMAP */
495 for (i = 0; i < 256; i++)
496 newport_cmap_setrgb(dc, i, rasops_cmap[i * 3],
497 rasops_cmap[i * 3 + 1], rasops_cmap[i * 3 + 2]);
498 }
499
500 /**** Attach routines ****/
501 static int
502 newport_match(device_t parent, struct cfdata *self, void *aux)
503 {
504 struct gio_attach_args *ga = aux;
505
506 /* newport doesn't decode all addresses */
507 if (ga->ga_addr != 0x1f000000 && ga->ga_addr != 0x1f400000 &&
508 ga->ga_addr != 0x1f800000 && ga->ga_addr != 0x1fc00000)
509 return 0;
510
511 /* Don't do the destructive probe if we're already attached */
512 if (newport_is_console && ga->ga_addr == newport_console_dc.dc_addr)
513 return 1;
514
515 if (platform.badaddr(
516 (void *)(ga->ga_ioh + NEWPORT_REX3_OFFSET + REX3_REG_XSTARTI),
517 sizeof(uint32_t)))
518 return 0;
519 if (platform.badaddr(
520 (void *)(ga->ga_ioh + NEWPORT_REX3_OFFSET + REX3_REG_XSTART),
521 sizeof(uint32_t)))
522 return 0;
523
524 /* Ugly, this probe is destructive, blame SGI... */
525 /* XXX Should be bus_space_peek/bus_space_poke XXX */
526 bus_space_write_4(ga->ga_iot, ga->ga_ioh,
527 NEWPORT_REX3_OFFSET + REX3_REG_XSTARTI, 0x12345678);
528 if (bus_space_read_4(ga->ga_iot, ga->ga_ioh,
529 NEWPORT_REX3_OFFSET + REX3_REG_XSTART)
530 != ((0x12345678 & 0xffff) << 11))
531 return 0;
532
533 return 1;
534 }
535
536 static void
537 newport_attach_common(struct newport_devconfig *dc, struct gio_attach_args *ga)
538 {
539 dc->dc_addr = ga->ga_addr;
540
541 dc->dc_st = ga->ga_iot;
542 dc->dc_sh = ga->ga_ioh;
543
544 wsfont_init();
545
546 dc->dc_font = wsfont_find(NULL, 8, 16, 0, WSDISPLAY_FONTORDER_L2R,
547 WSDISPLAY_FONTORDER_L2R);
548 if (dc->dc_font < 0)
549 panic("newport_attach_common: no suitable fonts");
550
551 if (wsfont_lock(dc->dc_font, &dc->dc_fontdata))
552 panic("newport_attach_common: unable to lock font data");
553
554 newport_setup_hw(dc);
555
556 newport_get_resolution(dc);
557
558 newport_fill_rectangle(dc, 0, 0, dc->dc_xres, dc->dc_yres, 0);
559 if (dc->dc_xres == 1280) {
560 dc->dc_screen = &newport_screen_1280x1024;
561 } else
562 dc->dc_screen = &newport_screen_1024x768;
563
564 }
565
566 static void
567 newport_attach(device_t parent, device_t self, void *aux)
568 {
569 struct gio_attach_args *ga = aux;
570 struct newport_softc *sc = device_private(self);
571 struct wsemuldisplaydev_attach_args wa;
572 unsigned long defattr;
573
574 sc->sc_dev = self;
575 if (newport_is_console && ga->ga_addr == newport_console_dc.dc_addr) {
576 wa.console = 1;
577 sc->sc_dc = &newport_console_dc;
578 } else {
579 wa.console = 0;
580 sc->sc_dc = malloc(sizeof(struct newport_devconfig),
581 M_DEVBUF, M_WAITOK | M_ZERO);
582 if (sc->sc_dc == NULL)
583 panic("newport_attach: out of memory");
584
585 newport_attach_common(sc->sc_dc, ga);
586 }
587
588 aprint_naive(": Display adapter\n");
589
590 aprint_normal(": SGI NG1 (board revision %d, cmap revision %d, xmap revision %d, vc2 revision %d), depth %d\n",
591 sc->sc_dc->dc_boardrev, sc->sc_dc->dc_cmaprev,
592 sc->sc_dc->dc_xmaprev, sc->sc_dc->dc_vc2rev, sc->sc_dc->dc_depth);
593 vcons_init(&sc->sc_dc->dc_vd, sc->sc_dc, sc->sc_dc->dc_screen,
594 &newport_accessops);
595 sc->sc_dc->dc_vd.init_screen = newport_init_screen;
596 if (newport_is_console) {
597 newport_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
598 vcons_init_screen(&sc->sc_dc->dc_vd, &newport_console_screen,
599 1, &defattr);
600 sc->sc_dc->dc_screen->textops =
601 &newport_console_screen.scr_ri.ri_ops;
602 memcpy(&newport_textops, &newport_console_screen.scr_ri.ri_ops,
603 sizeof(struct wsdisplay_emulops));
604 }
605 wa.scrdata = &newport_screenlist;
606 wa.accessops = &newport_accessops;
607 wa.accesscookie = &sc->sc_dc->dc_vd;
608
609 config_found(sc->sc_dev, &wa, wsemuldisplaydevprint);
610 }
611
612 int
613 newport_cnattach(struct gio_attach_args *ga)
614 {
615 struct rasops_info *ri = &newport_console_screen.scr_ri;
616 long defattr = NEWPORT_ATTR_ENCODE(WSCOL_WHITE, WSCOL_BLACK);
617 const struct wsscreen_descr *screen;
618
619 if (!newport_match(NULL, NULL, ga)) {
620 return ENXIO;
621 }
622
623 newport_attach_common(&newport_console_dc, ga);
624
625 if (newport_console_dc.dc_xres >= 1280 &&
626 newport_console_dc.dc_yres >= 1024)
627 screen = &newport_screen_1280x1024;
628 else
629 screen = &newport_screen_1024x768;
630
631 ri->ri_hw = &newport_console_screen;
632 ri->ri_depth = newport_console_dc.dc_depth;
633 ri->ri_width = newport_console_dc.dc_xres;
634 ri->ri_height = newport_console_dc.dc_yres;
635 ri->ri_stride = newport_console_dc.dc_xres; /* XXX */
636 ri->ri_flg = RI_CENTER | RI_FULLCLEAR;
637 ri->ri_ops.copyrows = newport_copyrows;
638 ri->ri_ops.eraserows = newport_eraserows;
639 ri->ri_ops.copycols = newport_copycols;
640 ri->ri_ops.erasecols = newport_erasecols;
641 ri->ri_ops.cursor = newport_cursor_dummy;
642 ri->ri_ops.mapchar = newport_mapchar;
643 ri->ri_ops.putchar = newport_putchar;
644 ri->ri_ops.allocattr = newport_allocattr;
645 ri->ri_font = newport_console_dc.dc_fontdata;
646 newport_console_screen.scr_cookie = &newport_console_dc;
647
648 newport_putchar(ri, 3, 3, 0x41, defattr);
649 wsdisplay_cnattach(screen, ri, 0, 0, defattr);
650 newport_putchar(ri, 4, 3, 0x42, defattr);
651
652 newport_is_console = 1;
653
654 return 0;
655 }
656
657 static void
658 newport_init_screen(void *cookie, struct vcons_screen *scr,
659 int existing, long *defattr)
660 {
661 struct newport_devconfig *dc = cookie;
662 struct rasops_info *ri = &scr->scr_ri;
663
664 ri->ri_depth = dc->dc_depth;
665 ri->ri_width = dc->dc_xres;
666 ri->ri_height = dc->dc_yres;
667 ri->ri_stride = dc->dc_xres; /* XXX */
668 ri->ri_flg = RI_CENTER;
669
670 /*&ri->ri_bits = (char *)sc->sc_fb.fb_pixels;*/
671
672 rasops_init(ri, dc->dc_yres / 8, dc->dc_xres / 8);
673 ri->ri_caps = WSSCREEN_WSCOLORS;
674
675 rasops_reconfig(ri, dc->dc_yres / ri->ri_font->fontheight,
676 dc->dc_xres / ri->ri_font->fontwidth);
677
678 ri->ri_hw = scr;
679 ri->ri_ops.copyrows = newport_copyrows;
680 ri->ri_ops.eraserows = newport_eraserows;
681 ri->ri_ops.copycols = newport_copycols;
682 ri->ri_ops.erasecols = newport_erasecols;
683 ri->ri_ops.cursor = newport_cursor;
684 ri->ri_ops.mapchar = newport_mapchar;
685 ri->ri_ops.putchar = newport_putchar;
686 ri->ri_ops.allocattr = newport_allocattr;
687 }
688
689 /**** wsdisplay textops ****/
690 static void
691 newport_cursor_dummy(void *c, int on, int row, int col)
692 {
693 }
694
695 static void
696 newport_cursor(void *c, int on, int row, int col)
697 {
698 struct rasops_info *ri = c;
699 struct vcons_screen *scr = ri->ri_hw;
700 struct newport_devconfig *dc = scr->scr_cookie;
701 int x, y, wi,he;
702
703 wi = ri->ri_font->fontwidth;
704 he = ri->ri_font->fontheight;
705
706 if (ri->ri_flg & RI_CURSOR) {
707 x = ri->ri_ccol * wi + ri->ri_xorigin;
708 y = ri->ri_crow * he + ri->ri_yorigin;
709 newport_bitblt(dc, x, y, x, y, wi, he, 12);
710 ri->ri_flg &= ~RI_CURSOR;
711 }
712
713 ri->ri_crow = row;
714 ri->ri_ccol = col;
715
716 if (on)
717 {
718 x = ri->ri_ccol * wi + ri->ri_xorigin;
719 y = ri->ri_crow * he + ri->ri_yorigin;
720 newport_bitblt(dc, x, y, x, y, wi, he, 12);
721 ri->ri_flg |= RI_CURSOR;
722 }
723 }
724
725 static int
726 newport_mapchar(void *c, int ch, unsigned int *cp)
727 {
728 struct rasops_info *ri = c;
729 struct vcons_screen *scr = ri->ri_hw;
730 struct newport_devconfig *dc = scr->scr_cookie;
731
732 if (dc->dc_fontdata->encoding != WSDISPLAY_FONTENC_ISO) {
733 ch = wsfont_map_unichar(dc->dc_fontdata, ch);
734
735 if (ch < 0)
736 goto fail;
737 }
738
739 if (ch < dc->dc_fontdata->firstchar ||
740 ch >= dc->dc_fontdata->firstchar + dc->dc_fontdata->numchars)
741 goto fail;
742
743 *cp = ch;
744 return 5;
745
746 fail:
747 *cp = ' ';
748 return 0;
749 }
750
751 static void
752 newport_putchar(void *c, int row, int col, u_int ch, long attr)
753 {
754 struct rasops_info *ri = c;
755 struct vcons_screen *scr = ri->ri_hw;
756 struct newport_devconfig *dc = scr->scr_cookie;
757 struct wsdisplay_font *font = ri->ri_font;
758 uint8_t *bitmap = (u_int8_t *)font->data + (ch - font->firstchar) *
759 font->fontheight * font->stride;
760 uint32_t pattern;
761 int i;
762 int x = col * font->fontwidth + ri->ri_xorigin;
763 int y = row * font->fontheight + ri->ri_yorigin;
764
765 rex3_wait_gfifo(dc);
766
767 rex3_write(dc, REX3_REG_DRAWMODE0, REX3_DRAWMODE0_OPCODE_DRAW |
768 REX3_DRAWMODE0_ADRMODE_BLOCK | REX3_DRAWMODE0_STOPONX |
769 REX3_DRAWMODE0_ENZPATTERN | REX3_DRAWMODE0_ZPOPAQUE);
770
771 rex3_write(dc, REX3_REG_DRAWMODE1,
772 REX3_DRAWMODE1_PLANES_CI |
773 REX3_DRAWMODE1_DD_DD8 |
774 REX3_DRAWMODE1_RWPACKED |
775 REX3_DRAWMODE1_HD_HD8 |
776 REX3_DRAWMODE1_COMPARE_LT |
777 REX3_DRAWMODE1_COMPARE_EQ |
778 REX3_DRAWMODE1_COMPARE_GT |
779 REX3_DRAWMODE1_LO_SRC);
780
781 rex3_write(dc, REX3_REG_XYSTARTI, (x << REX3_XYSTARTI_XSHIFT) | y);
782 rex3_write(dc, REX3_REG_XYENDI,
783 (x + font->fontwidth - 1) << REX3_XYENDI_XSHIFT);
784
785 rex3_write(dc, REX3_REG_COLORI, NEWPORT_ATTR_FG(attr));
786 rex3_write(dc, REX3_REG_COLORBACK, NEWPORT_ATTR_BG(attr));
787
788 rex3_write(dc, REX3_REG_WRMASK, 0xffffffff);
789
790 for (i = 0; i < font->fontheight; i++) {
791 /* XXX Works only with font->fontwidth == 8 XXX */
792 pattern = *bitmap << 24;
793
794 rex3_write_go(dc, REX3_REG_ZPATTERN, pattern);
795
796 bitmap += font->stride;
797 }
798 }
799
800 static void
801 newport_copycols(void *c, int row, int srccol, int dstcol, int ncols)
802 {
803 struct rasops_info *ri = c;
804 struct vcons_screen *scr = ri->ri_hw;
805 struct newport_devconfig *dc = scr->scr_cookie;
806 int32_t xs, xd, y, width, height;
807
808 xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol;
809 xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol;
810 y = ri->ri_yorigin + ri->ri_font->fontheight * row;
811 width = ri->ri_font->fontwidth * ncols;
812 height = ri->ri_font->fontheight;
813 newport_bitblt(dc, xs, y, xd, y, width, height, 3);
814 }
815
816 static void
817 newport_erasecols(void *c, int row, int startcol, int ncols,
818 long attr)
819 {
820 struct rasops_info *ri = c;
821 struct vcons_screen *scr = ri->ri_hw;
822 struct newport_devconfig *dc = scr->scr_cookie;
823 struct wsdisplay_font *font = dc->dc_fontdata;
824
825 newport_fill_rectangle(dc,
826 startcol * font->fontwidth, /* x1 */
827 row * font->fontheight, /* y1 */
828 (startcol + ncols) * font->fontwidth - 1, /* x2 */
829 (row + 1) * font->fontheight - 1, /* y2 */
830 NEWPORT_ATTR_BG(attr));
831 }
832
833 static void
834 newport_copyrows(void *c, int srcrow, int dstrow, int nrows)
835 {
836 struct rasops_info *ri = c;
837 struct vcons_screen *scr = ri->ri_hw;
838 struct newport_devconfig *dc = scr->scr_cookie;
839 int32_t x, ys, yd, width, height;
840
841 x = ri->ri_xorigin;
842 ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow;
843 yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow;
844 width = ri->ri_emuwidth;
845 height = ri->ri_font->fontheight * nrows;
846
847 newport_bitblt(dc, x, ys, x, yd, width, height, 3);
848 }
849
850 static void
851 newport_eraserows(void *c, int startrow, int nrows, long attr)
852 {
853 struct rasops_info *ri = c;
854 struct vcons_screen *scr = ri->ri_hw;
855 struct newport_devconfig *dc = scr->scr_cookie;
856 struct wsdisplay_font *font = dc->dc_fontdata;
857
858 newport_fill_rectangle(dc,
859 0, /* x1 */
860 startrow * font->fontheight, /* y1 */
861 dc->dc_xres, /* x2 */
862 (startrow + nrows) * font->fontheight - 1, /* y2 */
863 NEWPORT_ATTR_BG(attr));
864 }
865
866 static int
867 newport_allocattr(void *c, int fg, int bg, int flags, long *attr)
868 {
869 if (flags & WSATTR_BLINK)
870 return EINVAL;
871
872 if ((flags & WSATTR_WSCOLORS) == 0) {
873 fg = WSCOL_WHITE;
874 bg = WSCOL_BLACK;
875 }
876
877 if (flags & WSATTR_HILIT)
878 fg += 8;
879
880 if (flags & WSATTR_REVERSE) {
881 int tmp = fg;
882 fg = bg;
883 bg = tmp;
884 }
885
886 *attr = NEWPORT_ATTR_ENCODE(fg, bg);
887
888 return 0;
889 }
890
891 /**** wsdisplay accessops ****/
892
893 static int
894 newport_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
895 struct lwp *l)
896 {
897 struct vcons_data *vd;
898 struct newport_devconfig *dc;
899 struct vcons_screen *ms;
900 #if 0
901 struct wsdisplay_fbinfo *wdf;
902 int nmode;
903 #endif
904 vd = (struct vcons_data *)v;
905 dc = (struct newport_devconfig *)vd->cookie;
906 ms = (struct vcons_screen *)vd->active;
907
908 #define FBINFO (*(struct wsdisplay_fbinfo*)data)
909
910 switch (cmd) {
911 case WSDISPLAYIO_GINFO:
912 FBINFO.width = dc->dc_xres;
913 FBINFO.height = dc->dc_yres;
914 FBINFO.depth = dc->dc_depth;
915 FBINFO.cmsize = 1 << FBINFO.depth;
916 return 0;
917 case WSDISPLAYIO_GTYPE:
918 *(u_int *)data = WSDISPLAY_TYPE_NEWPORT;
919 return 0;
920 }
921 return EPASSTHROUGH;
922 }
923
924 static paddr_t
925 newport_mmap(void *v, void *vs, off_t offset, int prot)
926 {
927 struct vcons_data *vd;
928 struct newport_devconfig *dc;
929
930 vd = (struct vcons_data *)v;
931 dc = (struct newport_devconfig *)vd->cookie;
932
933 if ( offset >= 0xfffff)
934 return -1;
935
936 return mips_btop(dc->dc_addr + offset);
937 }
938