machfb.c revision 201223
1/*- 2 * Copyright (c) 2002 Bang Jun-Young 3 * Copyright (c) 2005 Marius Strobl <marius@FreeBSD.org> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * from: NetBSD: machfb.c,v 1.23 2005/03/07 21:45:24 martin Exp 29 */ 30 31#include <sys/cdefs.h> 32__FBSDID("$FreeBSD: head/sys/dev/fb/machfb.c 201223 2009-12-29 21:51:28Z rnoland $"); 33 34/* 35 * Driver for ATI Mach64 graphics chips. Some code is derived from the 36 * ATI Rage Pro and Derivatives Programmer's Guide. 37 */ 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/bus.h> 42#include <sys/consio.h> 43#include <sys/endian.h> 44#include <sys/eventhandler.h> 45#include <sys/fbio.h> 46#include <sys/kernel.h> 47#include <sys/module.h> 48#include <sys/resource.h> 49 50#include <vm/vm.h> 51#include <vm/pmap.h> 52 53#include <dev/ofw/ofw_bus.h> 54#include <dev/ofw/openfirm.h> 55 56#include <machine/bus.h> 57#include <machine/bus_private.h> 58#include <machine/ofw_machdep.h> 59#include <machine/pmap.h> 60#include <machine/resource.h> 61#include <machine/sc_machdep.h> 62 63#include <sys/rman.h> 64 65#include <dev/fb/fbreg.h> 66#include <dev/fb/gfb.h> 67#include <dev/fb/machfbreg.h> 68#include <dev/pci/pcivar.h> 69#include <dev/pci/pcireg.h> 70#include <dev/syscons/syscons.h> 71 72/* #define MACHFB_DEBUG */ 73 74#define MACHFB_DRIVER_NAME "machfb" 75 76#define MACH64_REG_OFF 0x7ffc00 77#define MACH64_REG_SIZE 1024 78 79struct machfb_softc { 80 video_adapter_t sc_va; /* must be first */ 81 82 phandle_t sc_node; 83 uint16_t sc_chip_id; 84 uint8_t sc_chip_rev; 85 86 struct resource *sc_memres; 87 struct resource *sc_vmemres; 88 bus_space_tag_t sc_memt; 89 bus_space_tag_t sc_regt; 90 bus_space_handle_t sc_memh; 91 bus_space_handle_t sc_regh; 92 u_long sc_mem; 93 u_long sc_vmem; 94 95 u_int sc_height; 96 u_int sc_width; 97 u_int sc_depth; 98 u_int sc_xmargin; 99 u_int sc_ymargin; 100 101 size_t sc_memsize; 102 u_int sc_memtype; 103 u_int sc_mem_freq; 104 u_int sc_ramdac_freq; 105 u_int sc_ref_freq; 106 107 u_int sc_ref_div; 108 u_int sc_mclk_post_div; 109 u_int sc_mclk_fb_div; 110 111 const u_char *sc_font; 112 u_int sc_cbwidth; 113 vm_offset_t sc_curoff; 114 115 int sc_bg_cache; 116 int sc_fg_cache; 117 u_int sc_draw_cache; 118#define MACHFB_DRAW_CHAR (1 << 0) 119#define MACHFB_DRAW_FILLRECT (1 << 1) 120 121 u_int sc_flags; 122#define MACHFB_CONSOLE (1 << 0) 123#define MACHFB_CUREN (1 << 1) 124#define MACHFB_DSP (1 << 2) 125#define MACHFB_SWAP (1 << 3) 126}; 127 128static const struct { 129 uint16_t chip_id; 130 const char *name; 131 uint32_t ramdac_freq; 132} const machfb_info[] = { 133 { ATI_MACH64_CT, "ATI Mach64 CT", 135000 }, 134 { ATI_RAGE_PRO_AGP, "ATI 3D Rage Pro (AGP)", 230000 }, 135 { ATI_RAGE_PRO_AGP1X, "ATI 3D Rage Pro (AGP 1x)", 230000 }, 136 { ATI_RAGE_PRO_PCI_B, "ATI 3D Rage Pro Turbo", 230000 }, 137 { ATI_RAGE_XC_PCI66, "ATI Rage XL (PCI66)", 230000 }, 138 { ATI_RAGE_XL_AGP, "ATI Rage XL (AGP)", 230000 }, 139 { ATI_RAGE_XC_AGP, "ATI Rage XC (AGP)", 230000 }, 140 { ATI_RAGE_XL_PCI66, "ATI Rage XL (PCI66)", 230000 }, 141 { ATI_RAGE_PRO_PCI_P, "ATI 3D Rage Pro", 230000 }, 142 { ATI_RAGE_PRO_PCI_L, "ATI 3D Rage Pro (limited 3D)", 230000 }, 143 { ATI_RAGE_XL_PCI, "ATI Rage XL", 230000 }, 144 { ATI_RAGE_XC_PCI, "ATI Rage XC", 230000 }, 145 { ATI_RAGE_II, "ATI 3D Rage I/II", 135000 }, 146 { ATI_RAGE_IIP, "ATI 3D Rage II+", 200000 }, 147 { ATI_RAGE_IIC_PCI, "ATI 3D Rage IIC", 230000 }, 148 { ATI_RAGE_IIC_AGP_B, "ATI 3D Rage IIC (AGP)", 230000 }, 149 { ATI_RAGE_IIC_AGP_P, "ATI 3D Rage IIC (AGP)", 230000 }, 150 { ATI_RAGE_LT_PRO_AGP, "ATI 3D Rage LT Pro (AGP 133MHz)", 230000 }, 151 { ATI_RAGE_MOB_M3_PCI, "ATI Rage Mobility M3", 230000 }, 152 { ATI_RAGE_MOB_M3_AGP, "ATI Rage Mobility M3 (AGP)", 230000 }, 153 { ATI_RAGE_LT, "ATI 3D Rage LT", 230000 }, 154 { ATI_RAGE_LT_PRO_PCI, "ATI 3D Rage LT Pro", 230000 }, 155 { ATI_RAGE_MOBILITY, "ATI Rage Mobility", 230000 }, 156 { ATI_RAGE_L_MOBILITY, "ATI Rage L Mobility", 230000 }, 157 { ATI_RAGE_LT_PRO, "ATI 3D Rage LT Pro", 230000 }, 158 { ATI_RAGE_LT_PRO2, "ATI 3D Rage LT Pro", 230000 }, 159 { ATI_RAGE_MOB_M1_PCI, "ATI Rage Mobility M1 (PCI)", 230000 }, 160 { ATI_RAGE_L_MOB_M1_PCI, "ATI Rage L Mobility (PCI)", 230000 }, 161 { ATI_MACH64_VT, "ATI Mach64 VT", 170000 }, 162 { ATI_MACH64_VTB, "ATI Mach64 VTB", 200000 }, 163 { ATI_MACH64_VT4, "ATI Mach64 VT4", 230000 } 164}; 165 166static const struct machfb_cmap { 167 uint8_t red; 168 uint8_t green; 169 uint8_t blue; 170} const machfb_default_cmap[16] = { 171 {0x00, 0x00, 0x00}, /* black */ 172 {0x00, 0x00, 0xff}, /* blue */ 173 {0x00, 0xff, 0x00}, /* green */ 174 {0x00, 0xc0, 0xc0}, /* cyan */ 175 {0xff, 0x00, 0x00}, /* red */ 176 {0xc0, 0x00, 0xc0}, /* magenta */ 177 {0xc0, 0xc0, 0x00}, /* brown */ 178 {0xc0, 0xc0, 0xc0}, /* light grey */ 179 {0x80, 0x80, 0x80}, /* dark grey */ 180 {0x80, 0x80, 0xff}, /* light blue */ 181 {0x80, 0xff, 0x80}, /* light green */ 182 {0x80, 0xff, 0xff}, /* light cyan */ 183 {0xff, 0x80, 0x80}, /* light red */ 184 {0xff, 0x80, 0xff}, /* light magenta */ 185 {0xff, 0xff, 0x80}, /* yellow */ 186 {0xff, 0xff, 0xff} /* white */ 187}; 188 189#define MACHFB_CMAP_OFF 16 190 191static const u_char const machfb_mouse_pointer_bits[64][8] = { 192 { 0x00, 0x00, }, /* ............ */ 193 { 0x80, 0x00, }, /* *........... */ 194 { 0xc0, 0x00, }, /* **.......... */ 195 { 0xe0, 0x00, }, /* ***......... */ 196 { 0xf0, 0x00, }, /* ****........ */ 197 { 0xf8, 0x00, }, /* *****....... */ 198 { 0xfc, 0x00, }, /* ******...... */ 199 { 0xfe, 0x00, }, /* *******..... */ 200 { 0xff, 0x00, }, /* ********.... */ 201 { 0xff, 0x80, }, /* *********... */ 202 { 0xfc, 0xc0, }, /* ******..**.. */ 203 { 0xdc, 0x00, }, /* **.***...... */ 204 { 0x8e, 0x00, }, /* *...***..... */ 205 { 0x0e, 0x00, }, /* ....***..... */ 206 { 0x07, 0x00, }, /* .....***.... */ 207 { 0x04, 0x00, }, /* .....*...... */ 208 { 0x00, 0x00, }, /* ............ */ 209 { 0x00, 0x00, }, /* ............ */ 210 { 0x00, 0x00, }, /* ............ */ 211 { 0x00, 0x00, }, /* ............ */ 212 { 0x00, 0x00, }, /* ............ */ 213 { 0x00, 0x00, }, /* ............ */ 214}; 215 216/* 217 * Lookup table to perform a bit-swap of the mouse pointer bits, 218 * map set bits to CUR_CLR0 and unset bits to transparent. 219 */ 220static const u_char const machfb_mouse_pointer_lut[] = { 221 0xaa, 0x2a, 0x8a, 0x0a, 0xa2, 0x22, 0x82, 0x02, 222 0xa8, 0x28, 0x88, 0x08, 0xa0, 0x20, 0x80, 0x00 223}; 224 225static const char *const machfb_memtype_names[] = { 226 "(N/A)", "DRAM", "EDO DRAM", "EDO DRAM", "SDRAM", "SGRAM", "WRAM", 227 "(unknown type)" 228}; 229 230extern const struct gfb_font gallant12x22; 231 232static struct machfb_softc machfb_softc; 233static struct bus_space_tag machfb_bst_store[1]; 234 235static device_probe_t machfb_pci_probe; 236static device_attach_t machfb_pci_attach; 237static device_detach_t machfb_pci_detach; 238 239static device_method_t machfb_methods[] = { 240 /* Device interface */ 241 DEVMETHOD(device_probe, machfb_pci_probe), 242 DEVMETHOD(device_attach, machfb_pci_attach), 243 DEVMETHOD(device_detach, machfb_pci_detach), 244 245 { 0, 0 } 246}; 247 248static driver_t machfb_pci_driver = { 249 MACHFB_DRIVER_NAME, 250 machfb_methods, 251 sizeof(struct machfb_softc), 252}; 253 254static devclass_t machfb_devclass; 255 256DRIVER_MODULE(machfb, pci, machfb_pci_driver, machfb_devclass, 0, 0); 257MODULE_DEPEND(machfb, pci, 1, 1, 1); 258 259static void machfb_cursor_enable(struct machfb_softc *, int); 260static int machfb_cursor_install(struct machfb_softc *); 261static int machfb_get_memsize(struct machfb_softc *); 262static void machfb_reset_engine(struct machfb_softc *); 263static void machfb_init_engine(struct machfb_softc *); 264#if 0 265static void machfb_adjust_frame(struct machfb_softc *, int, int); 266#endif 267static void machfb_shutdown_final(void *); 268static void machfb_shutdown_reset(void *); 269 270static int machfb_configure(int); 271 272static vi_probe_t machfb_probe; 273static vi_init_t machfb_init; 274static vi_get_info_t machfb_get_info; 275static vi_query_mode_t machfb_query_mode; 276static vi_set_mode_t machfb_set_mode; 277static vi_save_font_t machfb_save_font; 278static vi_load_font_t machfb_load_font; 279static vi_show_font_t machfb_show_font; 280static vi_save_palette_t machfb_save_palette; 281static vi_load_palette_t machfb_load_palette; 282static vi_set_border_t machfb_set_border; 283static vi_save_state_t machfb_save_state; 284static vi_load_state_t machfb_load_state; 285static vi_set_win_org_t machfb_set_win_org; 286static vi_read_hw_cursor_t machfb_read_hw_cursor; 287static vi_set_hw_cursor_t machfb_set_hw_cursor; 288static vi_set_hw_cursor_shape_t machfb_set_hw_cursor_shape; 289static vi_blank_display_t machfb_blank_display; 290static vi_mmap_t machfb_mmap; 291static vi_ioctl_t machfb_ioctl; 292static vi_clear_t machfb_clear; 293static vi_fill_rect_t machfb_fill_rect; 294static vi_bitblt_t machfb_bitblt; 295static vi_diag_t machfb_diag; 296static vi_save_cursor_palette_t machfb_save_cursor_palette; 297static vi_load_cursor_palette_t machfb_load_cursor_palette; 298static vi_copy_t machfb_copy; 299static vi_putp_t machfb_putp; 300static vi_putc_t machfb_putc; 301static vi_puts_t machfb_puts; 302static vi_putm_t machfb_putm; 303 304static video_switch_t machfbvidsw = { 305 .probe = machfb_probe, 306 .init = machfb_init, 307 .get_info = machfb_get_info, 308 .query_mode = machfb_query_mode, 309 .set_mode = machfb_set_mode, 310 .save_font = machfb_save_font, 311 .load_font = machfb_load_font, 312 .show_font = machfb_show_font, 313 .save_palette = machfb_save_palette, 314 .load_palette = machfb_load_palette, 315 .set_border = machfb_set_border, 316 .save_state = machfb_save_state, 317 .load_state = machfb_load_state, 318 .set_win_org = machfb_set_win_org, 319 .read_hw_cursor = machfb_read_hw_cursor, 320 .set_hw_cursor = machfb_set_hw_cursor, 321 .set_hw_cursor_shape = machfb_set_hw_cursor_shape, 322 .blank_display = machfb_blank_display, 323 .mmap = machfb_mmap, 324 .ioctl = machfb_ioctl, 325 .clear = machfb_clear, 326 .fill_rect = machfb_fill_rect, 327 .bitblt = machfb_bitblt, 328 .diag = machfb_diag, 329 .save_cursor_palette = machfb_save_cursor_palette, 330 .load_cursor_palette = machfb_load_cursor_palette, 331 .copy = machfb_copy, 332 .putp = machfb_putp, 333 .putc = machfb_putc, 334 .puts = machfb_puts, 335 .putm = machfb_putm 336}; 337 338VIDEO_DRIVER(machfb, machfbvidsw, machfb_configure); 339 340extern sc_rndr_sw_t txtrndrsw; 341RENDERER(machfb, 0, txtrndrsw, gfb_set); 342 343RENDERER_MODULE(machfb, gfb_set); 344 345/* 346 * Inline functions for getting access to register aperture. 347 */ 348static inline uint32_t regr(struct machfb_softc *, uint32_t); 349static inline uint8_t regrb(struct machfb_softc *, uint32_t); 350static inline void regw(struct machfb_softc *, uint32_t, uint32_t); 351static inline void regwb(struct machfb_softc *, uint32_t, uint8_t); 352static inline void regwb_pll(struct machfb_softc *, uint32_t, uint8_t); 353 354static inline uint32_t 355regr(struct machfb_softc *sc, uint32_t index) 356{ 357 358 return bus_space_read_4(sc->sc_regt, sc->sc_regh, index); 359} 360 361static inline uint8_t 362regrb(struct machfb_softc *sc, uint32_t index) 363{ 364 365 return bus_space_read_1(sc->sc_regt, sc->sc_regh, index); 366} 367 368static inline void 369regw(struct machfb_softc *sc, uint32_t index, uint32_t data) 370{ 371 372 bus_space_write_4(sc->sc_regt, sc->sc_regh, index, data); 373 bus_space_barrier(sc->sc_regt, sc->sc_regh, index, 4, 374 BUS_SPACE_BARRIER_WRITE); 375} 376 377static inline void 378regwb(struct machfb_softc *sc, uint32_t index, uint8_t data) 379{ 380 381 bus_space_write_1(sc->sc_regt, sc->sc_regh, index, data); 382 bus_space_barrier(sc->sc_regt, sc->sc_regh, index, 1, 383 BUS_SPACE_BARRIER_WRITE); 384} 385 386static inline void 387regwb_pll(struct machfb_softc *sc, uint32_t index, uint8_t data) 388{ 389 390 regwb(sc, CLOCK_CNTL + 1, (index << 2) | PLL_WR_EN); 391 regwb(sc, CLOCK_CNTL + 2, data); 392 regwb(sc, CLOCK_CNTL + 1, (index << 2) & ~PLL_WR_EN); 393} 394 395static inline void 396wait_for_fifo(struct machfb_softc *sc, uint8_t v) 397{ 398 399 while ((regr(sc, FIFO_STAT) & 0xffff) > (0x8000 >> v)) 400 ; 401} 402 403static inline void 404wait_for_idle(struct machfb_softc *sc) 405{ 406 407 wait_for_fifo(sc, 16); 408 while ((regr(sc, GUI_STAT) & 1) != 0) 409 ; 410} 411 412/* 413 * Inline functions for setting the background and foreground colors. 414 */ 415static inline void machfb_setbg(struct machfb_softc *sc, int bg); 416static inline void machfb_setfg(struct machfb_softc *sc, int fg); 417 418static inline void 419machfb_setbg(struct machfb_softc *sc, int bg) 420{ 421 422 if (bg == sc->sc_bg_cache) 423 return; 424 sc->sc_bg_cache = bg; 425 wait_for_fifo(sc, 1); 426 regw(sc, DP_BKGD_CLR, bg + MACHFB_CMAP_OFF); 427} 428 429static inline void 430machfb_setfg(struct machfb_softc *sc, int fg) 431{ 432 433 if (fg == sc->sc_fg_cache) 434 return; 435 sc->sc_fg_cache = fg; 436 wait_for_fifo(sc, 1); 437 regw(sc, DP_FRGD_CLR, fg + MACHFB_CMAP_OFF); 438} 439 440/* 441 * video driver interface 442 */ 443static int 444machfb_configure(int flags) 445{ 446 struct machfb_softc *sc; 447 phandle_t chosen, output; 448 ihandle_t stdout; 449 bus_addr_t addr; 450 uint32_t id; 451 int i, space; 452 453 /* 454 * For the high-level console probing return the number of 455 * registered adapters. 456 */ 457 if (!(flags & VIO_PROBE_ONLY)) { 458 for (i = 0; vid_find_adapter(MACHFB_DRIVER_NAME, i) >= 0; i++) 459 ; 460 return (i); 461 } 462 463 /* Low-level console probing and initialization. */ 464 465 sc = &machfb_softc; 466 if (sc->sc_va.va_flags & V_ADP_REGISTERED) 467 goto found; 468 469 if ((chosen = OF_finddevice("/chosen")) == -1) /* Quis contra nos? */ 470 return (0); 471 if (OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) == -1) 472 return (0); 473 if ((output = OF_instance_to_package(stdout)) == -1) 474 return (0); 475 if ((OF_getprop(output, "vendor-id", &id, sizeof(id)) == -1) || 476 id != ATI_VENDOR) 477 return (0); 478 if (OF_getprop(output, "device-id", &id, sizeof(id)) == -1) 479 return (0); 480 for (i = 0; i < sizeof(machfb_info) / sizeof(machfb_info[0]); i++) { 481 if (id == machfb_info[i].chip_id) { 482 sc->sc_flags = MACHFB_CONSOLE; 483 sc->sc_node = output; 484 sc->sc_chip_id = id; 485 break; 486 } 487 } 488 if (!(sc->sc_flags & MACHFB_CONSOLE)) 489 return (0); 490 491 if (OF_getprop(output, "revision-id", &sc->sc_chip_rev, 492 sizeof(sc->sc_chip_rev)) == -1) 493 return (0); 494 if (OF_decode_addr(output, 0, &space, &addr) != 0) 495 return (0); 496 sc->sc_memt = &machfb_bst_store[0]; 497 sc->sc_memh = sparc64_fake_bustag(space, addr, sc->sc_memt); 498 sc->sc_regt = sc->sc_memt; 499 bus_space_subregion(sc->sc_regt, sc->sc_memh, MACH64_REG_OFF, 500 MACH64_REG_SIZE, &sc->sc_regh); 501 502 if (machfb_init(0, &sc->sc_va, 0) < 0) 503 return (0); 504 505 found: 506 /* Return number of found adapters. */ 507 return (1); 508} 509 510static int 511machfb_probe(int unit, video_adapter_t **adpp, void *arg, int flags) 512{ 513 514 return (0); 515} 516 517static int 518machfb_init(int unit, video_adapter_t *adp, int flags) 519{ 520 struct machfb_softc *sc; 521 phandle_t options; 522 video_info_t *vi; 523 char buf[32]; 524 int i; 525 uint8_t dac_mask, dac_rindex, dac_windex; 526 527 sc = (struct machfb_softc *)adp; 528 vi = &adp->va_info; 529 530 if ((regr(sc, CONFIG_CHIP_ID) & 0xffff) != sc->sc_chip_id) 531 return (ENXIO); 532 533 sc->sc_ramdac_freq = 0; 534 for (i = 0; i < sizeof(machfb_info) / sizeof(machfb_info[0]); i++) { 535 if (sc->sc_chip_id == machfb_info[i].chip_id) { 536 sc->sc_ramdac_freq = machfb_info[i].ramdac_freq; 537 break; 538 } 539 } 540 if (sc->sc_ramdac_freq == 0) 541 return (ENXIO); 542 if (sc->sc_chip_id == ATI_RAGE_II && sc->sc_chip_rev & 0x07) 543 sc->sc_ramdac_freq = 170000; 544 545 vid_init_struct(adp, MACHFB_DRIVER_NAME, -1, unit); 546 547 if (OF_getprop(sc->sc_node, "height", &sc->sc_height, 548 sizeof(sc->sc_height)) == -1) 549 return (ENXIO); 550 if (OF_getprop(sc->sc_node, "width", &sc->sc_width, 551 sizeof(sc->sc_width)) == -1) 552 return (ENXIO); 553 if (OF_getprop(sc->sc_node, "depth", &sc->sc_depth, 554 sizeof(sc->sc_depth)) == -1) 555 return (ENXIO); 556 if ((options = OF_finddevice("/options")) == -1) 557 return (ENXIO); 558 if (OF_getprop(options, "screen-#rows", buf, sizeof(buf)) == -1) 559 return (ENXIO); 560 vi->vi_height = strtol(buf, NULL, 10); 561 if (OF_getprop(options, "screen-#columns", buf, sizeof(buf)) == -1) 562 return (ENXIO); 563 vi->vi_width = strtol(buf, NULL, 10); 564 vi->vi_cwidth = gallant12x22.width; 565 vi->vi_cheight = gallant12x22.height; 566 vi->vi_flags = V_INFO_COLOR; 567 vi->vi_mem_model = V_INFO_MM_OTHER; 568 569 sc->sc_font = gallant12x22.data; 570 sc->sc_cbwidth = howmany(vi->vi_cwidth, NBBY); /* width in bytes */ 571 sc->sc_xmargin = (sc->sc_width - (vi->vi_width * vi->vi_cwidth)) / 2; 572 sc->sc_ymargin = (sc->sc_height - (vi->vi_height * vi->vi_cheight)) / 2; 573 574 if (sc->sc_chip_id != ATI_MACH64_CT && 575 !((sc->sc_chip_id == ATI_MACH64_VT || 576 sc->sc_chip_id == ATI_RAGE_II) && 577 (sc->sc_chip_rev & 0x07) == 0)) 578 sc->sc_flags |= MACHFB_DSP; 579 580 sc->sc_memsize = machfb_get_memsize(sc); 581 if (sc->sc_memsize == 8192) 582 /* The last page is used as register aperture. */ 583 sc->sc_memsize -= 4; 584 sc->sc_memtype = regr(sc, CONFIG_STAT0) & 0x07; 585 586 if ((sc->sc_chip_id >= ATI_RAGE_XC_PCI66 && 587 sc->sc_chip_id <= ATI_RAGE_XL_PCI66) || 588 (sc->sc_chip_id >= ATI_RAGE_XL_PCI && 589 sc->sc_chip_id <= ATI_RAGE_XC_PCI)) 590 sc->sc_ref_freq = 29498; 591 else 592 sc->sc_ref_freq = 14318; 593 594 regwb(sc, CLOCK_CNTL + 1, PLL_REF_DIV << 2); 595 sc->sc_ref_div = regrb(sc, CLOCK_CNTL + 2); 596 regwb(sc, CLOCK_CNTL + 1, MCLK_FB_DIV << 2); 597 sc->sc_mclk_fb_div = regrb(sc, CLOCK_CNTL + 2); 598 sc->sc_mem_freq = (2 * sc->sc_ref_freq * sc->sc_mclk_fb_div) / 599 (sc->sc_ref_div * 2); 600 sc->sc_mclk_post_div = (sc->sc_mclk_fb_div * 2 * sc->sc_ref_freq) / 601 (sc->sc_mem_freq * sc->sc_ref_div); 602 603 machfb_init_engine(sc); 604#if 0 605 machfb_adjust_frame(0, 0); 606#endif 607 machfb_set_mode(adp, 0); 608 609 /* 610 * Install our 16-color color map. This is done only once and with 611 * an offset of 16 on sparc64 as there the OBP driver expects white 612 * to be at index 0 and black at 255 (some versions also use 1 - 8 613 * for color text support or the full palette for the boot banner 614 * logo but no versions seems to use the ISO 6429-1983 color map). 615 * Otherwise the colors are inverted when back in the OFW. 616 */ 617 dac_rindex = regrb(sc, DAC_RINDEX); 618 dac_windex = regrb(sc, DAC_WINDEX); 619 dac_mask = regrb(sc, DAC_MASK); 620 regwb(sc, DAC_MASK, 0xff); 621 regwb(sc, DAC_WINDEX, MACHFB_CMAP_OFF); 622 for (i = 0; i < 16; i++) { 623 regwb(sc, DAC_DATA, machfb_default_cmap[i].red); 624 regwb(sc, DAC_DATA, machfb_default_cmap[i].green); 625 regwb(sc, DAC_DATA, machfb_default_cmap[i].blue); 626 } 627 regwb(sc, DAC_MASK, dac_mask); 628 regwb(sc, DAC_RINDEX, dac_rindex); 629 regwb(sc, DAC_WINDEX, dac_windex); 630 631 machfb_blank_display(adp, V_DISPLAY_ON); 632 machfb_clear(adp); 633 634 /* 635 * Setting V_ADP_MODECHANGE serves as hack so machfb_set_mode() 636 * (which will invalidate our caches) is called as a precaution 637 * when the X server shuts down. 638 */ 639 adp->va_flags |= V_ADP_COLOR | V_ADP_MODECHANGE | V_ADP_PALETTE | 640 V_ADP_BORDER | V_ADP_INITIALIZED; 641 if (vid_register(adp) < 0) 642 return (ENXIO); 643 adp->va_flags |= V_ADP_REGISTERED; 644 645 return (0); 646} 647 648static int 649machfb_get_info(video_adapter_t *adp, int mode, video_info_t *info) 650{ 651 652 bcopy(&adp->va_info, info, sizeof(*info)); 653 654 return (0); 655} 656 657static int 658machfb_query_mode(video_adapter_t *adp, video_info_t *info) 659{ 660 661 return (ENODEV); 662} 663 664static int 665machfb_set_mode(video_adapter_t *adp, int mode) 666{ 667 struct machfb_softc *sc; 668 669 sc = (struct machfb_softc *)adp; 670 671 sc->sc_bg_cache = -1; 672 sc->sc_fg_cache = -1; 673 sc->sc_draw_cache = 0; 674 675 return (0); 676} 677 678static int 679machfb_save_font(video_adapter_t *adp, int page, int size, int width, 680 u_char *data, int c, int count) 681{ 682 683 return (ENODEV); 684} 685 686static int 687machfb_load_font(video_adapter_t *adp, int page, int size, int width, 688 u_char *data, int c, int count) 689{ 690 691 return (ENODEV); 692} 693 694static int 695machfb_show_font(video_adapter_t *adp, int page) 696{ 697 698 return (ENODEV); 699} 700 701static int 702machfb_save_palette(video_adapter_t *adp, u_char *palette) 703{ 704 struct machfb_softc *sc; 705 int i; 706 uint8_t dac_mask, dac_rindex, dac_windex; 707 708 sc = (struct machfb_softc *)adp; 709 710 dac_rindex = regrb(sc, DAC_RINDEX); 711 dac_windex = regrb(sc, DAC_WINDEX); 712 dac_mask = regrb(sc, DAC_MASK); 713 regwb(sc, DAC_MASK, 0xff); 714 regwb(sc, DAC_RINDEX, 0x0); 715 for (i = 0; i < 256 * 3; i++) 716 palette[i] = regrb(sc, DAC_DATA); 717 regwb(sc, DAC_MASK, dac_mask); 718 regwb(sc, DAC_RINDEX, dac_rindex); 719 regwb(sc, DAC_WINDEX, dac_windex); 720 721 return (0); 722} 723 724static int 725machfb_load_palette(video_adapter_t *adp, u_char *palette) 726{ 727 struct machfb_softc *sc; 728 int i; 729 uint8_t dac_mask, dac_rindex, dac_windex; 730 731 sc = (struct machfb_softc *)adp; 732 733 dac_rindex = regrb(sc, DAC_RINDEX); 734 dac_windex = regrb(sc, DAC_WINDEX); 735 dac_mask = regrb(sc, DAC_MASK); 736 regwb(sc, DAC_MASK, 0xff); 737 regwb(sc, DAC_WINDEX, 0x0); 738 for (i = 0; i < 256 * 3; i++) 739 regwb(sc, DAC_DATA, palette[i]); 740 regwb(sc, DAC_MASK, dac_mask); 741 regwb(sc, DAC_RINDEX, dac_rindex); 742 regwb(sc, DAC_WINDEX, dac_windex); 743 744 return (0); 745} 746 747static int 748machfb_set_border(video_adapter_t *adp, int border) 749{ 750 struct machfb_softc *sc; 751 752 sc = (struct machfb_softc *)adp; 753 754 machfb_fill_rect(adp, border, 0, 0, sc->sc_width, sc->sc_ymargin); 755 machfb_fill_rect(adp, border, 0, sc->sc_height - sc->sc_ymargin, 756 sc->sc_width, sc->sc_ymargin); 757 machfb_fill_rect(adp, border, 0, 0, sc->sc_xmargin, sc->sc_height); 758 machfb_fill_rect(adp, border, sc->sc_width - sc->sc_xmargin, 0, 759 sc->sc_xmargin, sc->sc_height); 760 761 return (0); 762} 763 764static int 765machfb_save_state(video_adapter_t *adp, void *p, size_t size) 766{ 767 768 return (ENODEV); 769} 770 771static int 772machfb_load_state(video_adapter_t *adp, void *p) 773{ 774 775 return (ENODEV); 776} 777 778static int 779machfb_set_win_org(video_adapter_t *adp, off_t offset) 780{ 781 782 return (ENODEV); 783} 784 785static int 786machfb_read_hw_cursor(video_adapter_t *adp, int *col, int *row) 787{ 788 789 *col = 0; 790 *row = 0; 791 792 return (0); 793} 794 795static int 796machfb_set_hw_cursor(video_adapter_t *adp, int col, int row) 797{ 798 799 return (ENODEV); 800} 801 802static int 803machfb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, 804 int celsize, int blink) 805{ 806 807 return (ENODEV); 808} 809 810static int 811machfb_blank_display(video_adapter_t *adp, int mode) 812{ 813 struct machfb_softc *sc; 814 uint32_t crtc_gen_cntl; 815 816 sc = (struct machfb_softc *)adp; 817 818 crtc_gen_cntl = (regr(sc, CRTC_GEN_CNTL) | CRTC_EXT_DISP_EN | CRTC_EN) & 819 ~(CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS); 820 switch (mode) { 821 case V_DISPLAY_ON: 822 break; 823 case V_DISPLAY_BLANK: 824 crtc_gen_cntl |= CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | 825 CRTC_DISPLAY_DIS; 826 break; 827 case V_DISPLAY_STAND_BY: 828 crtc_gen_cntl |= CRTC_HSYNC_DIS | CRTC_DISPLAY_DIS; 829 break; 830 case V_DISPLAY_SUSPEND: 831 crtc_gen_cntl |= CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS; 832 break; 833 } 834 regw(sc, CRTC_GEN_CNTL, crtc_gen_cntl); 835 836 return (0); 837} 838 839static int 840machfb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, 841 int prot, vm_memattr_t *memattr) 842{ 843 struct machfb_softc *sc; 844 video_info_t *vi; 845 846 sc = (struct machfb_softc *)adp; 847 vi = &adp->va_info; 848 849 /* BAR 2 - VGA memory */ 850 if (sc->sc_vmem != 0 && offset >= sc->sc_vmem && 851 offset < sc->sc_vmem + vi->vi_registers_size) { 852 *paddr = vi->vi_registers + offset - sc->sc_vmem; 853 return (0); 854 } 855 856 /* BAR 0 - framebuffer */ 857 if (offset >= sc->sc_mem && 858 offset < sc->sc_mem + vi->vi_buffer_size) { 859 *paddr = vi->vi_buffer + offset - sc->sc_mem; 860 return (0); 861 } 862 863 /* 'regular' framebuffer mmap()ing */ 864 if (offset < adp->va_window_size) { 865 *paddr = vi->vi_window + offset; 866 return (0); 867 } 868 869 return (EINVAL); 870} 871 872static int 873machfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) 874{ 875 struct machfb_softc *sc; 876 struct fbcursor *fbc; 877 struct fbtype *fb; 878 879 sc = (struct machfb_softc *)adp; 880 881 switch (cmd) { 882 case FBIOGTYPE: 883 fb = (struct fbtype *)data; 884 fb->fb_type = FBTYPE_PCIMISC; 885 fb->fb_height = sc->sc_height; 886 fb->fb_width = sc->sc_width; 887 fb->fb_depth = sc->sc_depth; 888 if (sc->sc_depth <= 1 || sc->sc_depth > 8) 889 fb->fb_cmsize = 0; 890 else 891 fb->fb_cmsize = 1 << sc->sc_depth; 892 fb->fb_size = adp->va_buffer_size; 893 break; 894 case FBIOSCURSOR: 895 fbc = (struct fbcursor *)data; 896 if (fbc->set & FB_CUR_SETCUR && fbc->enable == 0) { 897 machfb_cursor_enable(sc, 0); 898 sc->sc_flags &= ~MACHFB_CUREN; 899 } else 900 return (ENODEV); 901 break; 902 default: 903 return (fb_commonioctl(adp, cmd, data)); 904 } 905 906 return (0); 907} 908 909static int 910machfb_clear(video_adapter_t *adp) 911{ 912 struct machfb_softc *sc; 913 914 sc = (struct machfb_softc *)adp; 915 916 machfb_fill_rect(adp, (SC_NORM_ATTR >> 4) & 0xf, 0, 0, sc->sc_width, 917 sc->sc_height); 918 919 return (0); 920} 921 922static int 923machfb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) 924{ 925 struct machfb_softc *sc; 926 927 sc = (struct machfb_softc *)adp; 928 929 if (sc->sc_draw_cache != MACHFB_DRAW_FILLRECT) { 930 wait_for_fifo(sc, 7); 931 regw(sc, DP_WRITE_MASK, 0xff); 932 regw(sc, DP_PIX_WIDTH, DST_8BPP | SRC_8BPP | HOST_8BPP); 933 regw(sc, DP_SRC, FRGD_SRC_FRGD_CLR); 934 regw(sc, DP_MIX, MIX_SRC << 16); 935 regw(sc, CLR_CMP_CNTL, 0); /* no transparency */ 936 regw(sc, SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT); 937 regw(sc, DST_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM); 938 sc->sc_draw_cache = MACHFB_DRAW_FILLRECT; 939 } 940 machfb_setfg(sc, val); 941 wait_for_fifo(sc, 4); 942 regw(sc, SRC_Y_X, (x << 16) | y); 943 regw(sc, SRC_WIDTH1, cx); 944 regw(sc, DST_Y_X, (x << 16) | y); 945 regw(sc, DST_HEIGHT_WIDTH, (cx << 16) | cy); 946 947 return (0); 948} 949 950static int 951machfb_bitblt(video_adapter_t *adp, ...) 952{ 953 954 return (ENODEV); 955} 956 957static int 958machfb_diag(video_adapter_t *adp, int level) 959{ 960 video_info_t info; 961 962 fb_dump_adp_info(adp->va_name, adp, level); 963 machfb_get_info(adp, 0, &info); 964 fb_dump_mode_info(adp->va_name, adp, &info, level); 965 966 return (0); 967} 968 969static int 970machfb_save_cursor_palette(video_adapter_t *adp, u_char *palette) 971{ 972 973 return (ENODEV); 974} 975 976static int 977machfb_load_cursor_palette(video_adapter_t *adp, u_char *palette) 978{ 979 980 return (ENODEV); 981} 982 983static int 984machfb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n) 985{ 986 987 return (ENODEV); 988} 989 990static int 991machfb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a, 992 int size, int bpp, int bit_ltor, int byte_ltor) 993{ 994 995 return (ENODEV); 996} 997 998static int 999machfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) 1000{ 1001 struct machfb_softc *sc; 1002 const uint8_t *p; 1003 int i; 1004 1005 sc = (struct machfb_softc *)adp; 1006 1007 if (sc->sc_draw_cache != MACHFB_DRAW_CHAR) { 1008 wait_for_fifo(sc, 8); 1009 regw(sc, DP_WRITE_MASK, 0xff); /* XXX only good for 8 bit */ 1010 regw(sc, DP_PIX_WIDTH, DST_8BPP | SRC_1BPP | HOST_1BPP); 1011 regw(sc, DP_SRC, MONO_SRC_HOST | BKGD_SRC_BKGD_CLR | 1012 FRGD_SRC_FRGD_CLR); 1013 regw(sc, DP_MIX ,((MIX_SRC & 0xffff) << 16) | MIX_SRC); 1014 regw(sc, CLR_CMP_CNTL, 0); /* no transparency */ 1015 regw(sc, SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT); 1016 regw(sc, DST_CNTL, DST_Y_TOP_TO_BOTTOM | DST_X_LEFT_TO_RIGHT); 1017 regw(sc, HOST_CNTL, HOST_BYTE_ALIGN); 1018 sc->sc_draw_cache = MACHFB_DRAW_CHAR; 1019 } 1020 machfb_setbg(sc, (a >> 4) & 0xf); 1021 machfb_setfg(sc, a & 0xf); 1022 wait_for_fifo(sc, 4 + (adp->va_info.vi_cheight / sc->sc_cbwidth)); 1023 regw(sc, SRC_Y_X, 0); 1024 regw(sc, SRC_WIDTH1, adp->va_info.vi_cwidth); 1025 regw(sc, DST_Y_X, ((((off % adp->va_info.vi_width) * 1026 adp->va_info.vi_cwidth) + sc->sc_xmargin) << 16) | 1027 (((off / adp->va_info.vi_width) * adp->va_info.vi_cheight) + 1028 sc->sc_ymargin)); 1029 regw(sc, DST_HEIGHT_WIDTH, (adp->va_info.vi_cwidth << 16) | 1030 adp->va_info.vi_cheight); 1031 p = sc->sc_font + (c * adp->va_info.vi_cheight * sc->sc_cbwidth); 1032 for (i = 0; i < adp->va_info.vi_cheight * sc->sc_cbwidth; i += 4) 1033 regw(sc, HOST_DATA0 + i, (p[i + 3] << 24 | p[i + 2] << 16 | 1034 p[i + 1] << 8 | p[i])); 1035 1036 return (0); 1037} 1038 1039static int 1040machfb_puts(video_adapter_t *adp, vm_offset_t off, uint16_t *s, int len) 1041{ 1042 struct machfb_softc *sc; 1043 int blanks, i, x1, x2, y1, y2; 1044 uint8_t a, c, color1, color2; 1045 1046 sc = (struct machfb_softc *)adp; 1047 1048#define MACHFB_BLANK machfb_fill_rect(adp, color1, x1, y1, \ 1049 blanks * adp->va_info.vi_cwidth, \ 1050 adp->va_info.vi_cheight) 1051 1052 blanks = color1 = x1 = y1 = 0; 1053 for (i = 0; i < len; i++) { 1054 /* 1055 * Accelerate continuous blanks by drawing a respective 1056 * rectangle instead. Drawing a rectangle of any size 1057 * takes about the same number of operations as drawing 1058 * a single character. 1059 */ 1060 c = s[i] & 0xff; 1061 a = (s[i] & 0xff00) >> 8; 1062 if (c == 0x00 || c == 0x20 || c == 0xdb || c == 0xff) { 1063 color2 = (a >> (c == 0xdb ? 0 : 4) & 0xf); 1064 x2 = (((off + i) % adp->va_info.vi_width) * 1065 adp->va_info.vi_cwidth) + sc->sc_xmargin; 1066 y2 = (((off + i) / adp->va_info.vi_width) * 1067 adp->va_info.vi_cheight) + sc->sc_ymargin; 1068 if (blanks == 0) { 1069 color1 = color2; 1070 x1 = x2; 1071 y1 = y2; 1072 blanks++; 1073 } else if (color1 != color2 || y1 != y2) { 1074 MACHFB_BLANK; 1075 color1 = color2; 1076 x1 = x2; 1077 y1 = y2; 1078 blanks = 1; 1079 } else 1080 blanks++; 1081 } else { 1082 if (blanks != 0) { 1083 MACHFB_BLANK; 1084 blanks = 0; 1085 } 1086 vidd_putc(adp, off + i, c, a); 1087 } 1088 } 1089 if (blanks != 0) 1090 MACHFB_BLANK; 1091 1092#undef MACHFB_BLANK 1093 1094 return (0); 1095} 1096 1097static int 1098machfb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, 1099 uint32_t pixel_mask, int size, int width) 1100{ 1101 struct machfb_softc *sc; 1102 int error; 1103 1104 sc = (struct machfb_softc *)adp; 1105 1106 if ((!(sc->sc_flags & MACHFB_CUREN)) && 1107 (error = machfb_cursor_install(sc)) < 0) 1108 return (error); 1109 else { 1110 /* 1111 * The hardware cursor always must be disabled when 1112 * fiddling with its bits otherwise some artifacts 1113 * may appear on the screen. 1114 */ 1115 machfb_cursor_enable(sc, 0); 1116 } 1117 1118 regw(sc, CUR_HORZ_VERT_OFF, 0); 1119 if ((regr(sc, GEN_TEST_CNTL) & CRTC_DBL_SCAN_EN) != 0) 1120 y <<= 1; 1121 regw(sc, CUR_HORZ_VERT_POSN, ((y + sc->sc_ymargin) << 16) | 1122 (x + sc->sc_xmargin)); 1123 machfb_cursor_enable(sc, 1); 1124 sc->sc_flags |= MACHFB_CUREN; 1125 1126 return (0); 1127} 1128 1129/* 1130 * PCI bus interface 1131 */ 1132static int 1133machfb_pci_probe(device_t dev) 1134{ 1135 int i; 1136 1137 if (pci_get_class(dev) != PCIC_DISPLAY || 1138 pci_get_subclass(dev) != PCIS_DISPLAY_VGA) 1139 return (ENXIO); 1140 1141 for (i = 0; i < sizeof(machfb_info) / sizeof(machfb_info[0]); i++) { 1142 if (pci_get_device(dev) == machfb_info[i].chip_id) { 1143 device_set_desc(dev, machfb_info[i].name); 1144 return (BUS_PROBE_DEFAULT); 1145 } 1146 } 1147 1148 return (ENXIO); 1149} 1150 1151static int 1152machfb_pci_attach(device_t dev) 1153{ 1154 struct machfb_softc *sc; 1155 video_adapter_t *adp; 1156 video_switch_t *sw; 1157 video_info_t *vi; 1158 phandle_t node; 1159 int error, i, rid; 1160 uint32_t *p32, u32; 1161 uint8_t *p; 1162 1163 node = ofw_bus_get_node(dev); 1164 if ((sc = (struct machfb_softc *)vid_get_adapter(vid_find_adapter( 1165 MACHFB_DRIVER_NAME, 0))) != NULL && sc->sc_node == node) { 1166 device_printf(dev, "console\n"); 1167 device_set_softc(dev, sc); 1168 } else { 1169 sc = device_get_softc(dev); 1170 1171 sc->sc_node = node; 1172 sc->sc_chip_id = pci_get_device(dev); 1173 sc->sc_chip_rev = pci_get_revid(dev); 1174 } 1175 adp = &sc->sc_va; 1176 vi = &adp->va_info; 1177 1178 /* 1179 * Allocate resources regardless of whether we are the console 1180 * and already obtained the bus tag and handle for the framebuffer 1181 * in machfb_configure() or not so the resources are marked as 1182 * taken in the respective RMAN. 1183 */ 1184 1185 /* Enable memory and IO access. */ 1186 pci_write_config(dev, PCIR_COMMAND, 1187 pci_read_config(dev, PCIR_COMMAND, 2) | PCIM_CMD_PORTEN | 1188 PCIM_CMD_MEMEN, 2); 1189 1190 /* 1191 * NB: we need to take care that the framebuffer isn't mapped 1192 * in twice as besides wasting resources this isn't possible with 1193 * all MMUs. 1194 */ 1195 rid = PCIR_BAR(0); 1196 if ((sc->sc_memres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 1197 &rid, 0)) == NULL) { 1198 device_printf(dev, "cannot allocate memory resources\n"); 1199 return (ENXIO); 1200 } 1201 if (OF_getprop(sc->sc_node, "address", &u32, sizeof(u32)) > 0 && 1202 vtophys(u32) == rman_get_bushandle(sc->sc_memres)) 1203 adp->va_mem_base = u32; 1204 else { 1205 bus_release_resource(dev, SYS_RES_MEMORY, 1206 rman_get_rid(sc->sc_memres), sc->sc_memres); 1207 rid = PCIR_BAR(0); 1208 if ((sc->sc_memres = bus_alloc_resource_any(dev, 1209 SYS_RES_MEMORY, &rid, RF_ACTIVE)) == NULL) { 1210 device_printf(dev, 1211 "cannot allocate memory resources\n"); 1212 return (ENXIO); 1213 } 1214 adp->va_mem_base = 1215 (vm_offset_t)rman_get_virtual(sc->sc_memres); 1216 } 1217 sc->sc_memt = rman_get_bustag(sc->sc_memres); 1218 sc->sc_memh = rman_get_bushandle(sc->sc_memres); 1219 sc->sc_regt = sc->sc_memt; 1220 bus_space_subregion(sc->sc_regt, sc->sc_memh, MACH64_REG_OFF, 1221 MACH64_REG_SIZE, &sc->sc_regh); 1222 adp->va_mem_size = rman_get_size(sc->sc_memres); 1223 adp->va_buffer = adp->va_mem_base; 1224 adp->va_buffer_size = adp->va_mem_size; 1225 sc->sc_mem = rman_get_start(sc->sc_memres); 1226 vi->vi_buffer = sc->sc_memh; 1227 vi->vi_buffer_size = adp->va_buffer_size; 1228 1229 /* 1230 * Depending on the firmware version the VGA I/O and/or memory 1231 * resources of the Mach64 chips come up disabled. We generally 1232 * enable them above (pci(4) actually already did this unless 1233 * pci_enable_io_modes is not set) but this doesn't necessarily 1234 * mean that we get valid ones. Invalid resources seem to have 1235 * in common that they start at address 0. We don't allocate 1236 * them in this case in order to avoid warnings in apb(4) and 1237 * crashes when using these invalid resources. X.Org is aware 1238 * of this and doesn't use the VGA resources in this case (but 1239 * demands them if they are valid). 1240 */ 1241 rid = PCIR_BAR(2); 1242 if (bus_get_resource_start(dev, SYS_RES_MEMORY, rid) != 0) { 1243 if ((sc->sc_vmemres = bus_alloc_resource_any(dev, 1244 SYS_RES_MEMORY, &rid, RF_ACTIVE)) == NULL) { 1245 device_printf(dev, 1246 "cannot allocate VGA memory resources\n"); 1247 error = ENXIO; 1248 goto fail_memres; 1249 } 1250 adp->va_registers = 1251 (vm_offset_t)rman_get_virtual(sc->sc_vmemres); 1252 adp->va_registers_size = rman_get_size(sc->sc_vmemres); 1253 sc->sc_vmem = rman_get_start(sc->sc_vmemres); 1254 vi->vi_registers = rman_get_bushandle(sc->sc_vmemres); 1255 vi->vi_registers_size = adp->va_registers_size; 1256 } 1257 1258 if (!(sc->sc_flags & MACHFB_CONSOLE)) { 1259 if ((sw = vid_get_switch(MACHFB_DRIVER_NAME)) == NULL) { 1260 device_printf(dev, "cannot get video switch\n"); 1261 error = ENODEV; 1262 goto fail_vmemres; 1263 } 1264 /* 1265 * During device configuration we don't necessarily probe 1266 * the adapter which is the console first so we can't use 1267 * the device unit number for the video adapter unit. The 1268 * worst case would be that we use the video adapter unit 1269 * 0 twice. As it doesn't really matter which unit number 1270 * the corresponding video adapter has just use the next 1271 * unused one. 1272 */ 1273 for (i = 0; i < devclass_get_maxunit(machfb_devclass); i++) 1274 if (vid_find_adapter(MACHFB_DRIVER_NAME, i) < 0) 1275 break; 1276 if ((error = sw->init(i, adp, 0)) != 0) { 1277 device_printf(dev, "cannot initialize adapter\n"); 1278 goto fail_vmemres; 1279 } 1280 } 1281 1282 /* 1283 * Test whether the aperture is byte swapped or not, set 1284 * va_window and va_window_size as appropriate. Note that 1285 * the aperture could be mapped either big or little endian 1286 * on independently of the endianess of the host so this 1287 * has to be a runtime test. 1288 */ 1289 p32 = (uint32_t *)adp->va_buffer; 1290 u32 = *p32; 1291 p = (uint8_t *)adp->va_buffer; 1292 *p32 = 0x12345678; 1293 if (!(p[0] == 0x12 && p[1] == 0x34 && p[2] == 0x56 && p[3] == 0x78)) { 1294 adp->va_window = adp->va_buffer + 0x800000; 1295 adp->va_window_size = adp->va_buffer_size - 0x800000; 1296 vi->vi_window = vi->vi_buffer + 0x800000; 1297 vi->vi_window_size = vi->vi_buffer_size - 0x800000; 1298 sc->sc_flags |= MACHFB_SWAP; 1299 } else { 1300 adp->va_window = adp->va_buffer; 1301 adp->va_window_size = adp->va_buffer_size; 1302 vi->vi_window = vi->vi_buffer; 1303 vi->vi_window_size = vi->vi_buffer_size; 1304 } 1305 *p32 = u32; 1306 adp->va_window_gran = adp->va_window_size; 1307 1308 device_printf(dev, 1309 "%d MB aperture at %p %sswapped\n", 1310 (u_int)(adp->va_window_size / (1024 * 1024)), 1311 (void *)adp->va_window, (sc->sc_flags & MACHFB_SWAP) ? 1312 "" : "not "); 1313 device_printf(dev, 1314 "%ld KB %s %d.%d MHz, maximum RAMDAC clock %d MHz, %sDSP\n", 1315 (u_long)sc->sc_memsize, machfb_memtype_names[sc->sc_memtype], 1316 sc->sc_mem_freq / 1000, sc->sc_mem_freq % 1000, 1317 sc->sc_ramdac_freq / 1000, 1318 (sc->sc_flags & MACHFB_DSP) ? "" : "no "); 1319 device_printf(dev, "resolution %dx%d at %d bpp\n", 1320 sc->sc_width, sc->sc_height, sc->sc_depth); 1321 1322 /* 1323 * Allocate one page for the mouse pointer image at the end of 1324 * the little endian aperture, right before the memory mapped 1325 * registers that might also reside there. Must be done after 1326 * sc_memsize was set and possibly adjusted to account for the 1327 * memory mapped registers. 1328 */ 1329 sc->sc_curoff = (sc->sc_memsize * 1024) - PAGE_SIZE; 1330 sc->sc_memsize -= PAGE_SIZE / 1024; 1331 machfb_cursor_enable(sc, 0); 1332 /* Initialize with an all transparent image. */ 1333 memset((void *)(adp->va_buffer + sc->sc_curoff), 0xaa, PAGE_SIZE); 1334 1335 /* 1336 * Register a handler that performs some cosmetic surgery like 1337 * turning off the mouse pointer on halt in preparation for 1338 * handing the screen over to the OFW. Register another handler 1339 * that turns off the CRTC when resetting, otherwise the OFW 1340 * boot command issued by cpu_reset() just doesn't work. 1341 */ 1342 EVENTHANDLER_REGISTER(shutdown_final, machfb_shutdown_final, sc, 1343 SHUTDOWN_PRI_DEFAULT); 1344 EVENTHANDLER_REGISTER(shutdown_reset, machfb_shutdown_reset, sc, 1345 SHUTDOWN_PRI_DEFAULT); 1346 1347 return (0); 1348 1349 fail_vmemres: 1350 if (sc->sc_vmemres != NULL) 1351 bus_release_resource(dev, SYS_RES_MEMORY, 1352 rman_get_rid(sc->sc_vmemres), sc->sc_vmemres); 1353 fail_memres: 1354 bus_release_resource(dev, SYS_RES_MEMORY, 1355 rman_get_rid(sc->sc_memres), sc->sc_memres); 1356 1357 return (error); 1358} 1359 1360static int 1361machfb_pci_detach(device_t dev) 1362{ 1363 1364 return (EINVAL); 1365} 1366 1367/* 1368 * internal functions 1369 */ 1370static void 1371machfb_cursor_enable(struct machfb_softc *sc, int onoff) 1372{ 1373 1374 if (onoff) 1375 regw(sc, GEN_TEST_CNTL, 1376 regr(sc, GEN_TEST_CNTL) | HWCURSOR_ENABLE); 1377 else 1378 regw(sc, GEN_TEST_CNTL, 1379 regr(sc, GEN_TEST_CNTL) &~ HWCURSOR_ENABLE); 1380} 1381 1382static int 1383machfb_cursor_install(struct machfb_softc *sc) 1384{ 1385 uint16_t *p, v; 1386 uint8_t fg; 1387 int i, j; 1388 1389 if (sc->sc_curoff == 0) 1390 return (ENODEV); 1391 1392 machfb_cursor_enable(sc, 0); 1393 regw(sc, CUR_OFFSET, sc->sc_curoff >> 3); 1394 fg = SC_NORM_ATTR & 0xf; 1395 regw(sc, CUR_CLR0, machfb_default_cmap[fg].red << 24 | 1396 machfb_default_cmap[fg].green << 16 | 1397 machfb_default_cmap[fg].blue << 8); 1398 p = (uint16_t *)(sc->sc_va.va_buffer + sc->sc_curoff); 1399 for (i = 0; i < 64; i++) { 1400 for (j = 0; j < 8; j++) { 1401 v = machfb_mouse_pointer_lut[ 1402 machfb_mouse_pointer_bits[i][j] >> 4] << 8 | 1403 machfb_mouse_pointer_lut[ 1404 machfb_mouse_pointer_bits[i][j] & 0x0f]; 1405 if (sc->sc_flags & MACHFB_SWAP) 1406 *(p++) = bswap16(v); 1407 else 1408 *(p++) = v; 1409 } 1410 } 1411 1412 return (0); 1413} 1414 1415static int 1416machfb_get_memsize(struct machfb_softc *sc) 1417{ 1418 int tmp, memsize; 1419 const int const mem_tab[] = { 1420 512, 1024, 2048, 4096, 6144, 8192, 12288, 16384 1421 }; 1422 1423 tmp = regr(sc, MEM_CNTL); 1424#ifdef MACHFB_DEBUG 1425 printf("memcntl=0x%08x\n", tmp); 1426#endif 1427 if (sc->sc_flags & MACHFB_DSP) { 1428 tmp &= 0x0000000f; 1429 if (tmp < 8) 1430 memsize = (tmp + 1) * 512; 1431 else if (tmp < 12) 1432 memsize = (tmp - 3) * 1024; 1433 else 1434 memsize = (tmp - 7) * 2048; 1435 } else 1436 memsize = mem_tab[tmp & 0x07]; 1437 1438 return (memsize); 1439} 1440 1441static void 1442machfb_reset_engine(struct machfb_softc *sc) 1443{ 1444 1445 /* Reset engine.*/ 1446 regw(sc, GEN_TEST_CNTL, regr(sc, GEN_TEST_CNTL) & ~GUI_ENGINE_ENABLE); 1447 1448 /* Enable engine. */ 1449 regw(sc, GEN_TEST_CNTL, regr(sc, GEN_TEST_CNTL) | GUI_ENGINE_ENABLE); 1450 1451 /* 1452 * Ensure engine is not locked up by clearing any FIFO or 1453 * host errors. 1454 */ 1455 regw(sc, BUS_CNTL, regr(sc, BUS_CNTL) | BUS_HOST_ERR_ACK | 1456 BUS_FIFO_ERR_ACK); 1457} 1458 1459static void 1460machfb_init_engine(struct machfb_softc *sc) 1461{ 1462 uint32_t pitch_value; 1463 1464 pitch_value = sc->sc_width; 1465 1466 if (sc->sc_depth == 24) 1467 pitch_value *= 3; 1468 1469 machfb_reset_engine(sc); 1470 1471 wait_for_fifo(sc, 14); 1472 1473 regw(sc, CONTEXT_MASK, 0xffffffff); 1474 1475 regw(sc, DST_OFF_PITCH, (pitch_value / 8) << 22); 1476 1477 regw(sc, DST_Y_X, 0); 1478 regw(sc, DST_HEIGHT, 0); 1479 regw(sc, DST_BRES_ERR, 0); 1480 regw(sc, DST_BRES_INC, 0); 1481 regw(sc, DST_BRES_DEC, 0); 1482 1483 regw(sc, DST_CNTL, DST_LAST_PEL | DST_X_LEFT_TO_RIGHT | 1484 DST_Y_TOP_TO_BOTTOM); 1485 1486 regw(sc, SRC_OFF_PITCH, (pitch_value / 8) << 22); 1487 1488 regw(sc, SRC_Y_X, 0); 1489 regw(sc, SRC_HEIGHT1_WIDTH1, 1); 1490 regw(sc, SRC_Y_X_START, 0); 1491 regw(sc, SRC_HEIGHT2_WIDTH2, 1); 1492 1493 regw(sc, SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT); 1494 1495 wait_for_fifo(sc, 13); 1496 regw(sc, HOST_CNTL, 0); 1497 1498 regw(sc, PAT_REG0, 0); 1499 regw(sc, PAT_REG1, 0); 1500 regw(sc, PAT_CNTL, 0); 1501 1502 regw(sc, SC_LEFT, 0); 1503 regw(sc, SC_TOP, 0); 1504 regw(sc, SC_BOTTOM, sc->sc_height - 1); 1505 regw(sc, SC_RIGHT, pitch_value - 1); 1506 1507 regw(sc, DP_BKGD_CLR, 0); 1508 regw(sc, DP_FRGD_CLR, 0xffffffff); 1509 regw(sc, DP_WRITE_MASK, 0xffffffff); 1510 regw(sc, DP_MIX, (MIX_SRC << 16) | MIX_DST); 1511 1512 regw(sc, DP_SRC, FRGD_SRC_FRGD_CLR); 1513 1514 wait_for_fifo(sc, 3); 1515 regw(sc, CLR_CMP_CLR, 0); 1516 regw(sc, CLR_CMP_MASK, 0xffffffff); 1517 regw(sc, CLR_CMP_CNTL, 0); 1518 1519 wait_for_fifo(sc, 2); 1520 switch (sc->sc_depth) { 1521 case 8: 1522 regw(sc, DP_PIX_WIDTH, HOST_8BPP | SRC_8BPP | DST_8BPP); 1523 regw(sc, DP_CHAIN_MASK, DP_CHAIN_8BPP); 1524 regw(sc, DAC_CNTL, regr(sc, DAC_CNTL) | DAC_8BIT_EN); 1525 break; 1526#if 0 1527 case 32: 1528 regw(sc, DP_PIX_WIDTH, HOST_32BPP | SRC_32BPP | DST_32BPP); 1529 regw(sc, DP_CHAIN_MASK, DP_CHAIN_32BPP); 1530 regw(sc, DAC_CNTL, regr(sc, DAC_CNTL) | DAC_8BIT_EN); 1531 break; 1532#endif 1533 } 1534 1535 wait_for_fifo(sc, 2); 1536 regw(sc, CRTC_INT_CNTL, regr(sc, CRTC_INT_CNTL) & ~0x20); 1537 regw(sc, GUI_TRAJ_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM); 1538 1539 wait_for_idle(sc); 1540} 1541 1542#if 0 1543static void 1544machfb_adjust_frame(struct machfb_softc *sc, int x, int y) 1545{ 1546 int offset; 1547 1548 offset = ((x + y * sc->sc_width) * (sc->sc_depth >> 3)) >> 3; 1549 1550 regw(sc, CRTC_OFF_PITCH, (regr(sc, CRTC_OFF_PITCH) & 0xfff00000) | 1551 offset); 1552} 1553#endif 1554 1555static void 1556machfb_shutdown_final(void *v) 1557{ 1558 struct machfb_softc *sc = v; 1559 1560 machfb_cursor_enable(sc, 0); 1561 /* 1562 * In case this is the console set the cursor of the stdout 1563 * instance to the start of the last line so OFW output ends 1564 * up beneath what FreeBSD left on the screen. 1565 */ 1566 if (sc->sc_flags & MACHFB_CONSOLE) { 1567 OF_interpret("stdout @ is my-self 0 to column#", 0); 1568 OF_interpret("stdout @ is my-self #lines 1 - to line#", 0); 1569 } 1570} 1571 1572static void 1573machfb_shutdown_reset(void *v) 1574{ 1575 struct machfb_softc *sc = v; 1576 1577 machfb_blank_display(&sc->sc_va, V_DISPLAY_STAND_BY); 1578} 1579