1146482Smarius/*- 2146482Smarius * Copyright (c) 2002 Bang Jun-Young 3191076Smarius * Copyright (c) 2005 Marius Strobl <marius@FreeBSD.org> 4146482Smarius * All rights reserved. 5146482Smarius * 6146482Smarius * Redistribution and use in source and binary forms, with or without 7146482Smarius * modification, are permitted provided that the following conditions 8146482Smarius * are met: 9146482Smarius * 1. Redistributions of source code must retain the above copyright 10146482Smarius * notice, this list of conditions and the following disclaimer. 11146482Smarius * 2. Redistributions in binary form must reproduce the above copyright 12146482Smarius * notice, this list of conditions and the following disclaimer in the 13146482Smarius * documentation and/or other materials provided with the distribution. 14146482Smarius * 3. The name of the author may not be used to endorse or promote products 15146482Smarius * derived from this software without specific prior written permission. 16146482Smarius * 17146482Smarius * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18146482Smarius * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19146482Smarius * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20146482Smarius * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21146482Smarius * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22146482Smarius * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23146482Smarius * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24146482Smarius * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25146482Smarius * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26146482Smarius * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27146482Smarius * 28146482Smarius * from: NetBSD: machfb.c,v 1.23 2005/03/07 21:45:24 martin Exp 29146482Smarius */ 30191072Smarius 31146482Smarius#include <sys/cdefs.h> 32146482Smarius__FBSDID("$FreeBSD$"); 33146482Smarius 34146482Smarius/* 35191072Smarius * Driver for ATI Mach64 graphics chips. Some code is derived from the 36146482Smarius * ATI Rage Pro and Derivatives Programmer's Guide. 37146482Smarius */ 38146482Smarius 39146482Smarius#include <sys/param.h> 40146482Smarius#include <sys/systm.h> 41146482Smarius#include <sys/bus.h> 42146482Smarius#include <sys/consio.h> 43191076Smarius#include <sys/endian.h> 44146482Smarius#include <sys/eventhandler.h> 45146482Smarius#include <sys/fbio.h> 46146482Smarius#include <sys/kernel.h> 47146482Smarius#include <sys/module.h> 48146482Smarius#include <sys/resource.h> 49146482Smarius 50191076Smarius#include <vm/vm.h> 51191076Smarius#include <vm/pmap.h> 52191076Smarius 53146482Smarius#include <dev/ofw/ofw_bus.h> 54146482Smarius#include <dev/ofw/openfirm.h> 55146482Smarius 56146482Smarius#include <machine/bus.h> 57146482Smarius#include <machine/bus_private.h> 58146482Smarius#include <machine/ofw_machdep.h> 59191076Smarius#include <machine/pmap.h> 60146482Smarius#include <machine/resource.h> 61146482Smarius#include <machine/sc_machdep.h> 62146482Smarius 63146482Smarius#include <sys/rman.h> 64146482Smarius 65146482Smarius#include <dev/fb/fbreg.h> 66170840Smarius#include <dev/fb/gfb.h> 67146482Smarius#include <dev/fb/machfbreg.h> 68146482Smarius#include <dev/pci/pcivar.h> 69146482Smarius#include <dev/pci/pcireg.h> 70146482Smarius#include <dev/syscons/syscons.h> 71146482Smarius 72146482Smarius/* #define MACHFB_DEBUG */ 73146482Smarius 74146482Smarius#define MACHFB_DRIVER_NAME "machfb" 75146482Smarius 76146482Smarius#define MACH64_REG_OFF 0x7ffc00 77146482Smarius#define MACH64_REG_SIZE 1024 78146482Smarius 79146482Smariusstruct machfb_softc { 80146482Smarius video_adapter_t sc_va; /* must be first */ 81146482Smarius 82191072Smarius phandle_t sc_node; 83146482Smarius uint16_t sc_chip_id; 84146482Smarius uint8_t sc_chip_rev; 85146482Smarius 86146482Smarius struct resource *sc_memres; 87146482Smarius struct resource *sc_vmemres; 88146482Smarius bus_space_tag_t sc_memt; 89146482Smarius bus_space_tag_t sc_regt; 90230687Smarius bus_space_tag_t sc_vmemt; 91146482Smarius bus_space_handle_t sc_memh; 92230687Smarius bus_space_handle_t sc_vmemh; 93146482Smarius bus_space_handle_t sc_regh; 94191076Smarius u_long sc_mem; 95191076Smarius u_long sc_vmem; 96146482Smarius 97191076Smarius u_int sc_height; 98191076Smarius u_int sc_width; 99191076Smarius u_int sc_depth; 100191076Smarius u_int sc_xmargin; 101191076Smarius u_int sc_ymargin; 102146482Smarius 103146482Smarius size_t sc_memsize; 104191076Smarius u_int sc_memtype; 105191076Smarius u_int sc_mem_freq; 106191076Smarius u_int sc_ramdac_freq; 107191076Smarius u_int sc_ref_freq; 108146482Smarius 109191076Smarius u_int sc_ref_div; 110191076Smarius u_int sc_mclk_post_div; 111191076Smarius u_int sc_mclk_fb_div; 112146482Smarius 113170840Smarius const u_char *sc_font; 114191076Smarius u_int sc_cbwidth; 115146482Smarius vm_offset_t sc_curoff; 116146482Smarius 117147881Smarius int sc_bg_cache; 118147881Smarius int sc_fg_cache; 119191076Smarius u_int sc_draw_cache; 120146482Smarius#define MACHFB_DRAW_CHAR (1 << 0) 121146482Smarius#define MACHFB_DRAW_FILLRECT (1 << 1) 122146482Smarius 123191076Smarius u_int sc_flags; 124146482Smarius#define MACHFB_CONSOLE (1 << 0) 125146482Smarius#define MACHFB_CUREN (1 << 1) 126146482Smarius#define MACHFB_DSP (1 << 2) 127191076Smarius#define MACHFB_SWAP (1 << 3) 128146482Smarius}; 129146482Smarius 130147881Smariusstatic const struct { 131146482Smarius uint16_t chip_id; 132146482Smarius const char *name; 133146482Smarius uint32_t ramdac_freq; 134263764Sdim} machfb_info[] = { 135146482Smarius { ATI_MACH64_CT, "ATI Mach64 CT", 135000 }, 136146482Smarius { ATI_RAGE_PRO_AGP, "ATI 3D Rage Pro (AGP)", 230000 }, 137146482Smarius { ATI_RAGE_PRO_AGP1X, "ATI 3D Rage Pro (AGP 1x)", 230000 }, 138146482Smarius { ATI_RAGE_PRO_PCI_B, "ATI 3D Rage Pro Turbo", 230000 }, 139146482Smarius { ATI_RAGE_XC_PCI66, "ATI Rage XL (PCI66)", 230000 }, 140146482Smarius { ATI_RAGE_XL_AGP, "ATI Rage XL (AGP)", 230000 }, 141146482Smarius { ATI_RAGE_XC_AGP, "ATI Rage XC (AGP)", 230000 }, 142147881Smarius { ATI_RAGE_XL_PCI66, "ATI Rage XL (PCI66)", 230000 }, 143146482Smarius { ATI_RAGE_PRO_PCI_P, "ATI 3D Rage Pro", 230000 }, 144146482Smarius { ATI_RAGE_PRO_PCI_L, "ATI 3D Rage Pro (limited 3D)", 230000 }, 145146482Smarius { ATI_RAGE_XL_PCI, "ATI Rage XL", 230000 }, 146146482Smarius { ATI_RAGE_XC_PCI, "ATI Rage XC", 230000 }, 147146482Smarius { ATI_RAGE_II, "ATI 3D Rage I/II", 135000 }, 148146482Smarius { ATI_RAGE_IIP, "ATI 3D Rage II+", 200000 }, 149146482Smarius { ATI_RAGE_IIC_PCI, "ATI 3D Rage IIC", 230000 }, 150146482Smarius { ATI_RAGE_IIC_AGP_B, "ATI 3D Rage IIC (AGP)", 230000 }, 151146482Smarius { ATI_RAGE_IIC_AGP_P, "ATI 3D Rage IIC (AGP)", 230000 }, 152146482Smarius { ATI_RAGE_LT_PRO_AGP, "ATI 3D Rage LT Pro (AGP 133MHz)", 230000 }, 153146482Smarius { ATI_RAGE_MOB_M3_PCI, "ATI Rage Mobility M3", 230000 }, 154146482Smarius { ATI_RAGE_MOB_M3_AGP, "ATI Rage Mobility M3 (AGP)", 230000 }, 155146482Smarius { ATI_RAGE_LT, "ATI 3D Rage LT", 230000 }, 156146482Smarius { ATI_RAGE_LT_PRO_PCI, "ATI 3D Rage LT Pro", 230000 }, 157146482Smarius { ATI_RAGE_MOBILITY, "ATI Rage Mobility", 230000 }, 158146482Smarius { ATI_RAGE_L_MOBILITY, "ATI Rage L Mobility", 230000 }, 159146482Smarius { ATI_RAGE_LT_PRO, "ATI 3D Rage LT Pro", 230000 }, 160146482Smarius { ATI_RAGE_LT_PRO2, "ATI 3D Rage LT Pro", 230000 }, 161146482Smarius { ATI_RAGE_MOB_M1_PCI, "ATI Rage Mobility M1 (PCI)", 230000 }, 162146482Smarius { ATI_RAGE_L_MOB_M1_PCI, "ATI Rage L Mobility (PCI)", 230000 }, 163146482Smarius { ATI_MACH64_VT, "ATI Mach64 VT", 170000 }, 164146482Smarius { ATI_MACH64_VTB, "ATI Mach64 VTB", 200000 }, 165146482Smarius { ATI_MACH64_VT4, "ATI Mach64 VT4", 230000 } 166146482Smarius}; 167146482Smarius 168147881Smariusstatic const struct machfb_cmap { 169146482Smarius uint8_t red; 170146482Smarius uint8_t green; 171146482Smarius uint8_t blue; 172263764Sdim} machfb_default_cmap[16] = { 173146482Smarius {0x00, 0x00, 0x00}, /* black */ 174146482Smarius {0x00, 0x00, 0xff}, /* blue */ 175146482Smarius {0x00, 0xff, 0x00}, /* green */ 176146482Smarius {0x00, 0xc0, 0xc0}, /* cyan */ 177146482Smarius {0xff, 0x00, 0x00}, /* red */ 178146482Smarius {0xc0, 0x00, 0xc0}, /* magenta */ 179146482Smarius {0xc0, 0xc0, 0x00}, /* brown */ 180146482Smarius {0xc0, 0xc0, 0xc0}, /* light grey */ 181146482Smarius {0x80, 0x80, 0x80}, /* dark grey */ 182146482Smarius {0x80, 0x80, 0xff}, /* light blue */ 183146482Smarius {0x80, 0xff, 0x80}, /* light green */ 184146482Smarius {0x80, 0xff, 0xff}, /* light cyan */ 185146482Smarius {0xff, 0x80, 0x80}, /* light red */ 186146482Smarius {0xff, 0x80, 0xff}, /* light magenta */ 187146482Smarius {0xff, 0xff, 0x80}, /* yellow */ 188146482Smarius {0xff, 0xff, 0xff} /* white */ 189146482Smarius}; 190146482Smarius 191147881Smarius#define MACHFB_CMAP_OFF 16 192147881Smarius 193263764Sdimstatic const u_char machfb_mouse_pointer_bits[64][8] = { 194146482Smarius { 0x00, 0x00, }, /* ............ */ 195146482Smarius { 0x80, 0x00, }, /* *........... */ 196146482Smarius { 0xc0, 0x00, }, /* **.......... */ 197146482Smarius { 0xe0, 0x00, }, /* ***......... */ 198146482Smarius { 0xf0, 0x00, }, /* ****........ */ 199146482Smarius { 0xf8, 0x00, }, /* *****....... */ 200146482Smarius { 0xfc, 0x00, }, /* ******...... */ 201146482Smarius { 0xfe, 0x00, }, /* *******..... */ 202146482Smarius { 0xff, 0x00, }, /* ********.... */ 203146482Smarius { 0xff, 0x80, }, /* *********... */ 204146482Smarius { 0xfc, 0xc0, }, /* ******..**.. */ 205146482Smarius { 0xdc, 0x00, }, /* **.***...... */ 206146482Smarius { 0x8e, 0x00, }, /* *...***..... */ 207146482Smarius { 0x0e, 0x00, }, /* ....***..... */ 208146482Smarius { 0x07, 0x00, }, /* .....***.... */ 209146482Smarius { 0x04, 0x00, }, /* .....*...... */ 210146482Smarius { 0x00, 0x00, }, /* ............ */ 211146482Smarius { 0x00, 0x00, }, /* ............ */ 212146482Smarius { 0x00, 0x00, }, /* ............ */ 213146482Smarius { 0x00, 0x00, }, /* ............ */ 214146482Smarius { 0x00, 0x00, }, /* ............ */ 215146482Smarius { 0x00, 0x00, }, /* ............ */ 216146482Smarius}; 217146482Smarius 218146482Smarius/* 219146482Smarius * Lookup table to perform a bit-swap of the mouse pointer bits, 220146482Smarius * map set bits to CUR_CLR0 and unset bits to transparent. 221146482Smarius */ 222263764Sdimstatic const u_char machfb_mouse_pointer_lut[] = { 223146482Smarius 0xaa, 0x2a, 0x8a, 0x0a, 0xa2, 0x22, 0x82, 0x02, 224146482Smarius 0xa8, 0x28, 0x88, 0x08, 0xa0, 0x20, 0x80, 0x00 225146482Smarius}; 226146482Smarius 227191076Smariusstatic const char *const machfb_memtype_names[] = { 228146482Smarius "(N/A)", "DRAM", "EDO DRAM", "EDO DRAM", "SDRAM", "SGRAM", "WRAM", 229146482Smarius "(unknown type)" 230146482Smarius}; 231146482Smarius 232170840Smariusextern const struct gfb_font gallant12x22; 233170840Smarius 234146482Smariusstatic struct machfb_softc machfb_softc; 235146482Smariusstatic struct bus_space_tag machfb_bst_store[1]; 236146482Smarius 237146482Smariusstatic device_probe_t machfb_pci_probe; 238146482Smariusstatic device_attach_t machfb_pci_attach; 239146482Smariusstatic device_detach_t machfb_pci_detach; 240146482Smarius 241146482Smariusstatic device_method_t machfb_methods[] = { 242146482Smarius /* Device interface */ 243146482Smarius DEVMETHOD(device_probe, machfb_pci_probe), 244146482Smarius DEVMETHOD(device_attach, machfb_pci_attach), 245146482Smarius DEVMETHOD(device_detach, machfb_pci_detach), 246146482Smarius 247146482Smarius { 0, 0 } 248146482Smarius}; 249146482Smarius 250146482Smariusstatic driver_t machfb_pci_driver = { 251146482Smarius MACHFB_DRIVER_NAME, 252146482Smarius machfb_methods, 253146482Smarius sizeof(struct machfb_softc), 254146482Smarius}; 255146482Smarius 256146482Smariusstatic devclass_t machfb_devclass; 257146482Smarius 258146482SmariusDRIVER_MODULE(machfb, pci, machfb_pci_driver, machfb_devclass, 0, 0); 259146482SmariusMODULE_DEPEND(machfb, pci, 1, 1, 1); 260146482Smarius 261146482Smariusstatic void machfb_cursor_enable(struct machfb_softc *, int); 262146482Smariusstatic int machfb_cursor_install(struct machfb_softc *); 263146482Smariusstatic int machfb_get_memsize(struct machfb_softc *); 264146482Smariusstatic void machfb_reset_engine(struct machfb_softc *); 265146482Smariusstatic void machfb_init_engine(struct machfb_softc *); 266146482Smarius#if 0 267146482Smariusstatic void machfb_adjust_frame(struct machfb_softc *, int, int); 268146482Smarius#endif 269146971Smariusstatic void machfb_shutdown_final(void *); 270146971Smariusstatic void machfb_shutdown_reset(void *); 271146482Smarius 272146971Smariusstatic int machfb_configure(int); 273146482Smarius 274146482Smariusstatic vi_probe_t machfb_probe; 275146482Smariusstatic vi_init_t machfb_init; 276146482Smariusstatic vi_get_info_t machfb_get_info; 277146482Smariusstatic vi_query_mode_t machfb_query_mode; 278146482Smariusstatic vi_set_mode_t machfb_set_mode; 279146482Smariusstatic vi_save_font_t machfb_save_font; 280146482Smariusstatic vi_load_font_t machfb_load_font; 281146482Smariusstatic vi_show_font_t machfb_show_font; 282146482Smariusstatic vi_save_palette_t machfb_save_palette; 283146482Smariusstatic vi_load_palette_t machfb_load_palette; 284146482Smariusstatic vi_set_border_t machfb_set_border; 285146482Smariusstatic vi_save_state_t machfb_save_state; 286146482Smariusstatic vi_load_state_t machfb_load_state; 287146482Smariusstatic vi_set_win_org_t machfb_set_win_org; 288146482Smariusstatic vi_read_hw_cursor_t machfb_read_hw_cursor; 289146482Smariusstatic vi_set_hw_cursor_t machfb_set_hw_cursor; 290146482Smariusstatic vi_set_hw_cursor_shape_t machfb_set_hw_cursor_shape; 291146482Smariusstatic vi_blank_display_t machfb_blank_display; 292146482Smariusstatic vi_mmap_t machfb_mmap; 293146482Smariusstatic vi_ioctl_t machfb_ioctl; 294146482Smariusstatic vi_clear_t machfb_clear; 295146482Smariusstatic vi_fill_rect_t machfb_fill_rect; 296146482Smariusstatic vi_bitblt_t machfb_bitblt; 297146482Smariusstatic vi_diag_t machfb_diag; 298146482Smariusstatic vi_save_cursor_palette_t machfb_save_cursor_palette; 299146482Smariusstatic vi_load_cursor_palette_t machfb_load_cursor_palette; 300146482Smariusstatic vi_copy_t machfb_copy; 301146482Smariusstatic vi_putp_t machfb_putp; 302146482Smariusstatic vi_putc_t machfb_putc; 303146482Smariusstatic vi_puts_t machfb_puts; 304146482Smariusstatic vi_putm_t machfb_putm; 305146482Smarius 306146482Smariusstatic video_switch_t machfbvidsw = { 307146482Smarius .probe = machfb_probe, 308146482Smarius .init = machfb_init, 309146482Smarius .get_info = machfb_get_info, 310146482Smarius .query_mode = machfb_query_mode, 311146482Smarius .set_mode = machfb_set_mode, 312146482Smarius .save_font = machfb_save_font, 313146482Smarius .load_font = machfb_load_font, 314146482Smarius .show_font = machfb_show_font, 315146482Smarius .save_palette = machfb_save_palette, 316146482Smarius .load_palette = machfb_load_palette, 317146482Smarius .set_border = machfb_set_border, 318146482Smarius .save_state = machfb_save_state, 319146482Smarius .load_state = machfb_load_state, 320146482Smarius .set_win_org = machfb_set_win_org, 321146482Smarius .read_hw_cursor = machfb_read_hw_cursor, 322146482Smarius .set_hw_cursor = machfb_set_hw_cursor, 323146482Smarius .set_hw_cursor_shape = machfb_set_hw_cursor_shape, 324146482Smarius .blank_display = machfb_blank_display, 325146482Smarius .mmap = machfb_mmap, 326146482Smarius .ioctl = machfb_ioctl, 327146482Smarius .clear = machfb_clear, 328146482Smarius .fill_rect = machfb_fill_rect, 329146482Smarius .bitblt = machfb_bitblt, 330146482Smarius .diag = machfb_diag, 331146482Smarius .save_cursor_palette = machfb_save_cursor_palette, 332146482Smarius .load_cursor_palette = machfb_load_cursor_palette, 333146482Smarius .copy = machfb_copy, 334146482Smarius .putp = machfb_putp, 335146482Smarius .putc = machfb_putc, 336146482Smarius .puts = machfb_puts, 337146482Smarius .putm = machfb_putm 338146482Smarius}; 339146482Smarius 340146482SmariusVIDEO_DRIVER(machfb, machfbvidsw, machfb_configure); 341146482Smarius 342146482Smariusextern sc_rndr_sw_t txtrndrsw; 343146482SmariusRENDERER(machfb, 0, txtrndrsw, gfb_set); 344146482Smarius 345146482SmariusRENDERER_MODULE(machfb, gfb_set); 346146482Smarius 347146482Smarius/* 348146482Smarius * Inline functions for getting access to register aperture. 349146482Smarius */ 350146482Smariusstatic inline uint32_t regr(struct machfb_softc *, uint32_t); 351146482Smariusstatic inline uint8_t regrb(struct machfb_softc *, uint32_t); 352146482Smariusstatic inline void regw(struct machfb_softc *, uint32_t, uint32_t); 353146482Smariusstatic inline void regwb(struct machfb_softc *, uint32_t, uint8_t); 354146482Smariusstatic inline void regwb_pll(struct machfb_softc *, uint32_t, uint8_t); 355146482Smarius 356146482Smariusstatic inline uint32_t 357146482Smariusregr(struct machfb_softc *sc, uint32_t index) 358146482Smarius{ 359146482Smarius 360146482Smarius return bus_space_read_4(sc->sc_regt, sc->sc_regh, index); 361146482Smarius} 362146482Smarius 363146482Smariusstatic inline uint8_t 364146482Smariusregrb(struct machfb_softc *sc, uint32_t index) 365146482Smarius{ 366146482Smarius 367146482Smarius return bus_space_read_1(sc->sc_regt, sc->sc_regh, index); 368146482Smarius} 369146482Smarius 370146482Smariusstatic inline void 371146482Smariusregw(struct machfb_softc *sc, uint32_t index, uint32_t data) 372146482Smarius{ 373146482Smarius 374146482Smarius bus_space_write_4(sc->sc_regt, sc->sc_regh, index, data); 375146482Smarius bus_space_barrier(sc->sc_regt, sc->sc_regh, index, 4, 376146482Smarius BUS_SPACE_BARRIER_WRITE); 377146482Smarius} 378146482Smarius 379146482Smariusstatic inline void 380146482Smariusregwb(struct machfb_softc *sc, uint32_t index, uint8_t data) 381146482Smarius{ 382146482Smarius 383146482Smarius bus_space_write_1(sc->sc_regt, sc->sc_regh, index, data); 384146482Smarius bus_space_barrier(sc->sc_regt, sc->sc_regh, index, 1, 385146482Smarius BUS_SPACE_BARRIER_WRITE); 386146482Smarius} 387146482Smarius 388146482Smariusstatic inline void 389146482Smariusregwb_pll(struct machfb_softc *sc, uint32_t index, uint8_t data) 390146482Smarius{ 391146482Smarius 392146482Smarius regwb(sc, CLOCK_CNTL + 1, (index << 2) | PLL_WR_EN); 393146482Smarius regwb(sc, CLOCK_CNTL + 2, data); 394146482Smarius regwb(sc, CLOCK_CNTL + 1, (index << 2) & ~PLL_WR_EN); 395146482Smarius} 396146482Smarius 397146482Smariusstatic inline void 398146482Smariuswait_for_fifo(struct machfb_softc *sc, uint8_t v) 399146482Smarius{ 400146482Smarius 401146482Smarius while ((regr(sc, FIFO_STAT) & 0xffff) > (0x8000 >> v)) 402146482Smarius ; 403146482Smarius} 404146482Smarius 405146482Smariusstatic inline void 406146482Smariuswait_for_idle(struct machfb_softc *sc) 407146482Smarius{ 408146482Smarius 409146482Smarius wait_for_fifo(sc, 16); 410146482Smarius while ((regr(sc, GUI_STAT) & 1) != 0) 411146482Smarius ; 412146482Smarius} 413146482Smarius 414146482Smarius/* 415147881Smarius * Inline functions for setting the background and foreground colors. 416147881Smarius */ 417147881Smariusstatic inline void machfb_setbg(struct machfb_softc *sc, int bg); 418147881Smariusstatic inline void machfb_setfg(struct machfb_softc *sc, int fg); 419147881Smarius 420147881Smariusstatic inline void 421147881Smariusmachfb_setbg(struct machfb_softc *sc, int bg) 422147881Smarius{ 423147881Smarius 424147881Smarius if (bg == sc->sc_bg_cache) 425147881Smarius return; 426147881Smarius sc->sc_bg_cache = bg; 427147881Smarius wait_for_fifo(sc, 1); 428147881Smarius regw(sc, DP_BKGD_CLR, bg + MACHFB_CMAP_OFF); 429147881Smarius} 430147881Smarius 431147881Smariusstatic inline void 432147881Smariusmachfb_setfg(struct machfb_softc *sc, int fg) 433147881Smarius{ 434147881Smarius 435147881Smarius if (fg == sc->sc_fg_cache) 436147881Smarius return; 437147881Smarius sc->sc_fg_cache = fg; 438147881Smarius wait_for_fifo(sc, 1); 439147881Smarius regw(sc, DP_FRGD_CLR, fg + MACHFB_CMAP_OFF); 440147881Smarius} 441147881Smarius 442147881Smarius/* 443146482Smarius * video driver interface 444146482Smarius */ 445146482Smariusstatic int 446146482Smariusmachfb_configure(int flags) 447146482Smarius{ 448146482Smarius struct machfb_softc *sc; 449146482Smarius phandle_t chosen, output; 450146482Smarius ihandle_t stdout; 451146482Smarius bus_addr_t addr; 452146482Smarius uint32_t id; 453146482Smarius int i, space; 454146482Smarius 455146971Smarius /* 456146971Smarius * For the high-level console probing return the number of 457146971Smarius * registered adapters. 458146971Smarius */ 459146971Smarius if (!(flags & VIO_PROBE_ONLY)) { 460146971Smarius for (i = 0; vid_find_adapter(MACHFB_DRIVER_NAME, i) >= 0; i++) 461146971Smarius ; 462146971Smarius return (i); 463146971Smarius } 464146971Smarius 465146971Smarius /* Low-level console probing and initialization. */ 466146971Smarius 467146482Smarius sc = &machfb_softc; 468146971Smarius if (sc->sc_va.va_flags & V_ADP_REGISTERED) 469146971Smarius goto found; 470146482Smarius 471146482Smarius if ((chosen = OF_finddevice("/chosen")) == -1) /* Quis contra nos? */ 472146482Smarius return (0); 473146482Smarius if (OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) == -1) 474146482Smarius return (0); 475146482Smarius if ((output = OF_instance_to_package(stdout)) == -1) 476146482Smarius return (0); 477146482Smarius if ((OF_getprop(output, "vendor-id", &id, sizeof(id)) == -1) || 478146482Smarius id != ATI_VENDOR) 479146482Smarius return (0); 480146482Smarius if (OF_getprop(output, "device-id", &id, sizeof(id)) == -1) 481146482Smarius return (0); 482146482Smarius for (i = 0; i < sizeof(machfb_info) / sizeof(machfb_info[0]); i++) { 483146482Smarius if (id == machfb_info[i].chip_id) { 484146482Smarius sc->sc_flags = MACHFB_CONSOLE; 485146482Smarius sc->sc_node = output; 486146482Smarius sc->sc_chip_id = id; 487146482Smarius break; 488146482Smarius } 489146482Smarius } 490146482Smarius if (!(sc->sc_flags & MACHFB_CONSOLE)) 491146482Smarius return (0); 492146482Smarius 493146482Smarius if (OF_getprop(output, "revision-id", &sc->sc_chip_rev, 494146482Smarius sizeof(sc->sc_chip_rev)) == -1) 495146482Smarius return (0); 496146482Smarius if (OF_decode_addr(output, 0, &space, &addr) != 0) 497146482Smarius return (0); 498146482Smarius sc->sc_memt = &machfb_bst_store[0]; 499146482Smarius sc->sc_memh = sparc64_fake_bustag(space, addr, sc->sc_memt); 500146482Smarius sc->sc_regt = sc->sc_memt; 501146482Smarius bus_space_subregion(sc->sc_regt, sc->sc_memh, MACH64_REG_OFF, 502146482Smarius MACH64_REG_SIZE, &sc->sc_regh); 503146482Smarius 504146482Smarius if (machfb_init(0, &sc->sc_va, 0) < 0) 505146482Smarius return (0); 506146482Smarius 507146482Smarius found: 508146482Smarius /* Return number of found adapters. */ 509146482Smarius return (1); 510146482Smarius} 511146482Smarius 512146482Smariusstatic int 513146482Smariusmachfb_probe(int unit, video_adapter_t **adpp, void *arg, int flags) 514146482Smarius{ 515146482Smarius 516146482Smarius return (0); 517146482Smarius} 518146482Smarius 519146482Smariusstatic int 520146482Smariusmachfb_init(int unit, video_adapter_t *adp, int flags) 521146482Smarius{ 522146482Smarius struct machfb_softc *sc; 523146482Smarius phandle_t options; 524146482Smarius video_info_t *vi; 525146482Smarius char buf[32]; 526147881Smarius int i; 527147881Smarius uint8_t dac_mask, dac_rindex, dac_windex; 528146482Smarius 529146482Smarius sc = (struct machfb_softc *)adp; 530146482Smarius vi = &adp->va_info; 531146482Smarius 532146482Smarius if ((regr(sc, CONFIG_CHIP_ID) & 0xffff) != sc->sc_chip_id) 533146482Smarius return (ENXIO); 534146482Smarius 535146482Smarius sc->sc_ramdac_freq = 0; 536146482Smarius for (i = 0; i < sizeof(machfb_info) / sizeof(machfb_info[0]); i++) { 537146482Smarius if (sc->sc_chip_id == machfb_info[i].chip_id) { 538146482Smarius sc->sc_ramdac_freq = machfb_info[i].ramdac_freq; 539146482Smarius break; 540146482Smarius } 541146482Smarius } 542146482Smarius if (sc->sc_ramdac_freq == 0) 543146482Smarius return (ENXIO); 544146482Smarius if (sc->sc_chip_id == ATI_RAGE_II && sc->sc_chip_rev & 0x07) 545146482Smarius sc->sc_ramdac_freq = 170000; 546146482Smarius 547146482Smarius vid_init_struct(adp, MACHFB_DRIVER_NAME, -1, unit); 548146482Smarius 549191072Smarius if (OF_getprop(sc->sc_node, "height", &sc->sc_height, 550146482Smarius sizeof(sc->sc_height)) == -1) 551146482Smarius return (ENXIO); 552146482Smarius if (OF_getprop(sc->sc_node, "width", &sc->sc_width, 553146482Smarius sizeof(sc->sc_width)) == -1) 554146482Smarius return (ENXIO); 555146482Smarius if (OF_getprop(sc->sc_node, "depth", &sc->sc_depth, 556146482Smarius sizeof(sc->sc_depth)) == -1) 557146482Smarius return (ENXIO); 558146482Smarius if ((options = OF_finddevice("/options")) == -1) 559146482Smarius return (ENXIO); 560146482Smarius if (OF_getprop(options, "screen-#rows", buf, sizeof(buf)) == -1) 561146482Smarius return (ENXIO); 562146482Smarius vi->vi_height = strtol(buf, NULL, 10); 563146482Smarius if (OF_getprop(options, "screen-#columns", buf, sizeof(buf)) == -1) 564146482Smarius return (ENXIO); 565146482Smarius vi->vi_width = strtol(buf, NULL, 10); 566170840Smarius vi->vi_cwidth = gallant12x22.width; 567170840Smarius vi->vi_cheight = gallant12x22.height; 568146482Smarius vi->vi_flags = V_INFO_COLOR; 569146482Smarius vi->vi_mem_model = V_INFO_MM_OTHER; 570146482Smarius 571170840Smarius sc->sc_font = gallant12x22.data; 572170840Smarius sc->sc_cbwidth = howmany(vi->vi_cwidth, NBBY); /* width in bytes */ 573146482Smarius sc->sc_xmargin = (sc->sc_width - (vi->vi_width * vi->vi_cwidth)) / 2; 574146482Smarius sc->sc_ymargin = (sc->sc_height - (vi->vi_height * vi->vi_cheight)) / 2; 575146482Smarius 576146482Smarius if (sc->sc_chip_id != ATI_MACH64_CT && 577146482Smarius !((sc->sc_chip_id == ATI_MACH64_VT || 578146482Smarius sc->sc_chip_id == ATI_RAGE_II) && 579146482Smarius (sc->sc_chip_rev & 0x07) == 0)) 580146482Smarius sc->sc_flags |= MACHFB_DSP; 581146482Smarius 582146482Smarius sc->sc_memsize = machfb_get_memsize(sc); 583146482Smarius if (sc->sc_memsize == 8192) 584146482Smarius /* The last page is used as register aperture. */ 585146482Smarius sc->sc_memsize -= 4; 586146482Smarius sc->sc_memtype = regr(sc, CONFIG_STAT0) & 0x07; 587146482Smarius 588146482Smarius if ((sc->sc_chip_id >= ATI_RAGE_XC_PCI66 && 589146482Smarius sc->sc_chip_id <= ATI_RAGE_XL_PCI66) || 590146482Smarius (sc->sc_chip_id >= ATI_RAGE_XL_PCI && 591146482Smarius sc->sc_chip_id <= ATI_RAGE_XC_PCI)) 592146482Smarius sc->sc_ref_freq = 29498; 593146482Smarius else 594146482Smarius sc->sc_ref_freq = 14318; 595146482Smarius 596146482Smarius regwb(sc, CLOCK_CNTL + 1, PLL_REF_DIV << 2); 597146482Smarius sc->sc_ref_div = regrb(sc, CLOCK_CNTL + 2); 598146482Smarius regwb(sc, CLOCK_CNTL + 1, MCLK_FB_DIV << 2); 599146482Smarius sc->sc_mclk_fb_div = regrb(sc, CLOCK_CNTL + 2); 600146482Smarius sc->sc_mem_freq = (2 * sc->sc_ref_freq * sc->sc_mclk_fb_div) / 601146482Smarius (sc->sc_ref_div * 2); 602146482Smarius sc->sc_mclk_post_div = (sc->sc_mclk_fb_div * 2 * sc->sc_ref_freq) / 603146482Smarius (sc->sc_mem_freq * sc->sc_ref_div); 604146482Smarius 605146482Smarius machfb_init_engine(sc); 606146482Smarius#if 0 607191072Smarius machfb_adjust_frame(0, 0); 608146482Smarius#endif 609147881Smarius machfb_set_mode(adp, 0); 610146482Smarius 611147881Smarius /* 612191072Smarius * Install our 16-color color map. This is done only once and with 613147881Smarius * an offset of 16 on sparc64 as there the OBP driver expects white 614147881Smarius * to be at index 0 and black at 255 (some versions also use 1 - 8 615147881Smarius * for color text support or the full palette for the boot banner 616147881Smarius * logo but no versions seems to use the ISO 6429-1983 color map). 617147881Smarius * Otherwise the colors are inverted when back in the OFW. 618147881Smarius */ 619147881Smarius dac_rindex = regrb(sc, DAC_RINDEX); 620147881Smarius dac_windex = regrb(sc, DAC_WINDEX); 621147881Smarius dac_mask = regrb(sc, DAC_MASK); 622147881Smarius regwb(sc, DAC_MASK, 0xff); 623147881Smarius regwb(sc, DAC_WINDEX, MACHFB_CMAP_OFF); 624147881Smarius for (i = 0; i < 16; i++) { 625147881Smarius regwb(sc, DAC_DATA, machfb_default_cmap[i].red); 626147881Smarius regwb(sc, DAC_DATA, machfb_default_cmap[i].green); 627147881Smarius regwb(sc, DAC_DATA, machfb_default_cmap[i].blue); 628147881Smarius } 629147881Smarius regwb(sc, DAC_MASK, dac_mask); 630147881Smarius regwb(sc, DAC_RINDEX, dac_rindex); 631147881Smarius regwb(sc, DAC_WINDEX, dac_windex); 632146482Smarius 633147881Smarius machfb_blank_display(adp, V_DISPLAY_ON); 634147881Smarius machfb_clear(adp); 635146482Smarius 636147881Smarius /* 637147881Smarius * Setting V_ADP_MODECHANGE serves as hack so machfb_set_mode() 638147881Smarius * (which will invalidate our caches) is called as a precaution 639147881Smarius * when the X server shuts down. 640147881Smarius */ 641147881Smarius adp->va_flags |= V_ADP_COLOR | V_ADP_MODECHANGE | V_ADP_PALETTE | 642147881Smarius V_ADP_BORDER | V_ADP_INITIALIZED; 643146482Smarius if (vid_register(adp) < 0) 644146482Smarius return (ENXIO); 645146482Smarius adp->va_flags |= V_ADP_REGISTERED; 646146482Smarius 647146482Smarius return (0); 648146482Smarius} 649146482Smarius 650146482Smariusstatic int 651146482Smariusmachfb_get_info(video_adapter_t *adp, int mode, video_info_t *info) 652146482Smarius{ 653146482Smarius 654146482Smarius bcopy(&adp->va_info, info, sizeof(*info)); 655146482Smarius 656146482Smarius return (0); 657146482Smarius} 658146482Smarius 659146482Smariusstatic int 660146482Smariusmachfb_query_mode(video_adapter_t *adp, video_info_t *info) 661146482Smarius{ 662146482Smarius 663146482Smarius return (ENODEV); 664146482Smarius} 665146482Smarius 666146482Smariusstatic int 667146482Smariusmachfb_set_mode(video_adapter_t *adp, int mode) 668146482Smarius{ 669147881Smarius struct machfb_softc *sc; 670146482Smarius 671147881Smarius sc = (struct machfb_softc *)adp; 672147881Smarius 673147881Smarius sc->sc_bg_cache = -1; 674147881Smarius sc->sc_fg_cache = -1; 675191076Smarius sc->sc_draw_cache = 0; 676147881Smarius 677147881Smarius return (0); 678146482Smarius} 679146482Smarius 680146482Smariusstatic int 681150686Smariusmachfb_save_font(video_adapter_t *adp, int page, int size, int width, 682150686Smarius u_char *data, int c, int count) 683146482Smarius{ 684146482Smarius 685146482Smarius return (ENODEV); 686146482Smarius} 687146482Smarius 688146482Smariusstatic int 689150686Smariusmachfb_load_font(video_adapter_t *adp, int page, int size, int width, 690150686Smarius u_char *data, int c, int count) 691146482Smarius{ 692146482Smarius 693146482Smarius return (ENODEV); 694146482Smarius} 695146482Smarius 696146482Smariusstatic int 697146482Smariusmachfb_show_font(video_adapter_t *adp, int page) 698146482Smarius{ 699146482Smarius 700146482Smarius return (ENODEV); 701146482Smarius} 702146482Smarius 703146482Smariusstatic int 704146482Smariusmachfb_save_palette(video_adapter_t *adp, u_char *palette) 705146482Smarius{ 706147881Smarius struct machfb_softc *sc; 707147881Smarius int i; 708147881Smarius uint8_t dac_mask, dac_rindex, dac_windex; 709146482Smarius 710147881Smarius sc = (struct machfb_softc *)adp; 711147881Smarius 712147881Smarius dac_rindex = regrb(sc, DAC_RINDEX); 713147881Smarius dac_windex = regrb(sc, DAC_WINDEX); 714147881Smarius dac_mask = regrb(sc, DAC_MASK); 715147881Smarius regwb(sc, DAC_MASK, 0xff); 716147881Smarius regwb(sc, DAC_RINDEX, 0x0); 717147881Smarius for (i = 0; i < 256 * 3; i++) 718147881Smarius palette[i] = regrb(sc, DAC_DATA); 719147881Smarius regwb(sc, DAC_MASK, dac_mask); 720147881Smarius regwb(sc, DAC_RINDEX, dac_rindex); 721147881Smarius regwb(sc, DAC_WINDEX, dac_windex); 722147881Smarius 723147881Smarius return (0); 724146482Smarius} 725146482Smarius 726146482Smariusstatic int 727146482Smariusmachfb_load_palette(video_adapter_t *adp, u_char *palette) 728146482Smarius{ 729147881Smarius struct machfb_softc *sc; 730147881Smarius int i; 731147881Smarius uint8_t dac_mask, dac_rindex, dac_windex; 732146482Smarius 733147881Smarius sc = (struct machfb_softc *)adp; 734147881Smarius 735147881Smarius dac_rindex = regrb(sc, DAC_RINDEX); 736147881Smarius dac_windex = regrb(sc, DAC_WINDEX); 737147881Smarius dac_mask = regrb(sc, DAC_MASK); 738147881Smarius regwb(sc, DAC_MASK, 0xff); 739147881Smarius regwb(sc, DAC_WINDEX, 0x0); 740147881Smarius for (i = 0; i < 256 * 3; i++) 741147881Smarius regwb(sc, DAC_DATA, palette[i]); 742147881Smarius regwb(sc, DAC_MASK, dac_mask); 743147881Smarius regwb(sc, DAC_RINDEX, dac_rindex); 744147881Smarius regwb(sc, DAC_WINDEX, dac_windex); 745147881Smarius 746147881Smarius return (0); 747146482Smarius} 748146482Smarius 749146482Smariusstatic int 750146482Smariusmachfb_set_border(video_adapter_t *adp, int border) 751146482Smarius{ 752146482Smarius struct machfb_softc *sc; 753146482Smarius 754146482Smarius sc = (struct machfb_softc *)adp; 755146482Smarius 756146482Smarius machfb_fill_rect(adp, border, 0, 0, sc->sc_width, sc->sc_ymargin); 757146482Smarius machfb_fill_rect(adp, border, 0, sc->sc_height - sc->sc_ymargin, 758146482Smarius sc->sc_width, sc->sc_ymargin); 759146482Smarius machfb_fill_rect(adp, border, 0, 0, sc->sc_xmargin, sc->sc_height); 760146482Smarius machfb_fill_rect(adp, border, sc->sc_width - sc->sc_xmargin, 0, 761146482Smarius sc->sc_xmargin, sc->sc_height); 762146482Smarius 763146482Smarius return (0); 764146482Smarius} 765146482Smarius 766146482Smariusstatic int 767146482Smariusmachfb_save_state(video_adapter_t *adp, void *p, size_t size) 768146482Smarius{ 769146482Smarius 770146482Smarius return (ENODEV); 771146482Smarius} 772146482Smarius 773146482Smariusstatic int 774146482Smariusmachfb_load_state(video_adapter_t *adp, void *p) 775146482Smarius{ 776146482Smarius 777146482Smarius return (ENODEV); 778146482Smarius} 779146482Smarius 780146482Smariusstatic int 781146482Smariusmachfb_set_win_org(video_adapter_t *adp, off_t offset) 782146482Smarius{ 783146482Smarius 784146482Smarius return (ENODEV); 785146482Smarius} 786146482Smarius 787146482Smariusstatic int 788146482Smariusmachfb_read_hw_cursor(video_adapter_t *adp, int *col, int *row) 789146482Smarius{ 790146482Smarius 791146482Smarius *col = 0; 792146482Smarius *row = 0; 793146482Smarius 794146482Smarius return (0); 795146482Smarius} 796146482Smarius 797146482Smariusstatic int 798146482Smariusmachfb_set_hw_cursor(video_adapter_t *adp, int col, int row) 799146482Smarius{ 800146482Smarius 801146482Smarius return (ENODEV); 802146482Smarius} 803146482Smarius 804146482Smariusstatic int 805146482Smariusmachfb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, 806146482Smarius int celsize, int blink) 807146482Smarius{ 808146482Smarius 809146482Smarius return (ENODEV); 810146482Smarius} 811146482Smarius 812146482Smariusstatic int 813146482Smariusmachfb_blank_display(video_adapter_t *adp, int mode) 814146482Smarius{ 815146482Smarius struct machfb_softc *sc; 816147881Smarius uint32_t crtc_gen_cntl; 817146482Smarius 818146482Smarius sc = (struct machfb_softc *)adp; 819146482Smarius 820147881Smarius crtc_gen_cntl = (regr(sc, CRTC_GEN_CNTL) | CRTC_EXT_DISP_EN | CRTC_EN) & 821147881Smarius ~(CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS); 822147881Smarius switch (mode) { 823147881Smarius case V_DISPLAY_ON: 824147881Smarius break; 825147881Smarius case V_DISPLAY_BLANK: 826147881Smarius crtc_gen_cntl |= CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | 827147881Smarius CRTC_DISPLAY_DIS; 828147881Smarius break; 829147881Smarius case V_DISPLAY_STAND_BY: 830147881Smarius crtc_gen_cntl |= CRTC_HSYNC_DIS | CRTC_DISPLAY_DIS; 831147881Smarius break; 832147881Smarius case V_DISPLAY_SUSPEND: 833147881Smarius crtc_gen_cntl |= CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS; 834147881Smarius break; 835147881Smarius } 836147881Smarius regw(sc, CRTC_GEN_CNTL, crtc_gen_cntl); 837146482Smarius 838146482Smarius return (0); 839146482Smarius} 840146482Smarius 841146482Smariusstatic int 842201223Srnolandmachfb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, 843201223Srnoland int prot, vm_memattr_t *memattr) 844146482Smarius{ 845146482Smarius struct machfb_softc *sc; 846191076Smarius video_info_t *vi; 847146482Smarius 848146482Smarius sc = (struct machfb_softc *)adp; 849191076Smarius vi = &adp->va_info; 850146482Smarius 851191076Smarius /* BAR 2 - VGA memory */ 852191076Smarius if (sc->sc_vmem != 0 && offset >= sc->sc_vmem && 853191076Smarius offset < sc->sc_vmem + vi->vi_registers_size) { 854191076Smarius *paddr = vi->vi_registers + offset - sc->sc_vmem; 855146482Smarius return (0); 856146482Smarius } 857146482Smarius 858191076Smarius /* BAR 0 - framebuffer */ 859191076Smarius if (offset >= sc->sc_mem && 860191076Smarius offset < sc->sc_mem + vi->vi_buffer_size) { 861191076Smarius *paddr = vi->vi_buffer + offset - sc->sc_mem; 862146482Smarius return (0); 863146482Smarius } 864146482Smarius 865146482Smarius /* 'regular' framebuffer mmap()ing */ 866146482Smarius if (offset < adp->va_window_size) { 867191076Smarius *paddr = vi->vi_window + offset; 868146482Smarius return (0); 869146482Smarius } 870146482Smarius 871146482Smarius return (EINVAL); 872146482Smarius} 873146482Smarius 874146482Smariusstatic int 875146482Smariusmachfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) 876146482Smarius{ 877146482Smarius struct machfb_softc *sc; 878146482Smarius struct fbcursor *fbc; 879146482Smarius struct fbtype *fb; 880146482Smarius 881146482Smarius sc = (struct machfb_softc *)adp; 882146482Smarius 883146482Smarius switch (cmd) { 884146482Smarius case FBIOGTYPE: 885146482Smarius fb = (struct fbtype *)data; 886146482Smarius fb->fb_type = FBTYPE_PCIMISC; 887146482Smarius fb->fb_height = sc->sc_height; 888146482Smarius fb->fb_width = sc->sc_width; 889146482Smarius fb->fb_depth = sc->sc_depth; 890146482Smarius if (sc->sc_depth <= 1 || sc->sc_depth > 8) 891146482Smarius fb->fb_cmsize = 0; 892146482Smarius else 893146482Smarius fb->fb_cmsize = 1 << sc->sc_depth; 894146482Smarius fb->fb_size = adp->va_buffer_size; 895146482Smarius break; 896146482Smarius case FBIOSCURSOR: 897146482Smarius fbc = (struct fbcursor *)data; 898146971Smarius if (fbc->set & FB_CUR_SETCUR && fbc->enable == 0) { 899146971Smarius machfb_cursor_enable(sc, 0); 900146971Smarius sc->sc_flags &= ~MACHFB_CUREN; 901146971Smarius } else 902146971Smarius return (ENODEV); 903146482Smarius break; 904146482Smarius default: 905146482Smarius return (fb_commonioctl(adp, cmd, data)); 906146482Smarius } 907146482Smarius 908146482Smarius return (0); 909146482Smarius} 910146482Smarius 911146482Smariusstatic int 912146482Smariusmachfb_clear(video_adapter_t *adp) 913146482Smarius{ 914147881Smarius struct machfb_softc *sc; 915146482Smarius 916147881Smarius sc = (struct machfb_softc *)adp; 917147881Smarius 918147881Smarius machfb_fill_rect(adp, (SC_NORM_ATTR >> 4) & 0xf, 0, 0, sc->sc_width, 919147881Smarius sc->sc_height); 920147881Smarius 921147881Smarius return (0); 922146482Smarius} 923146482Smarius 924146482Smariusstatic int 925146482Smariusmachfb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) 926146482Smarius{ 927146482Smarius struct machfb_softc *sc; 928146482Smarius 929146482Smarius sc = (struct machfb_softc *)adp; 930146482Smarius 931146482Smarius if (sc->sc_draw_cache != MACHFB_DRAW_FILLRECT) { 932146482Smarius wait_for_fifo(sc, 7); 933146482Smarius regw(sc, DP_WRITE_MASK, 0xff); 934146482Smarius regw(sc, DP_PIX_WIDTH, DST_8BPP | SRC_8BPP | HOST_8BPP); 935146482Smarius regw(sc, DP_SRC, FRGD_SRC_FRGD_CLR); 936146482Smarius regw(sc, DP_MIX, MIX_SRC << 16); 937146482Smarius regw(sc, CLR_CMP_CNTL, 0); /* no transparency */ 938146482Smarius regw(sc, SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT); 939146482Smarius regw(sc, DST_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM); 940146482Smarius sc->sc_draw_cache = MACHFB_DRAW_FILLRECT; 941146482Smarius } 942147881Smarius machfb_setfg(sc, val); 943147881Smarius wait_for_fifo(sc, 4); 944146482Smarius regw(sc, SRC_Y_X, (x << 16) | y); 945146482Smarius regw(sc, SRC_WIDTH1, cx); 946146482Smarius regw(sc, DST_Y_X, (x << 16) | y); 947146482Smarius regw(sc, DST_HEIGHT_WIDTH, (cx << 16) | cy); 948146482Smarius 949146482Smarius return (0); 950146482Smarius} 951146482Smarius 952146482Smariusstatic int 953146482Smariusmachfb_bitblt(video_adapter_t *adp, ...) 954146482Smarius{ 955146482Smarius 956146482Smarius return (ENODEV); 957146482Smarius} 958146482Smarius 959146482Smariusstatic int 960146482Smariusmachfb_diag(video_adapter_t *adp, int level) 961146482Smarius{ 962146482Smarius video_info_t info; 963146482Smarius 964146482Smarius fb_dump_adp_info(adp->va_name, adp, level); 965146482Smarius machfb_get_info(adp, 0, &info); 966146482Smarius fb_dump_mode_info(adp->va_name, adp, &info, level); 967146482Smarius 968146482Smarius return (0); 969146482Smarius} 970146482Smarius 971146482Smariusstatic int 972146482Smariusmachfb_save_cursor_palette(video_adapter_t *adp, u_char *palette) 973146482Smarius{ 974146482Smarius 975146482Smarius return (ENODEV); 976146482Smarius} 977146482Smarius 978146482Smariusstatic int 979146482Smariusmachfb_load_cursor_palette(video_adapter_t *adp, u_char *palette) 980146482Smarius{ 981146482Smarius 982146482Smarius return (ENODEV); 983146482Smarius} 984146482Smarius 985146482Smariusstatic int 986146482Smariusmachfb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n) 987146482Smarius{ 988146482Smarius 989146482Smarius return (ENODEV); 990146482Smarius} 991146482Smarius 992146482Smariusstatic int 993146482Smariusmachfb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a, 994146482Smarius int size, int bpp, int bit_ltor, int byte_ltor) 995146482Smarius{ 996146482Smarius 997146482Smarius return (ENODEV); 998146482Smarius} 999146482Smarius 1000146482Smariusstatic int 1001146482Smariusmachfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) 1002146482Smarius{ 1003146482Smarius struct machfb_softc *sc; 1004170840Smarius const uint8_t *p; 1005146482Smarius int i; 1006146482Smarius 1007146482Smarius sc = (struct machfb_softc *)adp; 1008146482Smarius 1009146482Smarius if (sc->sc_draw_cache != MACHFB_DRAW_CHAR) { 1010146482Smarius wait_for_fifo(sc, 8); 1011146482Smarius regw(sc, DP_WRITE_MASK, 0xff); /* XXX only good for 8 bit */ 1012146482Smarius regw(sc, DP_PIX_WIDTH, DST_8BPP | SRC_1BPP | HOST_1BPP); 1013146482Smarius regw(sc, DP_SRC, MONO_SRC_HOST | BKGD_SRC_BKGD_CLR | 1014146482Smarius FRGD_SRC_FRGD_CLR); 1015146482Smarius regw(sc, DP_MIX ,((MIX_SRC & 0xffff) << 16) | MIX_SRC); 1016146482Smarius regw(sc, CLR_CMP_CNTL, 0); /* no transparency */ 1017146482Smarius regw(sc, SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT); 1018146482Smarius regw(sc, DST_CNTL, DST_Y_TOP_TO_BOTTOM | DST_X_LEFT_TO_RIGHT); 1019146482Smarius regw(sc, HOST_CNTL, HOST_BYTE_ALIGN); 1020146482Smarius sc->sc_draw_cache = MACHFB_DRAW_CHAR; 1021146482Smarius } 1022147881Smarius machfb_setbg(sc, (a >> 4) & 0xf); 1023147881Smarius machfb_setfg(sc, a & 0xf); 1024147881Smarius wait_for_fifo(sc, 4 + (adp->va_info.vi_cheight / sc->sc_cbwidth)); 1025146482Smarius regw(sc, SRC_Y_X, 0); 1026146482Smarius regw(sc, SRC_WIDTH1, adp->va_info.vi_cwidth); 1027146482Smarius regw(sc, DST_Y_X, ((((off % adp->va_info.vi_width) * 1028146482Smarius adp->va_info.vi_cwidth) + sc->sc_xmargin) << 16) | 1029146482Smarius (((off / adp->va_info.vi_width) * adp->va_info.vi_cheight) + 1030146482Smarius sc->sc_ymargin)); 1031146482Smarius regw(sc, DST_HEIGHT_WIDTH, (adp->va_info.vi_cwidth << 16) | 1032146482Smarius adp->va_info.vi_cheight); 1033147881Smarius p = sc->sc_font + (c * adp->va_info.vi_cheight * sc->sc_cbwidth); 1034146482Smarius for (i = 0; i < adp->va_info.vi_cheight * sc->sc_cbwidth; i += 4) 1035146482Smarius regw(sc, HOST_DATA0 + i, (p[i + 3] << 24 | p[i + 2] << 16 | 1036146482Smarius p[i + 1] << 8 | p[i])); 1037146482Smarius 1038146482Smarius return (0); 1039146482Smarius} 1040146482Smarius 1041146482Smariusstatic int 1042146482Smariusmachfb_puts(video_adapter_t *adp, vm_offset_t off, uint16_t *s, int len) 1043146482Smarius{ 1044146482Smarius struct machfb_softc *sc; 1045146482Smarius int blanks, i, x1, x2, y1, y2; 1046146482Smarius uint8_t a, c, color1, color2; 1047146482Smarius 1048146482Smarius sc = (struct machfb_softc *)adp; 1049146482Smarius 1050146482Smarius#define MACHFB_BLANK machfb_fill_rect(adp, color1, x1, y1, \ 1051146482Smarius blanks * adp->va_info.vi_cwidth, \ 1052146482Smarius adp->va_info.vi_cheight) 1053146482Smarius 1054146482Smarius blanks = color1 = x1 = y1 = 0; 1055146482Smarius for (i = 0; i < len; i++) { 1056146482Smarius /* 1057146482Smarius * Accelerate continuous blanks by drawing a respective 1058191072Smarius * rectangle instead. Drawing a rectangle of any size 1059146482Smarius * takes about the same number of operations as drawing 1060146482Smarius * a single character. 1061146482Smarius */ 1062146482Smarius c = s[i] & 0xff; 1063146482Smarius a = (s[i] & 0xff00) >> 8; 1064146482Smarius if (c == 0x00 || c == 0x20 || c == 0xdb || c == 0xff) { 1065146482Smarius color2 = (a >> (c == 0xdb ? 0 : 4) & 0xf); 1066191072Smarius x2 = (((off + i) % adp->va_info.vi_width) * 1067146482Smarius adp->va_info.vi_cwidth) + sc->sc_xmargin; 1068146482Smarius y2 = (((off + i) / adp->va_info.vi_width) * 1069146482Smarius adp->va_info.vi_cheight) + sc->sc_ymargin; 1070146482Smarius if (blanks == 0) { 1071146482Smarius color1 = color2; 1072146482Smarius x1 = x2; 1073146482Smarius y1 = y2; 1074146482Smarius blanks++; 1075146482Smarius } else if (color1 != color2 || y1 != y2) { 1076146482Smarius MACHFB_BLANK; 1077146482Smarius color1 = color2; 1078146482Smarius x1 = x2; 1079146482Smarius y1 = y2; 1080146482Smarius blanks = 1; 1081146482Smarius } else 1082146482Smarius blanks++; 1083146482Smarius } else { 1084146482Smarius if (blanks != 0) { 1085146482Smarius MACHFB_BLANK; 1086146482Smarius blanks = 0; 1087146482Smarius } 1088174985Swkoszek vidd_putc(adp, off + i, c, a); 1089146482Smarius } 1090146482Smarius } 1091146482Smarius if (blanks != 0) 1092146482Smarius MACHFB_BLANK; 1093146482Smarius 1094146482Smarius#undef MACHFB_BLANK 1095146482Smarius 1096146482Smarius return (0); 1097146482Smarius} 1098146482Smarius 1099146482Smariusstatic int 1100146482Smariusmachfb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, 1101150686Smarius uint32_t pixel_mask, int size, int width) 1102146482Smarius{ 1103146482Smarius struct machfb_softc *sc; 1104146482Smarius int error; 1105146482Smarius 1106146482Smarius sc = (struct machfb_softc *)adp; 1107146482Smarius 1108146482Smarius if ((!(sc->sc_flags & MACHFB_CUREN)) && 1109146482Smarius (error = machfb_cursor_install(sc)) < 0) 1110191072Smarius return (error); 1111146482Smarius else { 1112146482Smarius /* 1113146482Smarius * The hardware cursor always must be disabled when 1114146482Smarius * fiddling with its bits otherwise some artifacts 1115146482Smarius * may appear on the screen. 1116146482Smarius */ 1117146482Smarius machfb_cursor_enable(sc, 0); 1118146482Smarius } 1119146482Smarius 1120146482Smarius regw(sc, CUR_HORZ_VERT_OFF, 0); 1121146482Smarius if ((regr(sc, GEN_TEST_CNTL) & CRTC_DBL_SCAN_EN) != 0) 1122146482Smarius y <<= 1; 1123146482Smarius regw(sc, CUR_HORZ_VERT_POSN, ((y + sc->sc_ymargin) << 16) | 1124146482Smarius (x + sc->sc_xmargin)); 1125146482Smarius machfb_cursor_enable(sc, 1); 1126146482Smarius sc->sc_flags |= MACHFB_CUREN; 1127146482Smarius 1128146482Smarius return (0); 1129146482Smarius} 1130146482Smarius 1131146482Smarius/* 1132146482Smarius * PCI bus interface 1133146482Smarius */ 1134146482Smariusstatic int 1135146482Smariusmachfb_pci_probe(device_t dev) 1136146482Smarius{ 1137146482Smarius int i; 1138146482Smarius 1139146482Smarius if (pci_get_class(dev) != PCIC_DISPLAY || 1140146482Smarius pci_get_subclass(dev) != PCIS_DISPLAY_VGA) 1141146482Smarius return (ENXIO); 1142146482Smarius 1143146482Smarius for (i = 0; i < sizeof(machfb_info) / sizeof(machfb_info[0]); i++) { 1144146482Smarius if (pci_get_device(dev) == machfb_info[i].chip_id) { 1145146482Smarius device_set_desc(dev, machfb_info[i].name); 1146146482Smarius return (BUS_PROBE_DEFAULT); 1147146482Smarius } 1148146482Smarius } 1149191072Smarius 1150146482Smarius return (ENXIO); 1151146482Smarius} 1152146482Smarius 1153146482Smariusstatic int 1154146482Smariusmachfb_pci_attach(device_t dev) 1155146482Smarius{ 1156146482Smarius struct machfb_softc *sc; 1157146482Smarius video_adapter_t *adp; 1158146482Smarius video_switch_t *sw; 1159191076Smarius video_info_t *vi; 1160146482Smarius phandle_t node; 1161191076Smarius int error, i, rid; 1162191076Smarius uint32_t *p32, u32; 1163146482Smarius uint8_t *p; 1164146482Smarius 1165146482Smarius node = ofw_bus_get_node(dev); 1166146482Smarius if ((sc = (struct machfb_softc *)vid_get_adapter(vid_find_adapter( 1167146482Smarius MACHFB_DRIVER_NAME, 0))) != NULL && sc->sc_node == node) { 1168191072Smarius device_printf(dev, "console\n"); 1169191072Smarius device_set_softc(dev, sc); 1170146482Smarius } else { 1171146482Smarius sc = device_get_softc(dev); 1172146482Smarius 1173146482Smarius sc->sc_node = node; 1174146482Smarius sc->sc_chip_id = pci_get_device(dev); 1175146482Smarius sc->sc_chip_rev = pci_get_revid(dev); 1176146482Smarius } 1177146482Smarius adp = &sc->sc_va; 1178191076Smarius vi = &adp->va_info; 1179191072Smarius 1180191076Smarius rid = PCIR_BAR(0); 1181230687Smarius if ((sc->sc_memres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 1182230687Smarius RF_ACTIVE)) == NULL) { 1183146482Smarius device_printf(dev, "cannot allocate memory resources\n"); 1184146482Smarius return (ENXIO); 1185146482Smarius } 1186230687Smarius sc->sc_memt = rman_get_bustag(sc->sc_memres); 1187230687Smarius sc->sc_memh = rman_get_bushandle(sc->sc_memres); 1188230687Smarius sc->sc_mem = rman_get_start(sc->sc_memres); 1189230687Smarius vi->vi_buffer = sc->sc_memh; 1190230687Smarius vi->vi_buffer_size = rman_get_size(sc->sc_memres); 1191191076Smarius if (OF_getprop(sc->sc_node, "address", &u32, sizeof(u32)) > 0 && 1192230687Smarius vtophys(u32) == sc->sc_memh) 1193191076Smarius adp->va_mem_base = u32; 1194191076Smarius else { 1195230687Smarius if (bus_space_map(sc->sc_memt, vi->vi_buffer, 1196230687Smarius vi->vi_buffer_size, BUS_SPACE_MAP_LINEAR, 1197230687Smarius &sc->sc_memh) != 0) { 1198230687Smarius device_printf(dev, "cannot map memory resources\n"); 1199230687Smarius error = ENXIO; 1200230687Smarius goto fail_memres; 1201191076Smarius } 1202191076Smarius adp->va_mem_base = 1203191076Smarius (vm_offset_t)rman_get_virtual(sc->sc_memres); 1204191076Smarius } 1205230687Smarius adp->va_mem_size = vi->vi_buffer_size; 1206191076Smarius adp->va_buffer = adp->va_mem_base; 1207191076Smarius adp->va_buffer_size = adp->va_mem_size; 1208230687Smarius sc->sc_regt = sc->sc_memt; 1209230687Smarius if (bus_space_subregion(sc->sc_regt, sc->sc_memh, MACH64_REG_OFF, 1210230687Smarius MACH64_REG_SIZE, &sc->sc_regh) != 0) { 1211230687Smarius device_printf(dev, "cannot allocate register resources\n"); 1212230687Smarius error = ENXIO; 1213230687Smarius goto fail_memmap; 1214230687Smarius } 1215146482Smarius 1216146482Smarius /* 1217146482Smarius * Depending on the firmware version the VGA I/O and/or memory 1218230687Smarius * resources of the Mach64 chips come up disabled. These will be 1219230687Smarius * enabled by pci(4) when activating the resource in question but 1220230687Smarius * this doesn't necessarily mean that the resource is valid. 1221230687Smarius * Invalid resources seem to have in common that they start at 1222230687Smarius * address 0. We don't allocate the VGA memory in this case in 1223230687Smarius * order to avoid warnings in apb(4) and crashes when using this 1224230687Smarius * invalid resources. X.Org is aware of this and doesn't use the 1225230687Smarius * VGA memory resource in this case (but demands it if it's valid). 1226146482Smarius */ 1227191076Smarius rid = PCIR_BAR(2); 1228191076Smarius if (bus_get_resource_start(dev, SYS_RES_MEMORY, rid) != 0) { 1229146482Smarius if ((sc->sc_vmemres = bus_alloc_resource_any(dev, 1230191076Smarius SYS_RES_MEMORY, &rid, RF_ACTIVE)) == NULL) { 1231146482Smarius device_printf(dev, 1232146482Smarius "cannot allocate VGA memory resources\n"); 1233146482Smarius error = ENXIO; 1234230687Smarius goto fail_memmap; 1235146482Smarius } 1236230687Smarius sc->sc_vmemt = rman_get_bustag(sc->sc_vmemres); 1237230687Smarius sc->sc_vmemh = rman_get_bushandle(sc->sc_vmemres); 1238230687Smarius sc->sc_vmem = rman_get_start(sc->sc_vmemres); 1239230687Smarius vi->vi_registers = sc->sc_vmemh; 1240230687Smarius vi->vi_registers_size = rman_get_size(sc->sc_vmemres); 1241230687Smarius if (bus_space_map(sc->sc_vmemt, vi->vi_registers, 1242230687Smarius vi->vi_registers_size, BUS_SPACE_MAP_LINEAR, 1243230687Smarius &sc->sc_vmemh) != 0) { 1244230687Smarius device_printf(dev, 1245230687Smarius "cannot map VGA memory resources\n"); 1246230687Smarius error = ENXIO; 1247230687Smarius goto fail_vmemres; 1248230687Smarius } 1249191076Smarius adp->va_registers = 1250191076Smarius (vm_offset_t)rman_get_virtual(sc->sc_vmemres); 1251230687Smarius adp->va_registers_size = vi->vi_registers_size; 1252146482Smarius } 1253146482Smarius 1254146482Smarius if (!(sc->sc_flags & MACHFB_CONSOLE)) { 1255146482Smarius if ((sw = vid_get_switch(MACHFB_DRIVER_NAME)) == NULL) { 1256146482Smarius device_printf(dev, "cannot get video switch\n"); 1257146482Smarius error = ENODEV; 1258230687Smarius goto fail_vmemmap; 1259146482Smarius } 1260146482Smarius /* 1261146482Smarius * During device configuration we don't necessarily probe 1262146482Smarius * the adapter which is the console first so we can't use 1263191072Smarius * the device unit number for the video adapter unit. The 1264146482Smarius * worst case would be that we use the video adapter unit 1265191072Smarius * 0 twice. As it doesn't really matter which unit number 1266146482Smarius * the corresponding video adapter has just use the next 1267146482Smarius * unused one. 1268146482Smarius */ 1269146482Smarius for (i = 0; i < devclass_get_maxunit(machfb_devclass); i++) 1270146482Smarius if (vid_find_adapter(MACHFB_DRIVER_NAME, i) < 0) 1271146482Smarius break; 1272146482Smarius if ((error = sw->init(i, adp, 0)) != 0) { 1273146482Smarius device_printf(dev, "cannot initialize adapter\n"); 1274230687Smarius goto fail_vmemmap; 1275146482Smarius } 1276146482Smarius } 1277146482Smarius 1278146482Smarius /* 1279146482Smarius * Test whether the aperture is byte swapped or not, set 1280191076Smarius * va_window and va_window_size as appropriate. Note that 1281191076Smarius * the aperture could be mapped either big or little endian 1282230687Smarius * independently of the endianess of the host so this has 1283230687Smarius * to be a runtime test. 1284146482Smarius */ 1285146482Smarius p32 = (uint32_t *)adp->va_buffer; 1286191076Smarius u32 = *p32; 1287146482Smarius p = (uint8_t *)adp->va_buffer; 1288146482Smarius *p32 = 0x12345678; 1289146482Smarius if (!(p[0] == 0x12 && p[1] == 0x34 && p[2] == 0x56 && p[3] == 0x78)) { 1290146482Smarius adp->va_window = adp->va_buffer + 0x800000; 1291146482Smarius adp->va_window_size = adp->va_buffer_size - 0x800000; 1292191076Smarius vi->vi_window = vi->vi_buffer + 0x800000; 1293191076Smarius vi->vi_window_size = vi->vi_buffer_size - 0x800000; 1294191076Smarius sc->sc_flags |= MACHFB_SWAP; 1295146482Smarius } else { 1296146482Smarius adp->va_window = adp->va_buffer; 1297146482Smarius adp->va_window_size = adp->va_buffer_size; 1298191076Smarius vi->vi_window = vi->vi_buffer; 1299191076Smarius vi->vi_window_size = vi->vi_buffer_size; 1300146482Smarius } 1301191076Smarius *p32 = u32; 1302146482Smarius adp->va_window_gran = adp->va_window_size; 1303146482Smarius 1304191076Smarius device_printf(dev, 1305191076Smarius "%d MB aperture at %p %sswapped\n", 1306191076Smarius (u_int)(adp->va_window_size / (1024 * 1024)), 1307191076Smarius (void *)adp->va_window, (sc->sc_flags & MACHFB_SWAP) ? 1308191076Smarius "" : "not "); 1309191076Smarius device_printf(dev, 1310191076Smarius "%ld KB %s %d.%d MHz, maximum RAMDAC clock %d MHz, %sDSP\n", 1311191076Smarius (u_long)sc->sc_memsize, machfb_memtype_names[sc->sc_memtype], 1312191076Smarius sc->sc_mem_freq / 1000, sc->sc_mem_freq % 1000, 1313191076Smarius sc->sc_ramdac_freq / 1000, 1314191076Smarius (sc->sc_flags & MACHFB_DSP) ? "" : "no "); 1315191076Smarius device_printf(dev, "resolution %dx%d at %d bpp\n", 1316191076Smarius sc->sc_width, sc->sc_height, sc->sc_depth); 1317191076Smarius 1318146482Smarius /* 1319146482Smarius * Allocate one page for the mouse pointer image at the end of 1320146482Smarius * the little endian aperture, right before the memory mapped 1321191072Smarius * registers that might also reside there. Must be done after 1322146482Smarius * sc_memsize was set and possibly adjusted to account for the 1323146482Smarius * memory mapped registers. 1324146482Smarius */ 1325146482Smarius sc->sc_curoff = (sc->sc_memsize * 1024) - PAGE_SIZE; 1326146482Smarius sc->sc_memsize -= PAGE_SIZE / 1024; 1327146482Smarius machfb_cursor_enable(sc, 0); 1328146482Smarius /* Initialize with an all transparent image. */ 1329146482Smarius memset((void *)(adp->va_buffer + sc->sc_curoff), 0xaa, PAGE_SIZE); 1330146482Smarius 1331146482Smarius /* 1332146971Smarius * Register a handler that performs some cosmetic surgery like 1333146971Smarius * turning off the mouse pointer on halt in preparation for 1334191072Smarius * handing the screen over to the OFW. Register another handler 1335146971Smarius * that turns off the CRTC when resetting, otherwise the OFW 1336146971Smarius * boot command issued by cpu_reset() just doesn't work. 1337146482Smarius */ 1338146482Smarius EVENTHANDLER_REGISTER(shutdown_final, machfb_shutdown_final, sc, 1339146482Smarius SHUTDOWN_PRI_DEFAULT); 1340146482Smarius EVENTHANDLER_REGISTER(shutdown_reset, machfb_shutdown_reset, sc, 1341146482Smarius SHUTDOWN_PRI_DEFAULT); 1342146482Smarius 1343146482Smarius return (0); 1344146482Smarius 1345230687Smarius fail_vmemmap: 1346230687Smarius if (adp->va_registers != 0) 1347230687Smarius bus_space_unmap(sc->sc_vmemt, sc->sc_vmemh, 1348230687Smarius vi->vi_registers_size); 1349146482Smarius fail_vmemres: 1350191072Smarius if (sc->sc_vmemres != NULL) 1351191076Smarius bus_release_resource(dev, SYS_RES_MEMORY, 1352191076Smarius rman_get_rid(sc->sc_vmemres), sc->sc_vmemres); 1353230687Smarius fail_memmap: 1354230687Smarius bus_space_unmap(sc->sc_memt, sc->sc_memh, vi->vi_buffer_size); 1355146482Smarius fail_memres: 1356191076Smarius bus_release_resource(dev, SYS_RES_MEMORY, 1357191076Smarius rman_get_rid(sc->sc_memres), sc->sc_memres); 1358146482Smarius 1359146482Smarius return (error); 1360146482Smarius} 1361146482Smarius 1362146482Smariusstatic int 1363146482Smariusmachfb_pci_detach(device_t dev) 1364146482Smarius{ 1365146482Smarius 1366146482Smarius return (EINVAL); 1367146482Smarius} 1368146482Smarius 1369146482Smarius/* 1370146482Smarius * internal functions 1371146482Smarius */ 1372146482Smariusstatic void 1373146482Smariusmachfb_cursor_enable(struct machfb_softc *sc, int onoff) 1374146482Smarius{ 1375146482Smarius 1376146482Smarius if (onoff) 1377146482Smarius regw(sc, GEN_TEST_CNTL, 1378146482Smarius regr(sc, GEN_TEST_CNTL) | HWCURSOR_ENABLE); 1379146482Smarius else 1380146482Smarius regw(sc, GEN_TEST_CNTL, 1381146482Smarius regr(sc, GEN_TEST_CNTL) &~ HWCURSOR_ENABLE); 1382146482Smarius} 1383146482Smarius 1384146482Smariusstatic int 1385146482Smariusmachfb_cursor_install(struct machfb_softc *sc) 1386146482Smarius{ 1387191076Smarius uint16_t *p, v; 1388146482Smarius uint8_t fg; 1389146482Smarius int i, j; 1390146482Smarius 1391146482Smarius if (sc->sc_curoff == 0) 1392146482Smarius return (ENODEV); 1393146482Smarius 1394146482Smarius machfb_cursor_enable(sc, 0); 1395146482Smarius regw(sc, CUR_OFFSET, sc->sc_curoff >> 3); 1396146482Smarius fg = SC_NORM_ATTR & 0xf; 1397147881Smarius regw(sc, CUR_CLR0, machfb_default_cmap[fg].red << 24 | 1398147881Smarius machfb_default_cmap[fg].green << 16 | 1399147881Smarius machfb_default_cmap[fg].blue << 8); 1400146482Smarius p = (uint16_t *)(sc->sc_va.va_buffer + sc->sc_curoff); 1401191076Smarius for (i = 0; i < 64; i++) { 1402191076Smarius for (j = 0; j < 8; j++) { 1403191076Smarius v = machfb_mouse_pointer_lut[ 1404191076Smarius machfb_mouse_pointer_bits[i][j] >> 4] << 8 | 1405146482Smarius machfb_mouse_pointer_lut[ 1406191076Smarius machfb_mouse_pointer_bits[i][j] & 0x0f]; 1407191076Smarius if (sc->sc_flags & MACHFB_SWAP) 1408191076Smarius *(p++) = bswap16(v); 1409191076Smarius else 1410191076Smarius *(p++) = v; 1411191076Smarius } 1412191076Smarius } 1413146482Smarius 1414146482Smarius return (0); 1415146482Smarius} 1416146482Smarius 1417146482Smariusstatic int 1418146482Smariusmachfb_get_memsize(struct machfb_softc *sc) 1419146482Smarius{ 1420146482Smarius int tmp, memsize; 1421263764Sdim const int mem_tab[] = { 1422146482Smarius 512, 1024, 2048, 4096, 6144, 8192, 12288, 16384 1423146482Smarius }; 1424146482Smarius 1425146482Smarius tmp = regr(sc, MEM_CNTL); 1426146482Smarius#ifdef MACHFB_DEBUG 1427146482Smarius printf("memcntl=0x%08x\n", tmp); 1428146482Smarius#endif 1429146482Smarius if (sc->sc_flags & MACHFB_DSP) { 1430146482Smarius tmp &= 0x0000000f; 1431146482Smarius if (tmp < 8) 1432146482Smarius memsize = (tmp + 1) * 512; 1433146482Smarius else if (tmp < 12) 1434146482Smarius memsize = (tmp - 3) * 1024; 1435146482Smarius else 1436146482Smarius memsize = (tmp - 7) * 2048; 1437146482Smarius } else 1438146482Smarius memsize = mem_tab[tmp & 0x07]; 1439146482Smarius 1440146482Smarius return (memsize); 1441146482Smarius} 1442146482Smarius 1443146482Smariusstatic void 1444146482Smariusmachfb_reset_engine(struct machfb_softc *sc) 1445146482Smarius{ 1446146482Smarius 1447146482Smarius /* Reset engine.*/ 1448146482Smarius regw(sc, GEN_TEST_CNTL, regr(sc, GEN_TEST_CNTL) & ~GUI_ENGINE_ENABLE); 1449146482Smarius 1450146482Smarius /* Enable engine. */ 1451146482Smarius regw(sc, GEN_TEST_CNTL, regr(sc, GEN_TEST_CNTL) | GUI_ENGINE_ENABLE); 1452146482Smarius 1453146482Smarius /* 1454146482Smarius * Ensure engine is not locked up by clearing any FIFO or 1455146482Smarius * host errors. 1456146482Smarius */ 1457146482Smarius regw(sc, BUS_CNTL, regr(sc, BUS_CNTL) | BUS_HOST_ERR_ACK | 1458146482Smarius BUS_FIFO_ERR_ACK); 1459146482Smarius} 1460146482Smarius 1461146482Smariusstatic void 1462146482Smariusmachfb_init_engine(struct machfb_softc *sc) 1463146482Smarius{ 1464146482Smarius uint32_t pitch_value; 1465146482Smarius 1466146482Smarius pitch_value = sc->sc_width; 1467146482Smarius 1468146482Smarius if (sc->sc_depth == 24) 1469146482Smarius pitch_value *= 3; 1470146482Smarius 1471146482Smarius machfb_reset_engine(sc); 1472146482Smarius 1473146482Smarius wait_for_fifo(sc, 14); 1474146482Smarius 1475146482Smarius regw(sc, CONTEXT_MASK, 0xffffffff); 1476146482Smarius 1477146482Smarius regw(sc, DST_OFF_PITCH, (pitch_value / 8) << 22); 1478146482Smarius 1479146482Smarius regw(sc, DST_Y_X, 0); 1480146482Smarius regw(sc, DST_HEIGHT, 0); 1481146482Smarius regw(sc, DST_BRES_ERR, 0); 1482146482Smarius regw(sc, DST_BRES_INC, 0); 1483146482Smarius regw(sc, DST_BRES_DEC, 0); 1484146482Smarius 1485146482Smarius regw(sc, DST_CNTL, DST_LAST_PEL | DST_X_LEFT_TO_RIGHT | 1486146482Smarius DST_Y_TOP_TO_BOTTOM); 1487146482Smarius 1488146482Smarius regw(sc, SRC_OFF_PITCH, (pitch_value / 8) << 22); 1489146482Smarius 1490146482Smarius regw(sc, SRC_Y_X, 0); 1491146482Smarius regw(sc, SRC_HEIGHT1_WIDTH1, 1); 1492146482Smarius regw(sc, SRC_Y_X_START, 0); 1493146482Smarius regw(sc, SRC_HEIGHT2_WIDTH2, 1); 1494146482Smarius 1495146482Smarius regw(sc, SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT); 1496146482Smarius 1497146482Smarius wait_for_fifo(sc, 13); 1498146482Smarius regw(sc, HOST_CNTL, 0); 1499146482Smarius 1500146482Smarius regw(sc, PAT_REG0, 0); 1501146482Smarius regw(sc, PAT_REG1, 0); 1502146482Smarius regw(sc, PAT_CNTL, 0); 1503146482Smarius 1504146482Smarius regw(sc, SC_LEFT, 0); 1505146482Smarius regw(sc, SC_TOP, 0); 1506146482Smarius regw(sc, SC_BOTTOM, sc->sc_height - 1); 1507146482Smarius regw(sc, SC_RIGHT, pitch_value - 1); 1508146482Smarius 1509146482Smarius regw(sc, DP_BKGD_CLR, 0); 1510146482Smarius regw(sc, DP_FRGD_CLR, 0xffffffff); 1511146482Smarius regw(sc, DP_WRITE_MASK, 0xffffffff); 1512146482Smarius regw(sc, DP_MIX, (MIX_SRC << 16) | MIX_DST); 1513146482Smarius 1514146482Smarius regw(sc, DP_SRC, FRGD_SRC_FRGD_CLR); 1515146482Smarius 1516146482Smarius wait_for_fifo(sc, 3); 1517146482Smarius regw(sc, CLR_CMP_CLR, 0); 1518146482Smarius regw(sc, CLR_CMP_MASK, 0xffffffff); 1519146482Smarius regw(sc, CLR_CMP_CNTL, 0); 1520146482Smarius 1521146482Smarius wait_for_fifo(sc, 2); 1522146482Smarius switch (sc->sc_depth) { 1523146482Smarius case 8: 1524146482Smarius regw(sc, DP_PIX_WIDTH, HOST_8BPP | SRC_8BPP | DST_8BPP); 1525146482Smarius regw(sc, DP_CHAIN_MASK, DP_CHAIN_8BPP); 1526146482Smarius regw(sc, DAC_CNTL, regr(sc, DAC_CNTL) | DAC_8BIT_EN); 1527146482Smarius break; 1528146482Smarius#if 0 1529146482Smarius case 32: 1530146482Smarius regw(sc, DP_PIX_WIDTH, HOST_32BPP | SRC_32BPP | DST_32BPP); 1531146482Smarius regw(sc, DP_CHAIN_MASK, DP_CHAIN_32BPP); 1532146482Smarius regw(sc, DAC_CNTL, regr(sc, DAC_CNTL) | DAC_8BIT_EN); 1533146482Smarius break; 1534146482Smarius#endif 1535146482Smarius } 1536146482Smarius 1537147881Smarius wait_for_fifo(sc, 2); 1538146482Smarius regw(sc, CRTC_INT_CNTL, regr(sc, CRTC_INT_CNTL) & ~0x20); 1539146482Smarius regw(sc, GUI_TRAJ_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM); 1540146482Smarius 1541146482Smarius wait_for_idle(sc); 1542146482Smarius} 1543146482Smarius 1544146482Smarius#if 0 1545146482Smariusstatic void 1546146482Smariusmachfb_adjust_frame(struct machfb_softc *sc, int x, int y) 1547146482Smarius{ 1548146482Smarius int offset; 1549146482Smarius 1550146482Smarius offset = ((x + y * sc->sc_width) * (sc->sc_depth >> 3)) >> 3; 1551146482Smarius 1552146482Smarius regw(sc, CRTC_OFF_PITCH, (regr(sc, CRTC_OFF_PITCH) & 0xfff00000) | 1553191072Smarius offset); 1554146482Smarius} 1555146482Smarius#endif 1556146482Smarius 1557146482Smariusstatic void 1558146482Smariusmachfb_shutdown_final(void *v) 1559146482Smarius{ 1560146482Smarius struct machfb_softc *sc = v; 1561146482Smarius 1562146482Smarius machfb_cursor_enable(sc, 0); 1563146971Smarius /* 1564146971Smarius * In case this is the console set the cursor of the stdout 1565146971Smarius * instance to the start of the last line so OFW output ends 1566146971Smarius * up beneath what FreeBSD left on the screen. 1567146971Smarius */ 1568146971Smarius if (sc->sc_flags & MACHFB_CONSOLE) { 1569146971Smarius OF_interpret("stdout @ is my-self 0 to column#", 0); 1570146971Smarius OF_interpret("stdout @ is my-self #lines 1 - to line#", 0); 1571146971Smarius } 1572146482Smarius} 1573146482Smarius 1574146482Smariusstatic void 1575146482Smariusmachfb_shutdown_reset(void *v) 1576146482Smarius{ 1577146482Smarius struct machfb_softc *sc = v; 1578146482Smarius 1579146482Smarius machfb_blank_display(&sc->sc_va, V_DISPLAY_STAND_BY); 1580146482Smarius} 1581