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