1 /* $NetBSD: machfb.c,v 1.20 2005/01/17 22:52:46 martin Exp $ */ 2 3 /* 4 * Copyright (c) 2002 Bang Jun-Young 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 /* 31 * Some code is derived from ATI Rage Pro and Derivatives Programmer's Guide. 32 */ 33 34 #include <sys/cdefs.h> 35 __KERNEL_RCSID(0, "$NetBSD: machfb.c,v 1.20 2005/01/17 22:52:46 martin Exp $"); 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/kernel.h> 40 #include <sys/device.h> 41 #include <sys/malloc.h> 42 #include <sys/callout.h> 43 44 #ifdef __sparc__ 45 #include <machine/promlib.h> 46 #endif 47 48 #ifdef __powerpc__ 49 #include <dev/ofw/openfirm.h> 50 #include <dev/ofw/ofw_pci.h> 51 #endif 52 53 #include <dev/ic/videomode.h> 54 55 #include <dev/pci/pcivar.h> 56 #include <dev/pci/pcireg.h> 57 #include <dev/pci/pcidevs.h> 58 #include <dev/pci/pciio.h> 59 #include <dev/pci/machfbreg.h> 60 61 #include <dev/wscons/wsdisplayvar.h> 62 #include <dev/wscons/wsconsio.h> 63 #include <dev/wsfont/wsfont.h> 64 #include <dev/rasops/rasops.h> 65 66 #include "opt_wsemul.h" 67 68 #define MACH64_REG_SIZE 1024 69 #define MACH64_REG_OFF 0x7ffc00 70 71 #define NBARS 3 /* number of Mach64 PCI BARs */ 72 73 struct vga_bar { 74 bus_addr_t vb_base; 75 pcireg_t vb_busaddr; 76 bus_size_t vb_size; 77 pcireg_t vb_type; 78 int vb_flags; 79 }; 80 81 struct mach64_softc { 82 struct device sc_dev; 83 pci_chipset_tag_t sc_pc; 84 pcitag_t sc_pcitag; 85 86 struct vga_bar sc_bars[NBARS]; 87 struct vga_bar sc_rom; 88 89 #define sc_aperbase sc_bars[0].vb_base 90 #define sc_apersize sc_bars[0].vb_size 91 #define sc_aperphys sc_bars[0].vb_busaddr 92 93 #define sc_iobase sc_bars[1].vb_base 94 #define sc_iosize sc_bars[1].vb_size 95 96 #define sc_regbase sc_bars[2].vb_base 97 #define sc_regsize sc_bars[2].vb_size 98 #define sc_regphys sc_bars[2].vb_busaddr 99 100 bus_space_tag_t sc_regt; 101 bus_space_tag_t sc_memt; 102 bus_space_handle_t sc_regh; 103 bus_space_handle_t sc_memh; 104 105 size_t memsize; 106 int memtype; 107 108 int has_dsp; 109 int bits_per_pixel; 110 int max_x, max_y; 111 int virt_x, virt_y; 112 int color_depth; 113 114 int mem_freq; 115 int ramdac_freq; 116 int ref_freq; 117 118 int ref_div; 119 int log2_vclk_post_div; 120 int vclk_post_div; 121 int vclk_fb_div; 122 int mclk_post_div; 123 int mclk_fb_div; 124 125 struct mach64screen *wanted; 126 struct mach64screen *active; 127 void (*switchcb)(void *, int, int); 128 void *switchcbarg; 129 struct callout switch_callout; 130 LIST_HEAD(, mach64screen) screens; 131 const struct wsscreen_descr *currenttype; 132 u_char sc_cmap_red[256]; 133 u_char sc_cmap_green[256]; 134 u_char sc_cmap_blue[256]; 135 int sc_dacw; 136 }; 137 138 struct mach64screen { 139 struct rasops_info ri; 140 LIST_ENTRY(mach64screen) next; 141 struct mach64_softc *sc; 142 const struct wsscreen_descr *type; 143 int active; 144 u_int16_t *mem; 145 int dispoffset; 146 int mindispoffset; 147 int maxdispoffset; 148 149 int cursoron; 150 int cursorcol; 151 int cursorrow; 152 u_int16_t cursortmp; 153 }; 154 155 struct mach64_crtcregs { 156 u_int32_t h_total_disp; 157 u_int32_t h_sync_strt_wid; 158 u_int32_t v_total_disp; 159 u_int32_t v_sync_strt_wid; 160 u_int32_t gen_cntl; 161 u_int32_t clock_cntl; 162 u_int32_t color_depth; 163 u_int32_t dot_clock; 164 }; 165 166 struct { 167 u_int16_t chip_id; 168 u_int32_t ramdac_freq; 169 } mach64_info[] = { 170 { PCI_PRODUCT_ATI_MACH64_CT, 135000 }, 171 { PCI_PRODUCT_ATI_RAGE_PRO_AGP, 230000 }, 172 { PCI_PRODUCT_ATI_RAGE_PRO_AGP1X, 230000 }, 173 { PCI_PRODUCT_ATI_RAGE_PRO_PCI_B, 230000 }, 174 { PCI_PRODUCT_ATI_RAGE_XL_AGP, 230000 }, 175 { PCI_PRODUCT_ATI_RAGE_PRO_PCI_P, 230000 }, 176 { PCI_PRODUCT_ATI_RAGE_PRO_PCI_L, 230000 }, 177 { PCI_PRODUCT_ATI_RAGE_XL_PCI, 230000 }, 178 { PCI_PRODUCT_ATI_RAGE_II, 135000 }, 179 { PCI_PRODUCT_ATI_RAGE_IIP, 200000 }, 180 { PCI_PRODUCT_ATI_RAGE_IIC_PCI, 230000 }, 181 { PCI_PRODUCT_ATI_RAGE_IIC_AGP_B, 230000 }, 182 { PCI_PRODUCT_ATI_RAGE_IIC_AGP_P, 230000 }, 183 { PCI_PRODUCT_ATI_RAGE_LT_PRO_AGP, 230000 }, 184 { PCI_PRODUCT_ATI_RAGE_MOB_M3_PCI, 230000 }, 185 { PCI_PRODUCT_ATI_RAGE_MOB_M3_AGP, 230000 }, 186 { PCI_PRODUCT_ATI_RAGE_LT, 230000 }, 187 { PCI_PRODUCT_ATI_RAGE_LT_PRO_PCI, 230000 }, 188 { PCI_PRODUCT_ATI_RAGE_MOBILITY, 230000 }, 189 { PCI_PRODUCT_ATI_RAGE_LT_PRO, 230000 }, 190 { PCI_PRODUCT_ATI_MACH64_VT, 170000 }, 191 { PCI_PRODUCT_ATI_MACH64_VTB, 200000 }, 192 { PCI_PRODUCT_ATI_MACH64_VT4, 230000 } 193 }; 194 195 static int mach64_chip_id, mach64_chip_rev; 196 static struct videomode default_mode; 197 static struct mach64screen mach64_console_screen; 198 199 static char *mach64_memtype_names[] = { 200 "(N/A)", "DRAM", "EDO DRAM", "EDO DRAM", "SDRAM", "SGRAM", "WRAM", 201 "(unknown type)" 202 }; 203 204 struct videomode mach64_modes[] = { 205 /* 640x400 @ 70 Hz, 31.5 kHz */ 206 { 25175, 640, 664, 760, 800, 400, 409, 411, 450, 0 }, 207 /* 640x480 @ 72 Hz, 36.5 kHz */ 208 { 25175, 640, 664, 760, 800, 480, 491, 493, 525, 0 }, 209 /* 800x600 @ 72 Hz, 48.0 kHz */ 210 { 50000, 800, 856, 976, 1040, 600, 637, 643, 666, 211 VID_PHSYNC | VID_PVSYNC }, 212 /* 1024x768 @ 70 Hz, 56.5 kHz */ 213 { 75000, 1024, 1048, 1184, 1328, 768, 771, 777, 806, 214 VID_NHSYNC | VID_NVSYNC }, 215 /* 1152x864 @ 70 Hz, 62.4 kHz */ 216 { 92000, 1152, 1208, 1368, 1474, 864, 865, 875, 895, 0 }, 217 /* 1280x1024 @ 70 Hz, 74.59 kHz */ 218 { 126500, 1280, 1312, 1472, 1696, 1024, 1032, 1040, 1068, 219 VID_NHSYNC | VID_NVSYNC } 220 }; 221 222 /* Macallan: let the terminal emulator program the palette, it should be in the softc anyway */ 223 #if 0 224 /* FIXME values are wrong! */ 225 const u_char mach64_cmap[16 * 3] = { 226 0x00, 0x00, 0x00, /* black */ 227 0x7f, 0x00, 0x00, /* red */ 228 0x00, 0x7f, 0x00, /* green */ 229 0x7f, 0x7f, 0x00, /* brown */ 230 0x00, 0x00, 0x7f, /* blue */ 231 0x7f, 0x00, 0x7f, /* magenta */ 232 0x00, 0x7f, 0x7f, /* cyan */ 233 0xc8, 0xc8, 0xc8, /* white */ 234 235 0x7f, 0x7f, 0x7f, /* black */ 236 0xff, 0x00, 0x00, /* red */ 237 0x00, 0xff, 0x00, /* green */ 238 0xff, 0xff, 0x00, /* brown */ 239 0x00, 0x00, 0xff, /* blue */ 240 0xff, 0x00, 0xff, /* magenta */ 241 0x00, 0xff, 0xff, /* cyan */ 242 0xff, 0xff, 0xff, /* white */ 243 }; 244 #endif 245 246 #ifdef WSEMUL_VT100 247 extern const u_char rasops_cmap[768]; 248 #endif 249 250 int mach64_match(struct device *, struct cfdata *, void *); 251 void mach64_attach(struct device *, struct device *, void *); 252 253 CFATTACH_DECL(machfb, sizeof(struct mach64_softc), mach64_match, mach64_attach, 254 NULL, NULL); 255 256 void mach64_init(struct mach64_softc *); 257 int mach64_get_memsize(struct mach64_softc *); 258 int mach64_get_max_ramdac(struct mach64_softc *); 259 void mach64_get_mode(struct mach64_softc *, struct videomode *); 260 int mach64_calc_crtcregs(struct mach64_softc *, struct mach64_crtcregs *, 261 struct videomode *); 262 void mach64_set_crtcregs(struct mach64_softc *, struct mach64_crtcregs *); 263 int mach64_modeswitch(struct mach64_softc *, struct videomode *); 264 void mach64_set_dsp(struct mach64_softc *); 265 void mach64_set_pll(struct mach64_softc *, int); 266 void mach64_reset_engine(struct mach64_softc *); 267 void mach64_init_engine(struct mach64_softc *); 268 void mach64_adjust_frame(struct mach64_softc *, int, int); 269 void mach64_init_lut(struct mach64_softc *); 270 void mach64_switch_screen(struct mach64_softc *); 271 void mach64_init_screen(struct mach64_softc *, struct mach64screen *, 272 const struct wsscreen_descr *, int, long *, int); 273 void mach64_restore_screen(struct mach64screen *, 274 const struct wsscreen_descr *, u_int16_t *); 275 int mach64_set_screentype(struct mach64_softc *, 276 const struct wsscreen_descr *); 277 int mach64_is_console(struct pci_attach_args *); 278 279 void mach64_cursor(void *, int, int, int); 280 int mach64_mapchar(void *, int, u_int *); 281 void mach64_putchar(void *, int, int, u_int, long); 282 void mach64_copycols(void *, int, int, int, int); 283 void mach64_erasecols(void *, int, int, int, long); 284 void mach64_copyrows(void *, int, int, int); 285 void mach64_eraserows(void *, int, int, long); 286 int mach64_allocattr(void *, int, int, int, long *); 287 288 void mach64_scroll(void *, void *, int); 289 290 int mach64_putcmap(struct mach64_softc *, struct wsdisplay_cmap *); 291 int mach64_getcmap(struct mach64_softc *, struct wsdisplay_cmap *); 292 int mach64_putpalreg(struct mach64_softc *, uint8_t, uint8_t, uint8_t, uint8_t); 293 void mach64_bitblt(struct mach64_softc *, int, int, int, int, int, int, int, int) ; 294 void mach64_rectfill(struct mach64_softc *, int, int, int, int, int); 295 void mach64_showpal(struct mach64_softc *); 296 297 #if 0 298 const struct wsdisplay_emulops mach64_emulops = { 299 mach64_cursor, 300 mach64_mapchar, 301 mach64_putchar, 302 mach64_copycols, 303 mach64_erasecols, 304 mach64_copyrows, 305 mach64_eraserows, 306 mach64_allocattr, 307 }; 308 #endif 309 310 struct wsscreen_descr mach64_defaultscreen = { 311 "default", 312 0, 0, 313 &mach64_console_screen.ri.ri_ops, 314 8, 16, 315 WSSCREEN_WSCOLORS | WSSCREEN_HILIT, 316 &default_mode 317 }, mach64_80x25_screen = { 318 "80x25", 80, 25, 319 &mach64_console_screen.ri.ri_ops, 320 8, 16, 321 WSSCREEN_WSCOLORS | WSSCREEN_HILIT, 322 &mach64_modes[0] 323 }, mach64_80x30_screen = { 324 "80x30", 80, 30, 325 &mach64_console_screen.ri.ri_ops, 326 8, 16, 327 WSSCREEN_WSCOLORS | WSSCREEN_HILIT, 328 &mach64_modes[1] 329 }, mach64_80x40_screen = { 330 "80x40", 80, 40, 331 &mach64_console_screen.ri.ri_ops, 332 8, 10, 333 WSSCREEN_WSCOLORS | WSSCREEN_HILIT, 334 &mach64_modes[0] 335 }, mach64_80x50_screen = { 336 "80x50", 80, 50, 337 &mach64_console_screen.ri.ri_ops, 338 8, 8, 339 WSSCREEN_WSCOLORS | WSSCREEN_HILIT, 340 &mach64_modes[0] 341 }, mach64_100x37_screen = { 342 "100x37", 100, 37, 343 &mach64_console_screen.ri.ri_ops, 344 8, 16, 345 WSSCREEN_WSCOLORS | WSSCREEN_HILIT, 346 &mach64_modes[2] 347 }, mach64_128x48_screen = { 348 "128x48", 128, 48, 349 &mach64_console_screen.ri.ri_ops, 350 8, 16, 351 WSSCREEN_WSCOLORS | WSSCREEN_HILIT, 352 &mach64_modes[3] 353 }, mach64_144x54_screen = { 354 "144x54", 144, 54, 355 &mach64_console_screen.ri.ri_ops, 356 8, 16, 357 WSSCREEN_WSCOLORS | WSSCREEN_HILIT, 358 &mach64_modes[4] 359 }, mach64_160x64_screen = { 360 "160x54", 160, 64, 361 &mach64_console_screen.ri.ri_ops, 362 8, 16, 363 WSSCREEN_WSCOLORS | WSSCREEN_HILIT, 364 &mach64_modes[5] 365 }; 366 367 const struct wsscreen_descr *_mach64_scrlist[] = { 368 &mach64_defaultscreen, 369 &mach64_80x25_screen, 370 &mach64_80x30_screen, 371 &mach64_80x40_screen, 372 &mach64_80x50_screen, 373 &mach64_100x37_screen, 374 &mach64_128x48_screen, 375 &mach64_144x54_screen, 376 &mach64_160x64_screen 377 }; 378 379 struct wsscreen_list mach64_screenlist = { 380 sizeof(_mach64_scrlist) / sizeof(struct wsscreen_descr *), 381 _mach64_scrlist 382 }; 383 384 int mach64_ioctl(void *, u_long, caddr_t, int, struct proc *); 385 paddr_t mach64_mmap(void *, off_t, int); 386 int mach64_alloc_screen(void *, const struct wsscreen_descr *, void **, 387 int *, int *, long *); 388 void mach64_free_screen(void *, void *); 389 int mach64_show_screen(void *, void *, int, void (*)(void *, int, int), 390 void *); 391 int mach64_load_font(void *, void *, struct wsdisplay_font *); 392 393 struct wsdisplay_accessops mach64_accessops = { 394 mach64_ioctl, 395 mach64_mmap, 396 mach64_alloc_screen, 397 mach64_free_screen, 398 mach64_show_screen, 399 NULL, /* load_font */ 400 NULL, /* polls */ 401 NULL, /* getwschar */ 402 NULL, /* putwschar */ 403 NULL, /* scroll */ 404 NULL, /* getborder */ 405 NULL /* setborder */ 406 }; 407 408 /* 409 * Inline functions for getting access to register aperture. 410 */ 411 static inline u_int32_t regr(struct mach64_softc *, u_int32_t); 412 static inline u_int8_t regrb(struct mach64_softc *, u_int32_t); 413 static inline void regw(struct mach64_softc *, u_int32_t, u_int32_t); 414 static inline void regwb(struct mach64_softc *, u_int32_t, u_int8_t); 415 static inline void regwb_pll(struct mach64_softc *, u_int32_t, u_int8_t); 416 417 static inline u_int32_t 418 regr(struct mach64_softc *sc, u_int32_t index) 419 { 420 421 return bus_space_read_4(sc->sc_regt, sc->sc_regh, index); 422 } 423 424 static inline u_int8_t 425 regrb(struct mach64_softc *sc, u_int32_t index) 426 { 427 428 return bus_space_read_1(sc->sc_regt, sc->sc_regh, index); 429 } 430 431 static inline void 432 regw(struct mach64_softc *sc, u_int32_t index, u_int32_t data) 433 { 434 435 bus_space_write_4(sc->sc_regt, sc->sc_regh, index, data); 436 bus_space_barrier(sc->sc_regt, sc->sc_regh, index, 4, BUS_SPACE_BARRIER_WRITE); 437 } 438 439 static inline void 440 regwb(struct mach64_softc *sc, u_int32_t index, u_int8_t data) 441 { 442 443 bus_space_write_1(sc->sc_regt, sc->sc_regh, index, data); 444 bus_space_barrier(sc->sc_regt, sc->sc_regh, index, 1, BUS_SPACE_BARRIER_WRITE); 445 } 446 447 static inline void 448 regwb_pll(struct mach64_softc *sc, u_int32_t index, u_int8_t data) 449 { 450 451 regwb(sc, CLOCK_CNTL + 1, (index << 2) | PLL_WR_EN); 452 regwb(sc, CLOCK_CNTL + 2, data); 453 regwb(sc, CLOCK_CNTL + 1, (index << 2) & ~PLL_WR_EN); 454 } 455 456 static inline void 457 wait_for_fifo(struct mach64_softc *sc, u_int8_t v) 458 { 459 460 while ((regr(sc, FIFO_STAT) & 0xffff) > (0x8000 >> v)) 461 ; 462 } 463 464 static inline void 465 wait_for_idle(struct mach64_softc *sc) 466 { 467 468 wait_for_fifo(sc, 16); 469 while ((regr(sc, GUI_STAT) & 1) != 0) 470 ; 471 } 472 473 int 474 mach64_match(struct device *parent, struct cfdata *match, void *aux) 475 { 476 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 477 int i; 478 479 if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY || 480 PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_DISPLAY_VGA) 481 return 0; 482 483 for (i = 0; i < sizeof(mach64_info) / sizeof(mach64_info[0]); i++) 484 if (PCI_PRODUCT(pa->pa_id) == mach64_info[i].chip_id) { 485 mach64_chip_id = PCI_PRODUCT(pa->pa_id); 486 mach64_chip_rev = PCI_REVISION(pa->pa_class); 487 return 1; 488 } 489 490 return 0; 491 } 492 493 void 494 mach64_attach(struct device *parent, struct device *self, void *aux) 495 { 496 struct mach64_softc *sc = (void *)self; 497 struct pci_attach_args *pa = aux; 498 char devinfo[256]; 499 int bar, reg, id; 500 struct wsemuldisplaydev_attach_args aa; 501 long defattr; 502 int setmode, console; 503 504 sc->sc_pc = pa->pa_pc; 505 sc->sc_pcitag = pa->pa_tag; 506 sc->sc_dacw=-1; 507 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo)); 508 printf(": %s (rev. 0x%02x)\n", devinfo, PCI_REVISION(pa->pa_class)); 509 510 for (bar = 0; bar < NBARS; bar++) { 511 reg = PCI_MAPREG_START + (bar * 4); 512 sc->sc_bars[bar].vb_type = pci_mapreg_type(sc->sc_pc, 513 sc->sc_pcitag, reg); 514 (void)pci_mapreg_info(sc->sc_pc, sc->sc_pcitag, reg, 515 sc->sc_bars[bar].vb_type, &sc->sc_bars[bar].vb_base, 516 &sc->sc_bars[bar].vb_size, &sc->sc_bars[bar].vb_flags); 517 sc->sc_bars[bar].vb_busaddr=pci_conf_read(sc->sc_pc, sc->sc_pcitag, reg)&0xfffffff0; 518 } 519 sc->sc_memt = pa->pa_memt; 520 521 mach64_init(sc); 522 523 printf("%s: %d MB aperture at 0x%08x, %d KB registers at 0x%08x\n", 524 sc->sc_dev.dv_xname, (u_int)(sc->sc_apersize / (1024 * 1024)), 525 (u_int)sc->sc_aperphys, (u_int)(sc->sc_regsize / 1024), 526 (u_int)sc->sc_regphys); 527 528 if (mach64_chip_id == PCI_PRODUCT_ATI_MACH64_CT || 529 ((mach64_chip_id == PCI_PRODUCT_ATI_MACH64_VT || 530 mach64_chip_id == PCI_PRODUCT_ATI_RAGE_II) && 531 (mach64_chip_rev & 0x07) == 0)) 532 sc->has_dsp = 0; 533 else 534 sc->has_dsp = 1; 535 536 sc->memsize = mach64_get_memsize(sc); 537 if (sc->memsize == 8192) 538 /* The last page is used as register aperture. */ 539 sc->memsize -= 4; 540 sc->memtype = regr(sc, CONFIG_STAT0) & 0x07; 541 542 /* XXX is there any way to calculate reference frequency from 543 known values? */ 544 if (mach64_chip_id == PCI_PRODUCT_ATI_RAGE_XL_PCI) 545 sc->ref_freq = 29498; 546 else 547 sc->ref_freq = 14318; 548 549 regwb(sc, CLOCK_CNTL + 1, PLL_REF_DIV << 2); 550 sc->ref_div = regrb(sc, CLOCK_CNTL + 2); 551 regwb(sc, CLOCK_CNTL + 1, MCLK_FB_DIV << 2); 552 sc->mclk_fb_div = regrb(sc, CLOCK_CNTL + 2); 553 sc->mem_freq = (2 * sc->ref_freq * sc->mclk_fb_div) / 554 (sc->ref_div * 2); 555 sc->mclk_post_div = (sc->mclk_fb_div * 2 * sc->ref_freq) / 556 (sc->mem_freq * sc->ref_div); 557 sc->ramdac_freq = mach64_get_max_ramdac(sc); 558 printf("%s: %ld KB %s %d.%d MHz, maximum RAMDAC clock %d MHz\n", 559 sc->sc_dev.dv_xname, (u_long)sc->memsize, 560 mach64_memtype_names[sc->memtype], 561 sc->mem_freq / 1000, sc->mem_freq % 1000, 562 sc->ramdac_freq / 1000); 563 564 id = regr(sc, CONFIG_CHIP_ID) & 0xffff; 565 if (id != mach64_chip_id) { 566 printf("%s: chip ID mismatch, 0x%x != 0x%x\n", 567 sc->sc_dev.dv_xname, id, mach64_chip_id); 568 return; 569 } 570 571 console = mach64_is_console(pa); 572 573 #if defined(__sparc__) || defined(__powerpc__) 574 if (console) { 575 mach64_get_mode(sc, &default_mode); 576 setmode = 0; 577 } else { 578 memcpy(&default_mode, &mach64_modes[4], sizeof(struct videomode)); 579 setmode = 1; 580 } 581 #else 582 memcpy(&default_mode, &mach64_modes[0], sizeof(struct videomode)); 583 setmode = 1; 584 #endif 585 586 sc->bits_per_pixel = 8; 587 sc->virt_x = default_mode.hdisplay; 588 sc->virt_y = default_mode.vdisplay; 589 sc->max_x = sc->virt_x - 1; 590 sc->max_y = (sc->memsize * 1024) / 591 (sc->virt_x * (sc->bits_per_pixel / 8)) - 1; 592 593 sc->color_depth = CRTC_PIX_WIDTH_8BPP; 594 595 mach64_init_engine(sc); 596 #if 0 597 mach64_adjust_frame(0, 0); 598 if (sc->bits_per_pixel == 8) 599 mach64_init_lut(sc); 600 #endif 601 602 printf("%s: initial resolution %dx%d at %d bpp\n", sc->sc_dev.dv_xname, 603 default_mode.hdisplay, default_mode.vdisplay, 604 sc->bits_per_pixel); 605 606 mach64_console_screen.ri.ri_hw = sc; 607 mach64_console_screen.ri.ri_depth = sc->bits_per_pixel; 608 mach64_console_screen.ri.ri_bits = (void*)(u_long)sc->sc_aperbase; 609 mach64_console_screen.ri.ri_width = default_mode.hdisplay; 610 mach64_console_screen.ri.ri_height = default_mode.vdisplay; 611 mach64_console_screen.ri.ri_stride = mach64_console_screen.ri.ri_width; 612 613 mach64_console_screen.ri.ri_flg = RI_CLEAR|RI_CENTER; 614 615 #ifdef WSEMUL_SUN 616 mach64_console_screen.ri.ri_flg = RI_CLEAR|RI_CENTER|RI_FORCEMONO; 617 #endif 618 619 rasops_init(&mach64_console_screen.ri, mach64_console_screen.ri.ri_height / 16, 620 mach64_console_screen.ri.ri_width / 8); /* XXX width/height are nonsense */ 621 622 /* enable acceleration */ 623 mach64_console_screen.ri.ri_ops.copyrows=mach64_copyrows; 624 mach64_console_screen.ri.ri_ops.eraserows=mach64_eraserows; 625 mach64_console_screen.ri.ri_ops.copycols=mach64_copycols; 626 mach64_console_screen.ri.ri_ops.erasecols=mach64_erasecols; 627 628 mach64_defaultscreen.nrows = mach64_console_screen.ri.ri_rows; 629 mach64_defaultscreen.ncols = mach64_console_screen.ri.ri_cols; 630 631 mach64_console_screen.ri.ri_ops.allocattr(&mach64_console_screen.ri, 0, 0, 0, 632 &defattr); 633 634 /* really necessary? */ 635 mach64_defaultscreen.capabilities=mach64_console_screen.ri.ri_caps; 636 mach64_defaultscreen.textops=&mach64_console_screen.ri.ri_ops; 637 638 /* Initialize fonts */ 639 /* XXX Macallan: shouldn't that happen /before/ we call rasops_init()? */ 640 wsfont_init(); 641 642 if (console) { 643 mach64_init_screen(sc, &mach64_console_screen, 644 &mach64_defaultscreen, 1, &defattr, setmode); 645 wsdisplay_cnattach(&mach64_defaultscreen, &mach64_console_screen.ri, 646 0, 0, defattr); 647 } 648 649 mach64_init_lut(sc); 650 651 #ifdef DEBUG 652 mach64_showpal(sc); 653 delay(4000000); 654 #endif 655 aa.console = console; 656 aa.scrdata = &mach64_screenlist; 657 aa.accessops = &mach64_accessops; 658 aa.accesscookie = sc; 659 660 config_found(self, &aa, wsemuldisplaydevprint); 661 } 662 663 void 664 mach64_init_screen(struct mach64_softc *sc, struct mach64screen *scr, 665 const struct wsscreen_descr *type, int existing, long *attrp, int setmode) 666 { 667 668 scr->sc = sc; 669 scr->type = type; 670 scr->mindispoffset = 0; 671 scr->maxdispoffset = sc->memsize * 1024; 672 scr->dispoffset = 0; 673 scr->cursorcol = 0; 674 scr->cursorrow = 0; 675 676 scr->mem = (u_int16_t *)malloc(type->nrows * type->ncols * 2, 677 M_DEVBUF, M_WAITOK); 678 if (existing) { 679 scr->active = 1; 680 681 if (setmode && mach64_set_screentype(sc, type)) { 682 panic("%s: failed to switch video mode", 683 sc->sc_dev.dv_xname); 684 } 685 } else { 686 scr->active = 0; 687 } 688 689 LIST_INSERT_HEAD(&sc->screens, scr, next); 690 } 691 692 void 693 mach64_init(struct mach64_softc *sc) 694 { 695 u_int32_t *p32, saved_value; 696 u_int8_t *p; 697 int need_swap; 698 699 if (bus_space_map(sc->sc_memt, sc->sc_aperbase, sc->sc_apersize, 700 BUS_SPACE_MAP_LINEAR, &sc->sc_memh)) { 701 panic("%s: failed to map aperture", sc->sc_dev.dv_xname); 702 } 703 sc->sc_aperbase = (vaddr_t)bus_space_vaddr(sc->sc_memt, sc->sc_memh); 704 705 sc->sc_regt = sc->sc_memt; 706 bus_space_subregion(sc->sc_regt, sc->sc_memh, MACH64_REG_OFF, 707 sc->sc_regsize, &sc->sc_regh); 708 sc->sc_regbase = sc->sc_aperbase + 0x7ffc00; 709 710 /* 711 * Test wether the aperture is byte swapped or not 712 */ 713 p32 = (u_int32_t*)(u_long)sc->sc_aperbase; 714 saved_value = *p32; 715 p = (u_int8_t*)(u_long)sc->sc_aperbase; 716 *p32 = 0x12345678; 717 if (p[0] == 0x12 && p[1] == 0x34 && p[2] == 0x56 && p[3] == 0x78) 718 need_swap = 0; 719 else 720 need_swap = 1; 721 if (need_swap) { 722 sc->sc_aperbase += 0x800000; 723 sc->sc_apersize -= 0x800000; 724 } 725 *p32 = saved_value; 726 727 LIST_INIT(&sc->screens); 728 sc->active = NULL; 729 sc->currenttype = &mach64_defaultscreen; 730 callout_init(&sc->switch_callout); 731 } 732 733 int 734 mach64_get_memsize(struct mach64_softc *sc) 735 { 736 int tmp, memsize; 737 int mem_tab[] = { 738 512, 1024, 2048, 4096, 6144, 8192, 12288, 16384 739 }; 740 741 tmp = regr(sc, MEM_CNTL); 742 if (sc->has_dsp) { 743 tmp &= 0x0000000f; 744 if (tmp < 8) 745 memsize = (tmp + 1) * 512; 746 else if (tmp < 12) 747 memsize = (tmp - 3) * 1024; 748 else 749 memsize = (tmp - 7) * 2048; 750 } else { 751 memsize = mem_tab[tmp & 0x07]; 752 } 753 754 return memsize; 755 } 756 757 int 758 mach64_get_max_ramdac(struct mach64_softc *sc) 759 { 760 int i; 761 762 if ((mach64_chip_id == PCI_PRODUCT_ATI_MACH64_VT || 763 mach64_chip_id == PCI_PRODUCT_ATI_RAGE_II) && 764 (mach64_chip_rev & 0x07)) 765 return 170000; 766 767 for (i = 0; i < sizeof(mach64_info) / sizeof(mach64_info[0]); i++) 768 if (mach64_chip_id == mach64_info[i].chip_id) 769 return mach64_info[i].ramdac_freq; 770 771 if (sc->bits_per_pixel == 8) 772 return 135000; 773 else 774 return 80000; 775 } 776 777 void 778 mach64_get_mode(struct mach64_softc *sc, struct videomode *mode) 779 { 780 struct mach64_crtcregs crtc; 781 782 crtc.h_total_disp = regr(sc, CRTC_H_TOTAL_DISP); 783 crtc.h_sync_strt_wid = regr(sc, CRTC_H_SYNC_STRT_WID); 784 crtc.v_total_disp = regr(sc, CRTC_V_TOTAL_DISP); 785 crtc.v_sync_strt_wid = regr(sc, CRTC_V_SYNC_STRT_WID); 786 787 mode->htotal = ((crtc.h_total_disp & 0xffff) + 1) << 3; 788 mode->hdisplay = ((crtc.h_total_disp >> 16) + 1) << 3; 789 mode->hsync_start = ((crtc.h_sync_strt_wid & 0xffff) + 1) << 3; 790 mode->hsync_end = ((crtc.h_sync_strt_wid >> 16) << 3) + 791 mode->hsync_start; 792 mode->vtotal = (crtc.v_total_disp & 0xffff) + 1; 793 mode->vdisplay = (crtc.v_total_disp >> 16) + 1; 794 mode->vsync_start = (crtc.v_sync_strt_wid & 0xffff) + 1; 795 mode->vsync_end = (crtc.v_sync_strt_wid >> 16) + mode->vsync_start; 796 797 #ifdef MACH64_DEBUG 798 printf("mach64_get_mode: %d %d %d %d %d %d %d %d\n", 799 mode->hdisplay, mode->hsync_start, mode->hsync_end, mode->htotal, 800 mode->vdisplay, mode->vsync_start, mode->vsync_end, mode->vtotal); 801 #endif 802 } 803 804 int 805 mach64_calc_crtcregs(struct mach64_softc *sc, struct mach64_crtcregs *crtc, 806 struct videomode *mode) 807 { 808 809 if (mode->dot_clock > sc->ramdac_freq) 810 /* Clock too high. */ 811 return 1; 812 813 crtc->h_total_disp = (((mode->hdisplay >> 3) - 1) << 16) | 814 ((mode->htotal >> 3) - 1); 815 crtc->h_sync_strt_wid = 816 (((mode->hsync_end - mode->hsync_start) >> 3) << 16) | 817 ((mode->hsync_start >> 3) - 1); 818 819 crtc->v_total_disp = ((mode->vdisplay - 1) << 16) | 820 (mode->vtotal - 1); 821 crtc->v_sync_strt_wid = 822 ((mode->vsync_end - mode->vsync_start) << 16) | 823 (mode->vsync_start - 1); 824 825 if (mode->flags & VID_NVSYNC) 826 crtc->v_sync_strt_wid |= CRTC_VSYNC_NEG; 827 828 switch (sc->bits_per_pixel) { 829 case 8: 830 crtc->color_depth = CRTC_PIX_WIDTH_8BPP; 831 break; 832 case 16: 833 crtc->color_depth = CRTC_PIX_WIDTH_16BPP; 834 break; 835 case 32: 836 crtc->color_depth = CRTC_PIX_WIDTH_32BPP; 837 break; 838 } 839 840 crtc->gen_cntl = 0; 841 if (mode->flags & VID_INTERLACE) 842 crtc->gen_cntl |= CRTC_INTERLACE_EN; 843 if (mode->flags & VID_CSYNC) 844 crtc->gen_cntl |= CRTC_CSYNC_EN; 845 846 crtc->dot_clock = mode->dot_clock; 847 848 return 0; 849 } 850 851 void 852 mach64_set_crtcregs(struct mach64_softc *sc, struct mach64_crtcregs *crtc) 853 { 854 855 mach64_set_pll(sc, crtc->dot_clock); 856 857 if (sc->has_dsp) 858 mach64_set_dsp(sc); 859 860 regw(sc, CRTC_H_TOTAL_DISP, crtc->h_total_disp); 861 regw(sc, CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid); 862 regw(sc, CRTC_V_TOTAL_DISP, crtc->v_total_disp); 863 regw(sc, CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid); 864 865 regw(sc, CRTC_VLINE_CRNT_VLINE, 0); 866 867 regw(sc, CRTC_OFF_PITCH, (sc->virt_x >> 3) << 22); 868 869 regw(sc, CRTC_GEN_CNTL, crtc->gen_cntl | crtc->color_depth | 870 CRTC_EXT_DISP_EN | CRTC_EXT_EN); 871 } 872 873 int 874 mach64_modeswitch(struct mach64_softc *sc, struct videomode *mode) 875 { 876 struct mach64_crtcregs crtc; 877 878 if (mach64_calc_crtcregs(sc, &crtc, mode)) 879 return 1; 880 881 mach64_set_crtcregs(sc, &crtc); 882 return 0; 883 } 884 885 void 886 mach64_reset_engine(struct mach64_softc *sc) 887 { 888 889 /* Reset engine.*/ 890 regw(sc, GEN_TEST_CNTL, regr(sc, GEN_TEST_CNTL) & ~GUI_ENGINE_ENABLE); 891 892 /* Enable engine. */ 893 regw(sc, GEN_TEST_CNTL, regr(sc, GEN_TEST_CNTL) | GUI_ENGINE_ENABLE); 894 895 /* Ensure engine is not locked up by clearing any FIFO or 896 host errors. */ 897 regw(sc, BUS_CNTL, regr(sc, BUS_CNTL) | BUS_HOST_ERR_ACK | 898 BUS_FIFO_ERR_ACK); 899 } 900 901 void 902 mach64_init_engine(struct mach64_softc *sc) 903 { 904 u_int32_t pitch_value; 905 906 pitch_value = sc->virt_x; 907 908 if (sc->bits_per_pixel == 24) 909 pitch_value *= 3; 910 911 mach64_reset_engine(sc); 912 913 wait_for_fifo(sc, 14); 914 915 regw(sc, CONTEXT_MASK, 0xffffffff); 916 917 regw(sc, DST_OFF_PITCH, (pitch_value / 8) << 22); 918 919 regw(sc, DST_Y_X, 0); 920 regw(sc, DST_HEIGHT, 0); 921 regw(sc, DST_BRES_ERR, 0); 922 regw(sc, DST_BRES_INC, 0); 923 regw(sc, DST_BRES_DEC, 0); 924 925 regw(sc, DST_CNTL, DST_LAST_PEL | DST_X_LEFT_TO_RIGHT | 926 DST_Y_TOP_TO_BOTTOM); 927 928 regw(sc, SRC_OFF_PITCH, (pitch_value / 8) << 22); 929 930 regw(sc, SRC_Y_X, 0); 931 regw(sc, SRC_HEIGHT1_WIDTH1, 1); 932 regw(sc, SRC_Y_X_START, 0); 933 regw(sc, SRC_HEIGHT2_WIDTH2, 1); 934 935 regw(sc, SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT); 936 937 wait_for_fifo(sc, 13); 938 regw(sc, HOST_CNTL, 0); 939 940 regw(sc, PAT_REG0, 0); 941 regw(sc, PAT_REG1, 0); 942 regw(sc, PAT_CNTL, 0); 943 944 regw(sc, SC_LEFT, 0); 945 regw(sc, SC_TOP, 0); 946 regw(sc, SC_BOTTOM, default_mode.vdisplay - 1); 947 regw(sc, SC_RIGHT, pitch_value - 1); 948 949 regw(sc, DP_BKGD_CLR, 0); 950 regw(sc, DP_FRGD_CLR, 0xffffffff); 951 regw(sc, DP_WRITE_MASK, 0xffffffff); 952 regw(sc, DP_MIX, (MIX_SRC << 16) | MIX_DST); 953 954 regw(sc, DP_SRC, FRGD_SRC_FRGD_CLR); 955 956 wait_for_fifo(sc, 3); 957 regw(sc, CLR_CMP_CLR, 0); 958 regw(sc, CLR_CMP_MASK, 0xffffffff); 959 regw(sc, CLR_CMP_CNTL, 0); 960 961 wait_for_fifo(sc, 2); 962 switch (sc->bits_per_pixel) { 963 case 8: 964 regw(sc, DP_PIX_WIDTH, HOST_8BPP | SRC_8BPP | DST_8BPP); 965 regw(sc, DP_CHAIN_MASK, DP_CHAIN_8BPP); 966 /* XXX Macallan: huh? We /want/ an 8 bit per channel palette! */ 967 /*regw(sc, DAC_CNTL, regr(sc, DAC_CNTL) & ~DAC_8BIT_EN);*/ 968 regw(sc, DAC_CNTL, regr(sc, DAC_CNTL) | DAC_8BIT_EN); 969 break; 970 #if 0 971 case 32: 972 regw(sc, DP_PIX_WIDTH, HOST_32BPP | SRC_32BPP | DST_32BPP); 973 regw(sc, DP_CHAIN_MASK, DP_CHAIN_32BPP); 974 regw(sc, DAC_CNTL, regr(sc, DAC_CNTL) | DAC_8BIT_EN); 975 break; 976 #endif 977 } 978 979 wait_for_fifo(sc, 5); 980 regw(sc, CRTC_INT_CNTL, regr(sc, CRTC_INT_CNTL) & ~0x20); 981 regw(sc, GUI_TRAJ_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM); 982 983 wait_for_idle(sc); 984 } 985 986 void 987 mach64_adjust_frame(struct mach64_softc *sc, int x, int y) 988 { 989 int offset; 990 991 offset = ((x + y * sc->virt_x) * (sc->bits_per_pixel >> 3)) >> 3; 992 993 regw(sc, CRTC_OFF_PITCH, (regr(sc, CRTC_OFF_PITCH) & 0xfff00000) | 994 offset); 995 } 996 997 void 998 mach64_set_dsp(struct mach64_softc *sc) 999 { 1000 u_int32_t fifo_depth, page_size, dsp_precision, dsp_loop_latency; 1001 u_int32_t dsp_off, dsp_on, dsp_xclks_per_qw; 1002 u_int32_t xclks_per_qw, y; 1003 u_int32_t fifo_off, fifo_on; 1004 1005 if (mach64_chip_id == PCI_PRODUCT_ATI_MACH64_VT || 1006 mach64_chip_id == PCI_PRODUCT_ATI_RAGE_II || 1007 mach64_chip_id == PCI_PRODUCT_ATI_RAGE_IIP || 1008 mach64_chip_id == PCI_PRODUCT_ATI_RAGE_IIC_PCI || 1009 mach64_chip_id == PCI_PRODUCT_ATI_RAGE_IIC_AGP_B || 1010 mach64_chip_id == PCI_PRODUCT_ATI_RAGE_IIC_AGP_P) { 1011 dsp_loop_latency = 0; 1012 fifo_depth = 24; 1013 } else { 1014 dsp_loop_latency = 2; 1015 fifo_depth = 32; 1016 } 1017 1018 dsp_precision = 0; 1019 xclks_per_qw = (sc->mclk_fb_div * sc->vclk_post_div * 64 << 11) / 1020 (sc->vclk_fb_div * sc->mclk_post_div * sc->bits_per_pixel); 1021 y = (xclks_per_qw * fifo_depth) >> 11; 1022 while (y) { 1023 y >>= 1; 1024 dsp_precision++; 1025 } 1026 dsp_precision -= 5; 1027 fifo_off = ((xclks_per_qw * (fifo_depth - 1)) >> 5) + (3 << 6); 1028 1029 switch (sc->memtype) { 1030 case DRAM: 1031 case EDO_DRAM: 1032 case PSEUDO_EDO: 1033 if (sc->memsize > 1024) { 1034 page_size = 9; 1035 dsp_loop_latency += 6; 1036 } else { 1037 page_size = 10; 1038 if (sc->memtype == DRAM) 1039 dsp_loop_latency += 8; 1040 else 1041 dsp_loop_latency += 7; 1042 } 1043 break; 1044 case SDRAM: 1045 case SGRAM: 1046 if (sc->memsize > 1024) { 1047 page_size = 8; 1048 dsp_loop_latency += 8; 1049 } else { 1050 page_size = 10; 1051 dsp_loop_latency += 9; 1052 } 1053 break; 1054 default: 1055 page_size = 10; 1056 dsp_loop_latency += 9; 1057 break; 1058 } 1059 1060 if (xclks_per_qw >= (page_size << 11)) 1061 fifo_on = ((2 * page_size + 1) << 6) + (xclks_per_qw >> 5); 1062 else 1063 fifo_on = (3 * page_size + 2) << 6; 1064 1065 dsp_xclks_per_qw = xclks_per_qw >> dsp_precision; 1066 dsp_on = fifo_on >> dsp_precision; 1067 dsp_off = fifo_off >> dsp_precision; 1068 1069 #ifdef MACH64_DEBUG 1070 printf("dsp_xclks_per_qw = %d, dsp_on = %d, dsp_off = %d,\n" 1071 "dsp_precision = %d, dsp_loop_latency = %d,\n" 1072 "mclk_fb_div = %d, vclk_fb_div = %d,\n" 1073 "mclk_post_div = %d, vclk_post_div = %d\n", 1074 dsp_xclks_per_qw, dsp_on, dsp_off, dsp_precision, dsp_loop_latency, 1075 sc->mclk_fb_div, sc->vclk_fb_div, 1076 sc->mclk_post_div, sc->vclk_post_div); 1077 #endif 1078 1079 regw(sc, DSP_ON_OFF, ((dsp_on << 16) & DSP_ON) | (dsp_off & DSP_OFF)); 1080 regw(sc, DSP_CONFIG, ((dsp_precision << 20) & DSP_PRECISION) | 1081 ((dsp_loop_latency << 16) & DSP_LOOP_LATENCY) | 1082 (dsp_xclks_per_qw & DSP_XCLKS_PER_QW)); 1083 } 1084 1085 void 1086 mach64_set_pll(struct mach64_softc *sc, int clock) 1087 { 1088 int q; 1089 1090 q = (clock * sc->ref_div * 100) / (2 * sc->ref_freq); 1091 #ifdef MACH64_DEBUG 1092 printf("q = %d\n", q); 1093 #endif 1094 if (q > 25500) { 1095 printf("Warning: q > 25500\n"); 1096 q = 25500; 1097 sc->vclk_post_div = 1; 1098 sc->log2_vclk_post_div = 0; 1099 } else if (q > 12750) { 1100 sc->vclk_post_div = 1; 1101 sc->log2_vclk_post_div = 0; 1102 } else if (q > 6350) { 1103 sc->vclk_post_div = 2; 1104 sc->log2_vclk_post_div = 1; 1105 } else if (q > 3150) { 1106 sc->vclk_post_div = 4; 1107 sc->log2_vclk_post_div = 2; 1108 } else if (q >= 1600) { 1109 sc->vclk_post_div = 8; 1110 sc->log2_vclk_post_div = 3; 1111 } else { 1112 printf("Warning: q < 1600\n"); 1113 sc->vclk_post_div = 8; 1114 sc->log2_vclk_post_div = 3; 1115 } 1116 sc->vclk_fb_div = q * sc->vclk_post_div / 100; 1117 1118 regwb_pll(sc, MCLK_FB_DIV, sc->mclk_fb_div); 1119 regwb_pll(sc, VCLK_POST_DIV, sc->log2_vclk_post_div); 1120 regwb_pll(sc, VCLK0_FB_DIV, sc->vclk_fb_div); 1121 } 1122 1123 void 1124 mach64_init_lut(struct mach64_softc *sc) 1125 { 1126 /* XXX this is pretty dodgy since it's perfectly possible that 1127 both terminal emulations are compiled into the kernel, in this 1128 case we'd install the VT100 colour map which may be wrong */ 1129 #ifdef WSEMUL_SUN 1130 mach64_putpalreg(sc,0,255,255,255); 1131 mach64_putpalreg(sc,1,0,0,0); 1132 mach64_putpalreg(sc,255,0,0,0); 1133 #endif 1134 #ifdef WSEMUL_VT100 1135 { 1136 int i,idx; 1137 idx=0; 1138 for(i=0;i<256;i++) { 1139 mach64_putpalreg(sc,i,rasops_cmap[idx],rasops_cmap[idx+1],rasops_cmap[idx+2]); 1140 idx+=3; 1141 } 1142 } 1143 #endif 1144 } 1145 1146 int mach64_putpalreg(struct mach64_softc *sc, uint8_t index, uint8_t r, uint8_t g, uint8_t b) 1147 { 1148 sc->sc_cmap_red[index]=r; 1149 sc->sc_cmap_green[index]=g; 1150 sc->sc_cmap_blue[index]=b; 1151 /* writing the dac index takes a while, in theory we can poll some register 1152 to see when it's ready - but we better avoid writing it unnecessarily */ 1153 if(index!=sc->sc_dacw) 1154 { 1155 regwb(sc, DAC_MASK, 0xff); 1156 regwb(sc, DAC_WINDEX, index); 1157 } 1158 sc->sc_dacw=index+1; 1159 regwb(sc, DAC_DATA, r); 1160 regwb(sc, DAC_DATA, g); 1161 regwb(sc, DAC_DATA, b); 1162 return 0; 1163 } 1164 1165 int mach64_putcmap(struct mach64_softc *sc, struct wsdisplay_cmap *cm) 1166 { 1167 u_int index = cm->index; 1168 u_int count = cm->count; 1169 int i, error; 1170 u_char rbuf[256], gbuf[256], bbuf[256]; 1171 u_char *r, *g, *b; 1172 1173 printf("putcmap: %d %d\n",index, count); 1174 if (cm->index >= 256 || cm->count > 256 || 1175 (cm->index + cm->count) > 256) 1176 return EINVAL; 1177 error = copyin(cm->red, &rbuf[index], count); 1178 if (error) 1179 return error; 1180 error = copyin(cm->green, &gbuf[index], count); 1181 if (error) 1182 return error; 1183 error = copyin(cm->blue, &bbuf[index], count); 1184 if (error) 1185 return error; 1186 1187 memcpy(&sc->sc_cmap_red[index], &rbuf[index], count); 1188 memcpy(&sc->sc_cmap_green[index], &gbuf[index], count); 1189 memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count); 1190 1191 r = &sc->sc_cmap_red[index]; 1192 g = &sc->sc_cmap_green[index]; 1193 b = &sc->sc_cmap_blue[index]; 1194 1195 for (i = 0; i < count; i++) { 1196 mach64_putpalreg(sc,index,*r, *g, *b); 1197 index++; 1198 r++, g++, b++; 1199 } 1200 return 0; 1201 } 1202 1203 int mach64_getcmap(struct mach64_softc *sc, struct wsdisplay_cmap *cm) 1204 { 1205 u_int index = cm->index; 1206 u_int count = cm->count; 1207 int error; 1208 1209 if (index >= 255 || count > 256 || index + count > 256) 1210 return EINVAL; 1211 1212 error = copyout(&sc->sc_cmap_red[index], cm->red, count); 1213 if (error) 1214 return error; 1215 error = copyout(&sc->sc_cmap_green[index], cm->green, count); 1216 if (error) 1217 return error; 1218 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count); 1219 if (error) 1220 return error; 1221 1222 return 0; 1223 } 1224 1225 void 1226 mach64_switch_screen(struct mach64_softc *sc) 1227 { 1228 struct mach64screen *scr, *oldscr; 1229 const struct wsscreen_descr *type; 1230 1231 scr = sc->wanted; 1232 if (!scr) { 1233 printf("mach64_switch_screen: disappeared\n"); 1234 (*sc->switchcb)(sc->switchcbarg, EIO, 0); 1235 return; 1236 } 1237 type = scr->type; 1238 oldscr = sc->active; /* can be NULL! */ 1239 #ifdef DIAGNOSTIC 1240 if (oldscr) { 1241 if (!oldscr->active) 1242 panic("mach64_switch_screen: not active"); 1243 if (oldscr->type != sc->currenttype) 1244 panic("mach64_switch_screen: bad type"); 1245 } 1246 #endif 1247 if (scr == oldscr) 1248 return; 1249 1250 #ifdef DIAGNOSTIC 1251 /* XXX Macallan: this one bites us at reboot */ 1252 /* if (scr->active) 1253 panic("mach64_switch_screen: active");*/ 1254 #endif 1255 1256 if (oldscr) 1257 oldscr->active = 0; 1258 1259 if (sc->currenttype != type) { 1260 mach64_set_screentype(sc, type); 1261 sc->currenttype = type; 1262 } 1263 1264 scr->dispoffset = scr->mindispoffset; 1265 1266 if (!oldscr || (scr->dispoffset != oldscr->dispoffset)) { 1267 1268 } 1269 1270 /* Clear the entire screen. */ 1271 1272 scr->active = 1; 1273 mach64_restore_screen(scr, type, scr->mem); 1274 1275 sc->active = scr; 1276 1277 mach64_cursor(scr, scr->cursoron, scr->cursorrow, scr->cursorcol); 1278 1279 sc->wanted = 0; 1280 if (sc->switchcb) 1281 (*sc->switchcb)(sc->switchcbarg, 0, 0); 1282 } 1283 1284 void 1285 mach64_restore_screen(struct mach64screen *scr, 1286 const struct wsscreen_descr *type, u_int16_t *mem) 1287 { 1288 1289 } 1290 1291 int 1292 mach64_set_screentype(struct mach64_softc *sc, const struct wsscreen_descr *des) 1293 { 1294 struct mach64_crtcregs regs; 1295 1296 if (mach64_calc_crtcregs(sc, ®s, 1297 (struct videomode *)des->modecookie)) 1298 return 1; 1299 1300 mach64_set_crtcregs(sc, ®s); 1301 return 0; 1302 } 1303 1304 int 1305 mach64_is_console(struct pci_attach_args *pa) 1306 { 1307 #ifdef __sparc__ 1308 int node; 1309 1310 node = PCITAG_NODE(pa->pa_tag); 1311 if (node == -1) 1312 return 0; 1313 1314 return (node == prom_instance_to_package(prom_stdout())); 1315 #elif defined(__powerpc__) 1316 /* check if we're the /chosen console device */ 1317 int chosen, stdout, node, us; 1318 us=pcidev_to_ofdev(pa->pa_pc, pa->pa_tag); 1319 chosen = OF_finddevice("/chosen"); 1320 OF_getprop(chosen, "stdout", &stdout, 4); 1321 node = OF_instance_to_package(stdout); 1322 printf("us : %08x\n",us); 1323 printf("inst: %08x\n",stdout); 1324 printf("node: %08x\n",node); 1325 return((us==node)||(us==stdout)); 1326 #else 1327 return 1; 1328 #endif 1329 } 1330 1331 /* 1332 * wsdisplay_emulops 1333 */ 1334 1335 void 1336 mach64_cursor(void *cookie, int on, int row, int col) 1337 { 1338 1339 } 1340 1341 #if 0 1342 int 1343 mach64_mapchar(void *cookie, int uni, u_int *index) 1344 { 1345 1346 return 0; 1347 } 1348 1349 void 1350 mach64_putchar(void *cookie, int row, int col, u_int c, long attr) 1351 { 1352 1353 } 1354 #endif 1355 1356 void 1357 mach64_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) 1358 { 1359 struct rasops_info *ri=cookie; 1360 struct mach64_softc *sc=ri->ri_hw; 1361 int32_t xs,xd,y,width,height; 1362 1363 xs=ri->ri_xorigin+ri->ri_font->fontwidth*srccol; 1364 xd=ri->ri_xorigin+ri->ri_font->fontwidth*dstcol; 1365 y=ri->ri_yorigin+ri->ri_font->fontheight*row; 1366 width=ri->ri_font->fontwidth*ncols; 1367 height=ri->ri_font->fontheight; 1368 mach64_bitblt(sc,xs,y,xd,y,width,height,MIX_SRC,0xff); 1369 } 1370 1371 void 1372 mach64_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr) 1373 { 1374 struct rasops_info *ri=cookie; 1375 struct mach64_softc *sc=ri->ri_hw; 1376 int32_t x,y,width,height,fg,bg,ul;; 1377 1378 x=ri->ri_xorigin+ri->ri_font->fontwidth*startcol; 1379 y=ri->ri_yorigin+ri->ri_font->fontheight*row; 1380 width=ri->ri_font->fontwidth*ncols; 1381 height=ri->ri_font->fontheight; 1382 rasops_unpack_attr(fillattr,&fg,&bg,&ul); 1383 1384 mach64_rectfill(sc,x,y,width,height,bg); 1385 1386 } 1387 1388 void 1389 mach64_copyrows(void *cookie, int srcrow, int dstrow, int nrows) 1390 { 1391 struct rasops_info *ri=cookie; 1392 struct mach64_softc *sc=ri->ri_hw; 1393 int32_t x,ys,yd,width,height; 1394 1395 x=ri->ri_xorigin; 1396 ys=ri->ri_yorigin+ri->ri_font->fontheight*srcrow; 1397 yd=ri->ri_yorigin+ri->ri_font->fontheight*dstrow; 1398 width=ri->ri_emuwidth; 1399 height=ri->ri_font->fontheight*nrows; 1400 mach64_bitblt(sc,x,ys,x,yd,width,height,MIX_SRC,0xff); 1401 } 1402 1403 void mach64_bitblt(struct mach64_softc *sc, int xs, int ys, int xd, int yd, int width, int height, int rop, 1404 int mask) 1405 { 1406 uint32_t dest_ctl=0; 1407 wait_for_idle(sc); 1408 regw(sc,DP_WRITE_MASK,mask); /* XXX only good for 8 bit */ 1409 regw(sc,DP_PIX_WIDTH,DST_8BPP|SRC_8BPP|HOST_8BPP); 1410 regw(sc,DP_SRC,FRGD_SRC_BLIT); 1411 regw(sc,DP_MIX,(rop&0xffff)<<16); 1412 regw(sc,CLR_CMP_CNTL,0); /* no transparency */ 1413 if(yd<ys) { 1414 dest_ctl=DST_Y_TOP_TO_BOTTOM; 1415 } else { 1416 ys+=height-1; 1417 yd+=height-1; 1418 dest_ctl=DST_Y_BOTTOM_TO_TOP; 1419 } 1420 if(xd<xs) { 1421 dest_ctl|=DST_X_LEFT_TO_RIGHT; 1422 regw(sc,SRC_CNTL,SRC_LINE_X_LEFT_TO_RIGHT); 1423 } else { 1424 dest_ctl|=DST_X_RIGHT_TO_LEFT; 1425 xs+=width-1; 1426 xd+=width-1; 1427 regw(sc,SRC_CNTL,SRC_LINE_X_RIGHT_TO_LEFT); 1428 } 1429 regw(sc,DST_CNTL,dest_ctl); 1430 1431 regw(sc,SRC_Y_X,(xs<<16)|ys); 1432 regw(sc,SRC_WIDTH1,width); 1433 regw(sc,DST_Y_X,(xd<<16)|yd); 1434 regw(sc,DST_HEIGHT_WIDTH,(width<<16)|height); 1435 /* as long as the other rasops* functions aren't aware of the blitter we must wait here 1436 or the blitter might not be done when someone else draws the next line */ 1437 wait_for_idle(sc); 1438 } 1439 1440 void mach64_rectfill(struct mach64_softc *sc, int x, int y, int width, int height, int colour) 1441 { 1442 wait_for_idle(sc); 1443 regw(sc,DP_WRITE_MASK,0xff); 1444 regw(sc,DP_FRGD_CLR,colour); 1445 regw(sc,DP_PIX_WIDTH,DST_8BPP|SRC_8BPP|HOST_8BPP); 1446 regw(sc,DP_SRC,FRGD_SRC_FRGD_CLR); 1447 regw(sc,DP_MIX,(MIX_SRC)<<16); 1448 regw(sc,CLR_CMP_CNTL,0); /* no transparency */ 1449 regw(sc,SRC_CNTL,SRC_LINE_X_LEFT_TO_RIGHT); 1450 regw(sc,DST_CNTL,DST_X_LEFT_TO_RIGHT|DST_Y_TOP_TO_BOTTOM); 1451 1452 regw(sc,SRC_Y_X,(x<<16)|y); 1453 regw(sc,SRC_WIDTH1,width); 1454 regw(sc,DST_Y_X,(x<<16)|y); 1455 regw(sc,DST_HEIGHT_WIDTH,(width<<16)|height); 1456 wait_for_idle(sc); 1457 } 1458 1459 void mach64_showpal(struct mach64_softc *sc) 1460 { 1461 int i,x=0; 1462 for (i=0;i<16;i++) { 1463 mach64_rectfill(sc,x,0,64,64,i); 1464 x+=64; 1465 } 1466 } 1467 1468 int 1469 mach64_allocattr(void *cookie, int fg, int bg, int flags, long *attrp) 1470 { 1471 1472 return 0; 1473 } 1474 1475 void 1476 mach64_eraserows(void *cookie, int row, int nrows, long fillattr) 1477 { 1478 struct rasops_info *ri=cookie; 1479 struct mach64_softc *sc=ri->ri_hw; 1480 int32_t x,y,width,height,fg,bg,ul; 1481 1482 x=ri->ri_xorigin; 1483 y=ri->ri_yorigin+ri->ri_font->fontheight*row; 1484 width=ri->ri_emuwidth; 1485 height=ri->ri_font->fontheight*nrows; 1486 rasops_unpack_attr(fillattr,&fg,&bg,&ul); 1487 1488 mach64_rectfill(sc,x,y,width,height,bg); 1489 } 1490 1491 /* 1492 * wsdisplay_accessops 1493 */ 1494 1495 int 1496 mach64_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) 1497 { 1498 /* we'll probably need to add more stuff here */ 1499 struct mach64_softc *sc = v; 1500 struct wsdisplay_fbinfo *wdf; 1501 struct mach64screen *ms=sc->active; 1502 switch (cmd) { 1503 case WSDISPLAYIO_GTYPE: 1504 *(u_int *)data = WSDISPLAY_TYPE_PCIMISC; /* XXX ? */ 1505 return 0; 1506 1507 case WSDISPLAYIO_GINFO: 1508 wdf = (void *)data; 1509 wdf->height = ms->ri.ri_height; 1510 wdf->width = ms->ri.ri_width; 1511 wdf->depth = ms->ri.ri_depth; 1512 wdf->cmsize = 256; 1513 return 0; 1514 case WSDISPLAYIO_GETCMAP: 1515 return mach64_getcmap(sc, (struct wsdisplay_cmap *)data); 1516 1517 case WSDISPLAYIO_PUTCMAP: 1518 return mach64_putcmap(sc, (struct wsdisplay_cmap *)data); 1519 /* PCI config read/write passthrough. */ 1520 case PCI_IOC_CFGREAD: 1521 case PCI_IOC_CFGWRITE: 1522 return (pci_devioctl(sc->sc_pc, sc->sc_pcitag, 1523 cmd, data, flag, p)); 1524 #ifdef notyet 1525 case WSDISPLAYIO_SMODE: 1526 { 1527 int new_mode=*(int*)data; 1528 if(new_mode!=sc->sc_mode) 1529 { 1530 sc->sc_mode=new_mode; 1531 if(new_mode==WSDISPLAYIO_MODE_EMUL) 1532 { 1533 /* we'll probably want to reset the console into a known state here 1534 just in case the Xserver crashed or didn't properly clean up after 1535 itself for whetever reason */ 1536 } 1537 } 1538 } 1539 #endif 1540 } 1541 return EPASSTHROUGH; 1542 } 1543 1544 paddr_t 1545 mach64_mmap(void *v, off_t offset, int prot) 1546 { 1547 struct mach64_softc *sc = v; 1548 paddr_t pa; 1549 /* 'regular' framebuffer mmap()ing */ 1550 if(offset<sc->sc_apersize) { 1551 pa = bus_space_mmap(sc->sc_memt,sc->sc_aperbase+offset,0,prot,BUS_SPACE_MAP_LINEAR); 1552 return pa; 1553 } 1554 #if 0 1555 /* allow XFree86 to mmap() PCI space as if the BARs contain physical addresses */ 1556 if((offset>0x80000000) && (offset<=0xffffffff)) { 1557 pa = bus_space_mmap(sc->sc_memt,offset,0,prot,BUS_SPACE_MAP_LINEAR); 1558 return pa; 1559 } 1560 #endif 1561 1562 if((offset>=sc->sc_aperphys) && (offset<(sc->sc_aperphys+sc->sc_apersize))) { 1563 pa = bus_space_mmap(sc->sc_memt,offset,0,prot,BUS_SPACE_MAP_LINEAR); 1564 return pa; 1565 } 1566 1567 if((offset>=sc->sc_regphys) && (offset<(sc->sc_regphys+sc->sc_regsize))) { 1568 pa = bus_space_mmap(sc->sc_memt,offset,0,prot,BUS_SPACE_MAP_LINEAR); 1569 return pa; 1570 } 1571 1572 return -1; 1573 } 1574 1575 int 1576 mach64_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, 1577 int *curxp, int *curyp, long *defattrp) 1578 { 1579 struct mach64_softc *sc = v; 1580 struct mach64screen *scr; 1581 1582 scr = malloc(sizeof(struct mach64screen), M_DEVBUF, M_WAITOK|M_ZERO); 1583 mach64_init_screen(sc, scr, type, 0, defattrp, sc->active == NULL); 1584 rasops_init(&scr->ri, mach64_console_screen.ri.ri_height / 16, 1585 mach64_console_screen.ri.ri_width / 8); 1586 scr->ri.ri_hw=sc; 1587 scr->ri.ri_ops.copyrows=mach64_copyrows; 1588 scr->ri.ri_ops.eraserows=mach64_eraserows; 1589 scr->ri.ri_ops.copycols=mach64_copycols; 1590 scr->ri.ri_ops.erasecols=mach64_erasecols; 1591 1592 scr->mem = malloc(type->ncols * type->nrows * 2, M_DEVBUF, 1593 M_WAITOK); 1594 mach64_eraserows(&scr->ri, 0, type->nrows, *defattrp); 1595 if (sc->active == NULL) { 1596 scr->active = 1; 1597 sc->active = scr; 1598 sc->currenttype = type; 1599 } 1600 1601 *cookiep = scr; 1602 *curxp = scr->cursorcol; 1603 *curyp = scr->cursorrow; 1604 1605 return 0; 1606 } 1607 1608 void 1609 mach64_free_screen(void *v, void *cookie) 1610 { 1611 struct mach64_softc *sc = v; 1612 struct mach64screen *scr = cookie; 1613 1614 LIST_REMOVE(scr, next); 1615 if (scr != &mach64_console_screen) 1616 free(scr, M_DEVBUF); 1617 else 1618 panic("mach64_free_screen: console"); 1619 1620 if (sc->active == scr) 1621 sc->active = 0; 1622 } 1623 1624 int 1625 mach64_show_screen(void *v, void *cookie, int waitok, 1626 void (*cb)(void *, int, int), void *cbarg) 1627 { 1628 struct mach64_softc *sc = v; 1629 struct mach64screen *scr, *oldscr; 1630 1631 scr = cookie; 1632 oldscr = sc->active; 1633 if (scr == oldscr) 1634 return 0; 1635 1636 sc->wanted = scr; 1637 sc->switchcb = cb; 1638 sc->switchcbarg = cbarg; 1639 if (cb) { 1640 callout_reset(&sc->switch_callout, 0, 1641 (void(*)(void *))mach64_switch_screen, sc); 1642 return EAGAIN; 1643 } 1644 1645 mach64_switch_screen(sc); 1646 1647 return 0; 1648 } 1649 1650 #if 0 1651 int 1652 mach64_load_font(void *v, void *cookie, struct wsdisplay_font *data) 1653 { 1654 1655 return 0; 1656 } 1657 #endif 1658