gftfb.c revision 1.5 1 /* $NetBSD: gftfb.c,v 1.5 2024/02/21 13:04:01 macallan Exp $ */
2
3 /* $OpenBSD: sti_pci.c,v 1.7 2009/02/06 22:51:04 miod Exp $ */
4
5 /*
6 * Copyright (c) 2006, 2007 Miodrag Vallat.
7 *
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice, this permission notice, and the disclaimer below
11 * appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 */
21
22 #include <sys/param.h>
23 #include <sys/systm.h>
24 #include <sys/kmem.h>
25 #include <sys/device.h>
26
27 #include <dev/pci/pcivar.h>
28 #include <dev/pci/pcireg.h>
29 #include <dev/pci/pcidevs.h>
30 #include <dev/pci/pciio.h>
31
32 #include <dev/wscons/wsdisplayvar.h>
33 #include <dev/wscons/wsconsio.h>
34 #include <dev/wsfont/wsfont.h>
35 #include <dev/rasops/rasops.h>
36 #include <dev/wscons/wsdisplay_vconsvar.h>
37 #include <dev/pci/wsdisplay_pci.h>
38 #include <dev/wscons/wsdisplay_glyphcachevar.h>
39
40 #include <dev/ic/stireg.h>
41 #include <dev/ic/stivar.h>
42
43 #ifdef STIDEBUG
44 #define DPRINTF(s) do { \
45 if (stidebug) \
46 printf s; \
47 } while(0)
48
49 extern int stidebug;
50 #else
51 #define DPRINTF(s) /* */
52 #endif
53
54 int gftfb_match(device_t, cfdata_t, void *);
55 void gftfb_attach(device_t, device_t, void *);
56
57 struct gftfb_softc {
58 device_t sc_dev;
59 pci_chipset_tag_t sc_pc;
60 pcitag_t sc_tag;
61
62 /* stuff we need in order to use the STI ROM */
63 struct sti_softc sc_base;
64 struct sti_screen sc_scr;
65 bus_space_handle_t sc_romh;
66
67 int sc_width, sc_height;
68 int sc_locked;
69 struct vcons_screen sc_console_screen;
70 struct wsscreen_descr sc_defaultscreen_descr;
71 const struct wsscreen_descr *sc_screens[1];
72 struct wsscreen_list sc_screenlist;
73 struct vcons_data vd;
74 int sc_mode;
75 void (*sc_putchar)(void *, int, int, u_int, long);
76 u_char sc_cmap_red[256];
77 u_char sc_cmap_green[256];
78 u_char sc_cmap_blue[256];
79 uint32_t sc_hwmode;
80 #define HW_FB 0
81 #define HW_FILL 1
82 #define HW_BLIT 2
83 glyphcache sc_gc;
84 };
85
86 CFATTACH_DECL_NEW(gftfb, sizeof(struct gftfb_softc),
87 gftfb_match, gftfb_attach, NULL, NULL);
88
89 int gftfb_readbar(struct sti_softc *, struct pci_attach_args *, u_int, int);
90 int gftfb_check_rom(struct gftfb_softc *, struct pci_attach_args *);
91 void gftfb_enable_rom(struct sti_softc *);
92 void gftfb_disable_rom(struct sti_softc *);
93 void gftfb_enable_rom_internal(struct gftfb_softc *);
94 void gftfb_disable_rom_internal(struct gftfb_softc *);
95
96 void gftfb_setup(struct gftfb_softc *);
97
98 #define ngle_bt458_write(memt, memh, r, v) \
99 bus_space_write_stream_4(memt, memh, NGLE_REG_RAMDAC + ((r) << 2), (v) << 24)
100
101
102 /* XXX these really need to go into their own header */
103 int sti_pci_is_console(struct pci_attach_args *, bus_addr_t *);
104 int sti_rom_setup(struct sti_rom *, bus_space_tag_t, bus_space_tag_t,
105 bus_space_handle_t, bus_addr_t *, u_int);
106 int sti_screen_setup(struct sti_screen *, int);
107 void sti_describe_screen(struct sti_softc *, struct sti_screen *);
108
109 #define PCI_ROM_SIZE(mr) \
110 (PCI_MAPREG_ROM_ADDR(mr) & -PCI_MAPREG_ROM_ADDR(mr))
111
112 /* wsdisplay stuff */
113 static int gftfb_ioctl(void *, void *, u_long, void *, int,
114 struct lwp *);
115 static paddr_t gftfb_mmap(void *, void *, off_t, int);
116 static void gftfb_init_screen(void *, struct vcons_screen *, int, long *);
117
118 static int gftfb_putcmap(struct gftfb_softc *, struct wsdisplay_cmap *);
119 static int gftfb_getcmap(struct gftfb_softc *, struct wsdisplay_cmap *);
120 static void gftfb_restore_palette(struct gftfb_softc *);
121 static int gftfb_putpalreg(struct gftfb_softc *, uint8_t, uint8_t,
122 uint8_t, uint8_t);
123
124 static void gftfb_rectfill(struct gftfb_softc *, int, int, int, int,
125 uint32_t);
126 static void gftfb_bitblt(void *, int, int, int, int, int,
127 int, int);
128
129 static void gftfb_cursor(void *, int, int, int);
130 static void gftfb_putchar(void *, int, int, u_int, long);
131 static void gftfb_copycols(void *, int, int, int, int);
132 static void gftfb_erasecols(void *, int, int, int, long);
133 static void gftfb_copyrows(void *, int, int, int);
134 static void gftfb_eraserows(void *, int, int, long);
135
136 struct wsdisplay_accessops gftfb_accessops = {
137 gftfb_ioctl,
138 gftfb_mmap,
139 NULL, /* alloc_screen */
140 NULL, /* free_screen */
141 NULL, /* show_screen */
142 NULL, /* load_font */
143 NULL, /* pollc */
144 NULL /* scroll */
145 };
146
147 #define BA(F,C,S,A,J,B,I) \
148 (((F)<<31)|((C)<<27)|((S)<<24)|((A)<<21)|((J)<<16)|((B)<<12)|(I))
149
150 #define IBOvals(R,M,X,S,D,L,B,F) \
151 (((R)<<8)|((M)<<16)|((X)<<24)|((S)<<29)|((D)<<28)|((L)<<31)|((B)<<1)|(F))
152
153 #define IndexedDcd 0 /* Pixel data is indexed (pseudo) color */
154 #define Otc04 2 /* Pixels in each longword transfer (4) */
155 #define Otc32 5 /* Pixels in each longword transfer (32) */
156 #define Ots08 3 /* Each pixel is size (8)d transfer (1) */
157 #define OtsIndirect 6 /* Each bit goes through FG/BG color(8) */
158 #define AddrLong 5 /* FB address is Long aligned (pixel) */
159 #define BINovly 0x2 /* 8 bit overlay */
160 #define BINapp0I 0x0 /* Application Buffer 0, Indexed */
161 #define BINapp1I 0x1 /* Application Buffer 1, Indexed */
162 #define BINapp0F8 0xa /* Application Buffer 0, Fractional 8-8-8 */
163 #define BINattr 0xd /* Attribute Bitmap */
164 #define RopSrc 0x3
165 #define RopInv 0xc
166 #define BitmapExtent08 3 /* Each write hits ( 8) bits in depth */
167 #define BitmapExtent32 5 /* Each write hits (32) bits in depth */
168 #define DataDynamic 0 /* Data register reloaded by direct access */
169 #define MaskDynamic 1 /* Mask register reloaded by direct access */
170 #define MaskOtc 0 /* Mask contains Object Count valid bits */
171
172 int
173 gftfb_match(device_t parent, cfdata_t cf, void *aux)
174 {
175 struct pci_attach_args *paa = aux;
176
177 if (PCI_VENDOR(paa->pa_id) != PCI_VENDOR_HP)
178 return 0;
179
180 if (PCI_PRODUCT(paa->pa_id) == PCI_PRODUCT_HP_VISUALIZE_EG)
181 return 10; /* beat out sti at pci */
182
183 return 0;
184 }
185
186 void
187 gftfb_attach(device_t parent, device_t self, void *aux)
188 {
189 struct gftfb_softc *sc = device_private(self);
190 struct pci_attach_args *paa = aux;
191 struct sti_rom *rom;
192 struct rasops_info *ri;
193 struct wsemuldisplaydev_attach_args aa;
194 unsigned long defattr = 0;
195 int ret, is_console = 0, i, j;
196 uint8_t cmap[768];
197
198 sc->sc_dev = self;
199
200 sc->sc_pc = paa->pa_pc;
201 sc->sc_tag = paa->pa_tag;
202 sc->sc_base.sc_dev = self;
203 sc->sc_base.sc_enable_rom = gftfb_enable_rom;
204 sc->sc_base.sc_disable_rom = gftfb_disable_rom;
205
206 aprint_normal("\n");
207
208 if (gftfb_check_rom(sc, paa) != 0)
209 return;
210
211 ret = sti_pci_is_console(paa, sc->sc_base. bases);
212 if (ret != 0) {
213 sc->sc_base.sc_flags |= STI_CONSOLE;
214 is_console = 1;
215 }
216 rom = (struct sti_rom *)kmem_zalloc(sizeof(*rom), KM_SLEEP);
217 rom->rom_softc = &sc->sc_base;
218 ret = sti_rom_setup(rom, paa->pa_iot, paa->pa_memt, sc->sc_romh, sc->sc_base.bases, STI_CODEBASE_MAIN);
219 if (ret != 0) {
220 kmem_free(rom, sizeof(*rom));
221 return;
222 }
223
224 sc->sc_base.sc_rom = rom;
225
226 sc->sc_scr.scr_rom = sc->sc_base.sc_rom;
227 ret = sti_screen_setup(&sc->sc_scr, STI_FBMODE);
228
229 sc->sc_width = sc->sc_scr.scr_cfg.scr_width;
230 sc->sc_height = sc->sc_scr.scr_cfg.scr_height;
231
232 aprint_normal_dev(sc->sc_dev, "%s at %dx%d\n", sc->sc_scr.name,
233 sc->sc_width, sc->sc_height);
234 gftfb_setup(sc);
235
236 sc->sc_defaultscreen_descr = (struct wsscreen_descr){
237 "default",
238 0, 0,
239 NULL,
240 8, 16,
241 WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_UNDERLINE |
242 WSSCREEN_RESIZE,
243 NULL
244 };
245
246 sc->sc_screens[0] = &sc->sc_defaultscreen_descr;
247 sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens};
248 sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
249 sc->sc_locked = 0;
250
251 vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr,
252 &gftfb_accessops);
253 sc->vd.init_screen = gftfb_init_screen;
254 sc->vd.show_screen_cookie = &sc->sc_gc;
255 sc->vd.show_screen_cb = glyphcache_adapt;
256
257 ri = &sc->sc_console_screen.scr_ri;
258
259 sc->sc_gc.gc_bitblt = gftfb_bitblt;
260 sc->sc_gc.gc_blitcookie = sc;
261 sc->sc_gc.gc_rop = RopSrc;
262
263 if (is_console) {
264 vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1,
265 &defattr);
266 sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
267
268 sc->sc_defaultscreen_descr.textops = &ri->ri_ops;
269 sc->sc_defaultscreen_descr.capabilities = ri->ri_caps;
270 sc->sc_defaultscreen_descr.nrows = ri->ri_rows;
271 sc->sc_defaultscreen_descr.ncols = ri->ri_cols;
272
273 glyphcache_init(&sc->sc_gc, sc->sc_height + 5,
274 sc->sc_scr.fbheight - sc->sc_height - 5,
275 sc->sc_width,
276 ri->ri_font->fontwidth,
277 ri->ri_font->fontheight,
278 defattr);
279
280 wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0,
281 defattr);
282
283 gftfb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height,
284 ri->ri_devcmap[(defattr >> 16) & 0xff]);
285
286 vcons_replay_msgbuf(&sc->sc_console_screen);
287 } else {
288 /*
289 * since we're not the console we can postpone the rest
290 * until someone actually allocates a screen for us
291 */
292 if (sc->sc_console_screen.scr_ri.ri_rows == 0) {
293 /* do some minimal setup to avoid weirdnesses later */
294 vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1,
295 &defattr);
296 } else
297 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
298
299 glyphcache_init(&sc->sc_gc, sc->sc_height + 5,
300 sc->sc_scr.fbheight - sc->sc_height - 5,
301 sc->sc_width,
302 ri->ri_font->fontwidth,
303 ri->ri_font->fontheight,
304 defattr);
305 }
306
307 j = 0;
308 rasops_get_cmap(ri, cmap, sizeof(cmap));
309 for (i = 0; i < 256; i++) {
310 sc->sc_cmap_red[i] = cmap[j];
311 sc->sc_cmap_green[i] = cmap[j + 1];
312 sc->sc_cmap_blue[i] = cmap[j + 2];
313 gftfb_putpalreg(sc, i, cmap[j], cmap[j + 1], cmap[j + 2]);
314 j += 3;
315 }
316
317 /* no suspend/resume support yet */
318 if (!pmf_device_register(sc->sc_dev, NULL, NULL))
319 aprint_error_dev(sc->sc_dev,
320 "couldn't establish power handler\n");
321
322 aa.console = is_console;
323 aa.scrdata = &sc->sc_screenlist;
324 aa.accessops = &gftfb_accessops;
325 aa.accesscookie = &sc->vd;
326
327 config_found(sc->sc_dev, &aa, wsemuldisplaydevprint, CFARGS_NONE);
328 }
329
330 /*
331 * Grovel the STI ROM image.
332 */
333 int
334 gftfb_check_rom(struct gftfb_softc *spc, struct pci_attach_args *pa)
335 {
336 struct sti_softc *sc = &spc->sc_base;
337 pcireg_t address, mask;
338 bus_space_handle_t romh;
339 bus_size_t romsize, subsize, stiromsize;
340 bus_addr_t selected, offs, suboffs;
341 uint32_t tmp;
342 int i;
343 int rc;
344
345 /* sort of inline sti_pci_enable_rom(sc) */
346 address = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM);
347 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM,
348 ~PCI_MAPREG_ROM_ENABLE);
349 mask = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM);
350 address |= PCI_MAPREG_ROM_ENABLE;
351 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM, address);
352 sc->sc_flags |= STI_ROM_ENABLED;
353 /*
354 * Map the complete ROM for now.
355 */
356
357 romsize = PCI_ROM_SIZE(mask);
358 DPRINTF(("%s: mapping rom @ %lx for %lx\n", __func__,
359 (long)PCI_MAPREG_ROM_ADDR(address), (long)romsize));
360
361 rc = bus_space_map(pa->pa_memt, PCI_MAPREG_ROM_ADDR(address), romsize,
362 0, &romh);
363 if (rc != 0) {
364 aprint_error_dev(sc->sc_dev, "can't map PCI ROM (%d)\n", rc);
365 goto fail2;
366 }
367
368 gftfb_disable_rom_internal(spc);
369 /*
370 * Iterate over the ROM images, pick the best candidate.
371 */
372
373 selected = (bus_addr_t)-1;
374 for (offs = 0; offs < romsize; offs += subsize) {
375 gftfb_enable_rom_internal(spc);
376 /*
377 * Check for a valid ROM header.
378 */
379 tmp = bus_space_read_4(pa->pa_memt, romh, offs + 0);
380 tmp = le32toh(tmp);
381 if (tmp != 0x55aa0000) {
382 gftfb_disable_rom_internal(spc);
383 if (offs == 0) {
384 aprint_error_dev(sc->sc_dev,
385 "invalid PCI ROM header signature (%08x)\n",
386 tmp);
387 rc = EINVAL;
388 }
389 break;
390 }
391
392 /*
393 * Check ROM type.
394 */
395 tmp = bus_space_read_4(pa->pa_memt, romh, offs + 4);
396 tmp = le32toh(tmp);
397 if (tmp != 0x00000001) { /* 1 == STI ROM */
398 gftfb_disable_rom_internal(spc);
399 if (offs == 0) {
400 aprint_error_dev(sc->sc_dev,
401 "invalid PCI ROM type (%08x)\n", tmp);
402 rc = EINVAL;
403 }
404 break;
405 }
406
407 subsize = (bus_addr_t)bus_space_read_2(pa->pa_memt, romh,
408 offs + 0x0c);
409 subsize <<= 9;
410
411 #ifdef STIDEBUG
412 gftfb_disable_rom_internal(spc);
413 DPRINTF(("ROM offset %08x size %08x type %08x",
414 (u_int)offs, (u_int)subsize, tmp));
415 gftfb_enable_rom_internal(spc);
416 #endif
417
418 /*
419 * Check for a valid ROM data structure.
420 * We do not need it except to know what architecture the ROM
421 * code is for.
422 */
423
424 suboffs = offs +(bus_addr_t)bus_space_read_2(pa->pa_memt, romh,
425 offs + 0x18);
426 tmp = bus_space_read_4(pa->pa_memt, romh, suboffs + 0);
427 tmp = le32toh(tmp);
428 if (tmp != 0x50434952) { /* PCIR */
429 gftfb_disable_rom_internal(spc);
430 if (offs == 0) {
431 aprint_error_dev(sc->sc_dev, "invalid PCI data"
432 " signature (%08x)\n", tmp);
433 rc = EINVAL;
434 } else {
435 DPRINTF((" invalid PCI data signature %08x\n",
436 tmp));
437 continue;
438 }
439 }
440
441 tmp = bus_space_read_1(pa->pa_memt, romh, suboffs + 0x14);
442 gftfb_disable_rom_internal(spc);
443 DPRINTF((" code %02x", tmp));
444
445 switch (tmp) {
446 #ifdef __hppa__
447 case 0x10:
448 if (selected == (bus_addr_t)-1)
449 selected = offs;
450 break;
451 #endif
452 #ifdef __i386__
453 case 0x00:
454 if (selected == (bus_addr_t)-1)
455 selected = offs;
456 break;
457 #endif
458 default:
459 #ifdef STIDEBUG
460 DPRINTF((" (wrong architecture)"));
461 #endif
462 break;
463 }
464 DPRINTF(("%s\n", selected == offs ? " -> SELECTED" : ""));
465 }
466
467 if (selected == (bus_addr_t)-1) {
468 if (rc == 0) {
469 aprint_error_dev(sc->sc_dev, "found no ROM with "
470 "correct microcode architecture\n");
471 rc = ENOEXEC;
472 }
473 goto fail;
474 }
475
476 /*
477 * Read the STI region BAR assignments.
478 */
479
480 gftfb_enable_rom_internal(spc);
481 offs = selected +
482 (bus_addr_t)bus_space_read_2(pa->pa_memt, romh, selected + 0x0e);
483 for (i = 0; i < STI_REGION_MAX; i++) {
484 rc = gftfb_readbar(sc, pa, i,
485 bus_space_read_1(pa->pa_memt, romh, offs + i));
486 if (rc != 0)
487 goto fail;
488 }
489
490 /*
491 * Find out where the STI ROM itself lies, and its size.
492 */
493
494 offs = selected +
495 (bus_addr_t)bus_space_read_4(pa->pa_memt, romh, selected + 0x08);
496 stiromsize = (bus_addr_t)bus_space_read_4(pa->pa_memt, romh,
497 offs + 0x18);
498 stiromsize = le32toh(stiromsize);
499 gftfb_disable_rom_internal(spc);
500
501 /*
502 * Replace our mapping with a smaller mapping of only the area
503 * we are interested in.
504 */
505
506 DPRINTF(("remapping rom @ %lx for %lx\n",
507 (long)(PCI_MAPREG_ROM_ADDR(address) + offs), (long)stiromsize));
508 bus_space_unmap(pa->pa_memt, romh, romsize);
509 rc = bus_space_map(pa->pa_memt, PCI_MAPREG_ROM_ADDR(address) + offs,
510 stiromsize, 0, &spc->sc_romh);
511 if (rc != 0) {
512 aprint_error_dev(sc->sc_dev, "can't map STI ROM (%d)\n",
513 rc);
514 goto fail2;
515 }
516 gftfb_disable_rom_internal(spc);
517 sc->sc_flags &= ~STI_ROM_ENABLED;
518
519 return 0;
520
521 fail:
522 bus_space_unmap(pa->pa_memt, romh, romsize);
523 fail2:
524 gftfb_disable_rom_internal(spc);
525
526 return rc;
527 }
528
529 /*
530 * Decode a BAR register.
531 */
532 int
533 gftfb_readbar(struct sti_softc *sc, struct pci_attach_args *pa, u_int region,
534 int bar)
535 {
536 bus_addr_t addr;
537 bus_size_t size;
538 uint32_t cf;
539 int rc;
540
541 if (bar == 0) {
542 sc->bases[region] = 0;
543 return (0);
544 }
545
546 #ifdef DIAGNOSTIC
547 if (bar < PCI_MAPREG_START || bar > PCI_MAPREG_PPB_END) {
548 gftfb_disable_rom(sc);
549 printf("%s: unexpected bar %02x for region %d\n",
550 device_xname(sc->sc_dev), bar, region);
551 gftfb_enable_rom(sc);
552 }
553 #endif
554
555 cf = pci_conf_read(pa->pa_pc, pa->pa_tag, bar);
556
557 rc = pci_mapreg_info(pa->pa_pc, pa->pa_tag, bar, PCI_MAPREG_TYPE(cf),
558 &addr, &size, NULL);
559
560 if (rc != 0) {
561 gftfb_disable_rom(sc);
562 aprint_error_dev(sc->sc_dev, "invalid bar %02x for region %d\n",
563 bar, region);
564 gftfb_enable_rom(sc);
565 return (rc);
566 }
567
568 sc->bases[region] = addr;
569 return (0);
570 }
571
572 /*
573 * Enable PCI ROM.
574 */
575 void
576 gftfb_enable_rom_internal(struct gftfb_softc *spc)
577 {
578 pcireg_t address;
579
580 KASSERT(spc != NULL);
581
582 address = pci_conf_read(spc->sc_pc, spc->sc_tag, PCI_MAPREG_ROM);
583 address |= PCI_MAPREG_ROM_ENABLE;
584 pci_conf_write(spc->sc_pc, spc->sc_tag, PCI_MAPREG_ROM, address);
585 }
586
587 void
588 gftfb_enable_rom(struct sti_softc *sc)
589 {
590 struct gftfb_softc *spc = device_private(sc->sc_dev);
591
592 if (!ISSET(sc->sc_flags, STI_ROM_ENABLED)) {
593 gftfb_enable_rom_internal(spc);
594 }
595 SET(sc->sc_flags, STI_ROM_ENABLED);
596 }
597
598 /*
599 * Disable PCI ROM.
600 */
601 void
602 gftfb_disable_rom_internal(struct gftfb_softc *spc)
603 {
604 pcireg_t address;
605
606 KASSERT(spc != NULL);
607
608 address = pci_conf_read(spc->sc_pc, spc->sc_tag, PCI_MAPREG_ROM);
609 address &= ~PCI_MAPREG_ROM_ENABLE;
610 pci_conf_write(spc->sc_pc, spc->sc_tag, PCI_MAPREG_ROM, address);
611 }
612
613 void
614 gftfb_disable_rom(struct sti_softc *sc)
615 {
616 struct gftfb_softc *spc = device_private(sc->sc_dev);
617
618 if (ISSET(sc->sc_flags, STI_ROM_ENABLED)) {
619 gftfb_disable_rom_internal(spc);
620 }
621 CLR(sc->sc_flags, STI_ROM_ENABLED);
622 }
623
624 static inline void
625 gftfb_wait(struct gftfb_softc *sc)
626 {
627 struct sti_rom *rom = sc->sc_base.sc_rom;
628 bus_space_tag_t memt = rom->memt;
629 bus_space_handle_t memh = rom->regh[2];
630 uint8_t stat;
631
632 do {
633 stat = bus_space_read_1(memt, memh, NGLE_REG_15b0);
634 if (stat == 0)
635 stat = bus_space_read_1(memt, memh, NGLE_REG_15b0);
636 } while (stat != 0);
637 }
638
639 static inline void
640 gftfb_setup_fb(struct gftfb_softc *sc)
641 {
642 struct sti_rom *rom = sc->sc_base.sc_rom;
643 bus_space_tag_t memt = rom->memt;
644 bus_space_handle_t memh = rom->regh[2];
645
646 gftfb_wait(sc);
647 bus_space_write_stream_4(memt, memh, NGLE_REG_10, 0x13601000);
648 bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x83000300);
649 gftfb_wait(sc);
650 bus_space_write_1(memt, memh, NGLE_REG_16b1, 1);
651 sc->sc_hwmode = HW_FB;
652 }
653
654 void
655 gftfb_setup(struct gftfb_softc *sc)
656 {
657 struct sti_rom *rom = sc->sc_base.sc_rom;
658 bus_space_tag_t memt = rom->memt;
659 bus_space_handle_t memh = rom->regh[2];
660
661 sc->sc_hwmode = HW_FB;
662
663 /* set Bt458 read mask register to all planes */
664 gftfb_wait(sc);
665 ngle_bt458_write(memt, memh, 0x08, 0x04);
666 ngle_bt458_write(memt, memh, 0x0a, 0xff);
667
668 gftfb_setup_fb(sc);
669
670 /* attr. planes */
671 gftfb_wait(sc);
672 bus_space_write_stream_4(memt, memh, NGLE_REG_11, 0x2ea0d000);
673 bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x23000302);
674 bus_space_write_stream_4(memt, memh, NGLE_REG_12, NGLE_ARTIST_CMAP0);
675 bus_space_write_stream_4(memt, memh, NGLE_REG_8, 0xffffffff);
676
677 gftfb_wait(sc);
678 bus_space_write_stream_4(memt, memh, NGLE_REG_6, 0x00000000);
679 bus_space_write_stream_4(memt, memh, NGLE_REG_9,
680 (sc->sc_scr.scr_cfg.scr_width << 16) | sc->sc_scr.scr_cfg.scr_height);
681 /*
682 * blit into offscreen memory to force flush previous - apparently
683 * some chips have a bug this works around
684 */
685 bus_space_write_stream_4(memt, memh, NGLE_REG_6, 0x05000000);
686 bus_space_write_stream_4(memt, memh, NGLE_REG_9, 0x00040001);
687
688 gftfb_wait(sc);
689 bus_space_write_stream_4(memt, memh, NGLE_REG_12, 0x00000000);
690
691 gftfb_setup_fb(sc);
692
693 /* make sure video output is enabled */
694 gftfb_wait(sc);
695 bus_space_write_stream_4(memt, memh, NGLE_REG_21,
696 bus_space_read_stream_4(memt, memh, NGLE_REG_21) | 0x0a000000);
697 bus_space_write_stream_4(memt, memh, NGLE_REG_27,
698 bus_space_read_stream_4(memt, memh, NGLE_REG_27) | 0x00800000);
699 }
700
701 static int
702 gftfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
703 struct lwp *l)
704 {
705 struct vcons_data *vd = v;
706 struct gftfb_softc *sc = vd->cookie;
707 struct wsdisplay_fbinfo *wdf;
708 struct vcons_screen *ms = vd->active;
709
710 switch (cmd) {
711 case WSDISPLAYIO_GTYPE:
712 *(u_int *)data = WSDISPLAY_TYPE_PCIMISC;
713 return 0;
714
715 /* PCI config read/write passthrough. */
716 case PCI_IOC_CFGREAD:
717 case PCI_IOC_CFGWRITE:
718 return pci_devioctl(sc->sc_pc, sc->sc_tag,
719 cmd, data, flag, l);
720
721 case WSDISPLAYIO_GET_BUSID:
722 return wsdisplayio_busid_pci(sc->sc_dev, sc->sc_pc,
723 sc->sc_tag, data);
724
725 case WSDISPLAYIO_GINFO:
726 if (ms == NULL)
727 return ENODEV;
728 wdf = (void *)data;
729 wdf->height = ms->scr_ri.ri_height;
730 wdf->width = ms->scr_ri.ri_width;
731 wdf->depth = ms->scr_ri.ri_depth;
732 wdf->cmsize = 256;
733 return 0;
734
735 case WSDISPLAYIO_GETCMAP:
736 return gftfb_getcmap(sc,
737 (struct wsdisplay_cmap *)data);
738
739 case WSDISPLAYIO_PUTCMAP:
740 return gftfb_putcmap(sc,
741 (struct wsdisplay_cmap *)data);
742
743 case WSDISPLAYIO_LINEBYTES:
744 *(u_int *)data = 2048;
745 return 0;
746
747 case WSDISPLAYIO_SMODE: {
748 int new_mode = *(int*)data;
749 if (new_mode != sc->sc_mode) {
750 sc->sc_mode = new_mode;
751 if(new_mode == WSDISPLAYIO_MODE_EMUL) {
752 gftfb_setup(sc);
753 gftfb_restore_palette(sc);
754 glyphcache_wipe(&sc->sc_gc);
755 gftfb_rectfill(sc, 0, 0, sc->sc_width,
756 sc->sc_height, ms->scr_ri.ri_devcmap[
757 (ms->scr_defattr >> 16) & 0xff]);
758 vcons_redraw_screen(ms);
759 }
760 }
761 }
762 return 0;
763
764 case WSDISPLAYIO_GET_FBINFO:
765 {
766 struct wsdisplayio_fbinfo *fbi = data;
767
768 return wsdisplayio_get_fbinfo(&ms->scr_ri, fbi);
769 }
770 }
771 return EPASSTHROUGH;
772 }
773
774 static paddr_t
775 gftfb_mmap(void *v, void *vs, off_t offset, int prot)
776 {
777 struct vcons_data *vd = v;
778 struct gftfb_softc *sc = vd->cookie;
779 struct sti_rom *rom = sc->sc_base.sc_rom;
780 paddr_t pa;
781
782 if (offset < 0 || offset >= sc->sc_scr.fblen)
783 return -1;
784
785 if (sc->sc_mode != WSDISPLAYIO_MODE_DUMBFB)
786 return -1;
787
788 pa = bus_space_mmap(rom->memt, sc->sc_scr.fbaddr, offset, prot,
789 BUS_SPACE_MAP_LINEAR);
790 return pa;
791 }
792
793 static void
794 gftfb_init_screen(void *cookie, struct vcons_screen *scr,
795 int existing, long *defattr)
796 {
797 struct gftfb_softc *sc = cookie;
798 struct rasops_info *ri = &scr->scr_ri;
799
800 ri->ri_depth = 8;
801 ri->ri_width = sc->sc_width;
802 ri->ri_height = sc->sc_height;
803 ri->ri_stride = 2048;
804 ri->ri_flg = RI_CENTER | RI_8BIT_IS_RGB |
805 RI_ENABLE_ALPHA | RI_PREFER_ALPHA;
806
807 ri->ri_bits = (void *)sc->sc_scr.fbaddr;
808 rasops_init(ri, 0, 0);
809 ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_UNDERLINE |
810 WSSCREEN_RESIZE;
811 scr->scr_flags |= VCONS_LOADFONT;
812
813 rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
814 sc->sc_width / ri->ri_font->fontwidth);
815
816 ri->ri_hw = scr;
817 sc->sc_putchar = ri->ri_ops.putchar;
818 ri->ri_ops.copyrows = gftfb_copyrows;
819 ri->ri_ops.copycols = gftfb_copycols;
820 ri->ri_ops.eraserows = gftfb_eraserows;
821 ri->ri_ops.erasecols = gftfb_erasecols;
822 ri->ri_ops.cursor = gftfb_cursor;
823 ri->ri_ops.putchar = gftfb_putchar;
824 }
825
826 static int
827 gftfb_putcmap(struct gftfb_softc *sc, struct wsdisplay_cmap *cm)
828 {
829 u_char *r, *g, *b;
830 u_int index = cm->index;
831 u_int count = cm->count;
832 int i, error;
833 u_char rbuf[256], gbuf[256], bbuf[256];
834
835 if (cm->index >= 256 || cm->count > 256 ||
836 (cm->index + cm->count) > 256)
837 return EINVAL;
838 error = copyin(cm->red, &rbuf[index], count);
839 if (error)
840 return error;
841 error = copyin(cm->green, &gbuf[index], count);
842 if (error)
843 return error;
844 error = copyin(cm->blue, &bbuf[index], count);
845 if (error)
846 return error;
847
848 memcpy(&sc->sc_cmap_red[index], &rbuf[index], count);
849 memcpy(&sc->sc_cmap_green[index], &gbuf[index], count);
850 memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count);
851
852 r = &sc->sc_cmap_red[index];
853 g = &sc->sc_cmap_green[index];
854 b = &sc->sc_cmap_blue[index];
855
856 for (i = 0; i < count; i++) {
857 gftfb_putpalreg(sc, index, *r, *g, *b);
858 index++;
859 r++, g++, b++;
860 }
861 return 0;
862 }
863
864 static int
865 gftfb_getcmap(struct gftfb_softc *sc, struct wsdisplay_cmap *cm)
866 {
867 u_int index = cm->index;
868 u_int count = cm->count;
869 int error;
870
871 if (index >= 255 || count > 256 || index + count > 256)
872 return EINVAL;
873
874 error = copyout(&sc->sc_cmap_red[index], cm->red, count);
875 if (error)
876 return error;
877 error = copyout(&sc->sc_cmap_green[index], cm->green, count);
878 if (error)
879 return error;
880 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count);
881 if (error)
882 return error;
883
884 return 0;
885 }
886
887 static void
888 gftfb_restore_palette(struct gftfb_softc *sc)
889 {
890 int i;
891
892 for (i = 0; i < 256; i++) {
893 gftfb_putpalreg(sc, i, sc->sc_cmap_red[i],
894 sc->sc_cmap_green[i], sc->sc_cmap_blue[i]);
895 }
896 }
897
898 static int
899 gftfb_putpalreg(struct gftfb_softc *sc, uint8_t idx, uint8_t r, uint8_t g,
900 uint8_t b)
901 {
902 struct sti_rom *rom = sc->sc_base.sc_rom;
903 bus_space_tag_t memt = rom->memt;
904 bus_space_handle_t memh = rom->regh[2];
905
906 gftfb_wait(sc);
907 bus_space_write_stream_4(memt, memh, NGLE_REG_10, 0xbbe0f000);
908 bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x03000300);
909 bus_space_write_stream_4(memt, memh, NGLE_REG_13, 0xffffffff);
910
911 gftfb_wait(sc);
912 bus_space_write_stream_4(memt, memh, NGLE_REG_3,
913 0x400 | (idx << 2));
914 bus_space_write_stream_4(memt, memh, NGLE_REG_4,
915 (r << 16) | (g << 8) | b);
916
917 bus_space_write_stream_4(memt, memh, NGLE_REG_2, 0x400);
918 bus_space_write_stream_4(memt, memh, NGLE_REG_26, 0x80000100);
919 gftfb_setup_fb(sc);
920 return 0;
921 }
922
923 static inline void
924 gftfb_wait_fifo(struct gftfb_softc *sc, uint32_t slots)
925 {
926 struct sti_rom *rom = sc->sc_base.sc_rom;
927 bus_space_tag_t memt = rom->memt;
928 bus_space_handle_t memh = rom->regh[2];
929 uint32_t reg;
930
931 do {
932 reg = bus_space_read_stream_4(memt, memh, NGLE_REG_34);
933 } while (reg < slots);
934 }
935
936 static void
937 gftfb_rectfill(struct gftfb_softc *sc, int x, int y, int wi, int he,
938 uint32_t bg)
939 {
940 struct sti_rom *rom = sc->sc_base.sc_rom;
941 bus_space_tag_t memt = rom->memt;
942 bus_space_handle_t memh = rom->regh[2];
943
944 if (sc->sc_hwmode != HW_FILL) {
945 gftfb_wait_fifo(sc, 4);
946 /* transfer data */
947 bus_space_write_stream_4(memt, memh, NGLE_REG_8, 0xffffffff);
948 /* plane mask */
949 bus_space_write_stream_4(memt, memh, NGLE_REG_13, 0xff);
950 /* bitmap op */
951 bus_space_write_stream_4(memt, memh, NGLE_REG_14,
952 IBOvals(RopSrc, 0, BitmapExtent08, 0, DataDynamic, MaskOtc, 0, 0));
953 /* dst bitmap access */
954 bus_space_write_stream_4(memt, memh, NGLE_REG_11,
955 BA(IndexedDcd, Otc32, OtsIndirect, AddrLong, 0, BINapp0I, 0));
956 sc->sc_hwmode = HW_FILL;
957 }
958 gftfb_wait_fifo(sc, 3);
959 bus_space_write_stream_4(memt, memh, NGLE_REG_35, bg);
960 /* dst XY */
961 bus_space_write_stream_4(memt, memh, NGLE_REG_6, (x << 16) | y);
962 /* len XY start */
963 bus_space_write_stream_4(memt, memh, NGLE_REG_9, (wi << 16) | he);
964
965 }
966
967
968 static void
969 gftfb_bitblt(void *cookie, int xs, int ys, int xd, int yd, int wi,
970 int he, int rop)
971 {
972 struct gftfb_softc *sc = cookie;
973 struct sti_rom *rom = sc->sc_base.sc_rom;
974 bus_space_tag_t memt = rom->memt;
975 bus_space_handle_t memh = rom->regh[2];
976
977 gftfb_wait(sc);
978 bus_space_write_stream_4(memt, memh, NGLE_REG_10, 0x13a01000);
979 gftfb_wait_fifo(sc, 5);
980 bus_space_write_stream_4(memt, memh, NGLE_REG_14, ((rop << 8) & 0xf00) | 0x23000000);
981 bus_space_write_stream_4(memt, memh, NGLE_REG_13, 0xff);
982 bus_space_write_stream_4(memt, memh, NGLE_REG_24, (xs << 16) | ys);
983 bus_space_write_stream_4(memt, memh, NGLE_REG_7, (wi << 16) | he);
984 bus_space_write_stream_4(memt, memh, NGLE_REG_25, (xd << 16) | yd);
985 sc->sc_hwmode = HW_BLIT;
986 }
987
988 static void
989 gftfb_nuke_cursor(struct rasops_info *ri)
990 {
991 struct vcons_screen *scr = ri->ri_hw;
992 struct gftfb_softc *sc = scr->scr_cookie;
993 int wi, he, x, y;
994
995 if (ri->ri_flg & RI_CURSOR) {
996 wi = ri->ri_font->fontwidth;
997 he = ri->ri_font->fontheight;
998 x = ri->ri_ccol * wi + ri->ri_xorigin;
999 y = ri->ri_crow * he + ri->ri_yorigin;
1000 gftfb_bitblt(sc, x, y, x, y, wi, he, RopInv);
1001 ri->ri_flg &= ~RI_CURSOR;
1002 }
1003 }
1004
1005 static void
1006 gftfb_cursor(void *cookie, int on, int row, int col)
1007 {
1008 struct rasops_info *ri = cookie;
1009 struct vcons_screen *scr = ri->ri_hw;
1010 struct gftfb_softc *sc = scr->scr_cookie;
1011 int x, y, wi, he;
1012
1013 wi = ri->ri_font->fontwidth;
1014 he = ri->ri_font->fontheight;
1015
1016 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
1017 if (on) {
1018 if (ri->ri_flg & RI_CURSOR) {
1019 gftfb_nuke_cursor(ri);
1020 }
1021 x = col * wi + ri->ri_xorigin;
1022 y = row * he + ri->ri_yorigin;
1023 gftfb_bitblt(sc, x, y, x, y, wi, he, RopInv);
1024 ri->ri_flg |= RI_CURSOR;
1025 }
1026 ri->ri_crow = row;
1027 ri->ri_ccol = col;
1028 } else
1029 {
1030 ri->ri_crow = row;
1031 ri->ri_ccol = col;
1032 ri->ri_flg &= ~RI_CURSOR;
1033 }
1034
1035 }
1036
1037 static void
1038 gftfb_putchar(void *cookie, int row, int col, u_int c, long attr)
1039 {
1040 struct rasops_info *ri = cookie;
1041 struct wsdisplay_font *font = PICK_FONT(ri, c);
1042 struct vcons_screen *scr = ri->ri_hw;
1043 struct gftfb_softc *sc = scr->scr_cookie;
1044 int x, y, wi, he, rv = GC_NOPE;
1045 #if 0
1046 uint32_t bg;
1047 #endif
1048 if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL)
1049 return;
1050
1051 if (!CHAR_IN_FONT(c, font))
1052 return;
1053
1054 if (row == ri->ri_crow && col == ri->ri_ccol) {
1055 ri->ri_flg &= ~RI_CURSOR;
1056 }
1057
1058 wi = font->fontwidth;
1059 he = font->fontheight;
1060
1061 x = ri->ri_xorigin + col * wi;
1062 y = ri->ri_yorigin + row * he;
1063 #if 0
1064 bg = ri->ri_devcmap[(attr >> 16) & 0xf];
1065
1066 /* XXX
1067 * rectfill currently draws rectangles less than 32 pixels wide as
1068 * 32 pixels wide, no idea why. So until I figure that one out we
1069 * draw blanks by software
1070 * bitblt doesn't seem to have this problem
1071 */
1072 if (c == 0x20) {
1073 gftfb_rectfill(sc, x, y, wi, he, bg);
1074 return;
1075 }
1076 #endif
1077 rv = glyphcache_try(&sc->sc_gc, c, x, y, attr);
1078 if (rv == GC_OK)
1079 return;
1080
1081 if (sc->sc_hwmode != HW_FB) gftfb_setup_fb(sc);
1082 sc->sc_putchar(cookie, row, col, c, attr);
1083
1084 if (rv == GC_ADD)
1085 glyphcache_add(&sc->sc_gc, c, x, y);
1086 }
1087
1088 static void
1089 gftfb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols)
1090 {
1091 struct rasops_info *ri = cookie;
1092 struct vcons_screen *scr = ri->ri_hw;
1093 struct gftfb_softc *sc = scr->scr_cookie;
1094 int32_t xs, xd, y, width, height;
1095
1096 if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
1097 if (ri->ri_crow == row &&
1098 (ri->ri_ccol >= srccol && ri->ri_ccol < (srccol + ncols)) &&
1099 (ri->ri_flg & RI_CURSOR)) {
1100 gftfb_nuke_cursor(ri);
1101 }
1102
1103 xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol;
1104 xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol;
1105 y = ri->ri_yorigin + ri->ri_font->fontheight * row;
1106 width = ri->ri_font->fontwidth * ncols;
1107 height = ri->ri_font->fontheight;
1108 gftfb_bitblt(sc, xs, y, xd, y, width, height, RopSrc);
1109 if (ri->ri_crow == row &&
1110 (ri->ri_ccol >= dstcol && ri->ri_ccol < (dstcol + ncols)))
1111 ri->ri_flg &= ~RI_CURSOR;
1112 }
1113 }
1114
1115 static void
1116 gftfb_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr)
1117 {
1118 struct rasops_info *ri = cookie;
1119 struct vcons_screen *scr = ri->ri_hw;
1120 struct gftfb_softc *sc = scr->scr_cookie;
1121 int32_t x, y, width, height, fg, bg, ul;
1122
1123 if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
1124 x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol;
1125 y = ri->ri_yorigin + ri->ri_font->fontheight * row;
1126 width = ri->ri_font->fontwidth * ncols;
1127 height = ri->ri_font->fontheight;
1128 rasops_unpack_attr(fillattr, &fg, &bg, &ul);
1129
1130 gftfb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]);
1131 if (ri->ri_crow == row &&
1132 (ri->ri_ccol >= startcol && ri->ri_ccol < (startcol + ncols)))
1133 ri->ri_flg &= ~RI_CURSOR;
1134 }
1135 }
1136
1137 static void
1138 gftfb_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
1139 {
1140 struct rasops_info *ri = cookie;
1141 struct vcons_screen *scr = ri->ri_hw;
1142 struct gftfb_softc *sc = scr->scr_cookie;
1143 int32_t x, ys, yd, width, height;
1144
1145 if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
1146 if ((ri->ri_crow >= srcrow && ri->ri_crow < (srcrow + nrows)) &&
1147 (ri->ri_flg & RI_CURSOR)) {
1148 gftfb_nuke_cursor(ri);
1149 }
1150 x = ri->ri_xorigin;
1151 ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow;
1152 yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow;
1153 width = ri->ri_emuwidth;
1154 height = ri->ri_font->fontheight * nrows;
1155 gftfb_bitblt(sc, x, ys, x, yd, width, height, RopSrc);
1156 if (ri->ri_crow >= dstrow && ri->ri_crow < (dstrow + nrows))
1157 ri->ri_flg &= ~RI_CURSOR;
1158 }
1159 }
1160
1161 static void
1162 gftfb_eraserows(void *cookie, int row, int nrows, long fillattr)
1163 {
1164 struct rasops_info *ri = cookie;
1165 struct vcons_screen *scr = ri->ri_hw;
1166 struct gftfb_softc *sc = scr->scr_cookie;
1167 int32_t x, y, width, height, fg, bg, ul;
1168
1169 if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
1170 x = ri->ri_xorigin;
1171 y = ri->ri_yorigin + ri->ri_font->fontheight * row;
1172 width = ri->ri_emuwidth;
1173 height = ri->ri_font->fontheight * nrows;
1174 rasops_unpack_attr(fillattr, &fg, &bg, &ul);
1175
1176 gftfb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]);
1177
1178 if (ri->ri_crow >= row && ri->ri_crow < (row + nrows))
1179 ri->ri_flg &= ~RI_CURSOR;
1180 }
1181 }
1182