1 /* $NetBSD: machfb.c,v 1.56 2009/01/03 03:43:22 yamt Exp $ */
4 * Copyright (c) 2002 Bang Jun-Young
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
31 * Some code is derived from ATI Rage Pro and Derivatives Programmer's Guide.
34 #include <sys/cdefs.h>
36 "$NetBSD: machfb.c,v 1.56 2009/01/03 03:43:22 yamt Exp $");
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/device.h>
42 #include <sys/malloc.h>
43 #include <sys/callout.h>
44 #include <sys/kauth.h>
47 #include <machine/promlib.h>
51 #include <dev/ofw/openfirm.h>
52 #include <dev/ofw/ofw_pci.h>
55 #include <dev/videomode/videomode.h>
57 #include <dev/pci/pcivar.h>
58 #include <dev/pci/pcireg.h>
59 #include <dev/pci/pcidevs.h>
60 #include <dev/pci/pciio.h>
61 #include <dev/pci/machfbreg.h>
64 #include <dev/sun/fbio.h>
65 #include <dev/sun/fbvar.h>
68 #include <dev/wscons/wsdisplayvar.h>
71 #include <dev/wscons/wsconsio.h>
72 #include <dev/wsfont/wsfont.h>
73 #include <dev/rasops/rasops.h>
75 #include <dev/wscons/wsdisplay_vconsvar.h>
77 #define MACH64_REG_SIZE 1024
78 #define MACH64_REG_OFF 0x7ffc00
80 #define NBARS 3 /* number of Mach64 PCI BARs */
93 struct fbdevice sc_fb
;
95 pci_chipset_tag_t sc_pc
;
98 struct vga_bar sc_bars
[NBARS
];
99 struct vga_bar sc_rom
;
101 #define sc_aperbase sc_bars[0].vb_base
102 #define sc_apersize sc_bars[0].vb_size
103 #define sc_aperphys sc_bars[0].vb_busaddr
105 #define sc_iobase sc_bars[1].vb_base
106 #define sc_iosize sc_bars[1].vb_size
108 #define sc_regbase sc_bars[2].vb_base
109 #define sc_regsize sc_bars[2].vb_size
110 #define sc_regphys sc_bars[2].vb_busaddr
112 bus_space_tag_t sc_regt
;
113 bus_space_tag_t sc_memt
;
114 bus_space_handle_t sc_regh
;
115 bus_space_handle_t sc_memh
;
116 void *sc_aperture
; /* mapped aperture vaddr */
117 void *sc_registers
; /* mapped registers vaddr */
119 uint32_t sc_nbus
, sc_ndev
, sc_nfunc
;
140 int log2_vclk_post_div
;
146 struct videomode
*sc_my_mode
;
147 u_char sc_cmap_red
[256];
148 u_char sc_cmap_green
[256];
149 u_char sc_cmap_blue
[256];
150 int sc_dacw
, sc_blanked
, sc_console
;
151 struct vcons_data vd
;
154 struct mach64_crtcregs
{
155 uint32_t h_total_disp
;
156 uint32_t h_sync_strt_wid
;
157 uint32_t v_total_disp
;
158 uint32_t v_sync_strt_wid
;
161 uint32_t color_depth
;
167 uint32_t ramdac_freq
;
168 } const mach64_info
[] = {
169 { PCI_PRODUCT_ATI_MACH64_CT
, 135000 },
170 { PCI_PRODUCT_ATI_RAGE_PRO_AGP
, 230000 },
171 { PCI_PRODUCT_ATI_RAGE_PRO_AGP1X
, 230000 },
172 { PCI_PRODUCT_ATI_RAGE_PRO_PCI_B
, 230000 },
173 { PCI_PRODUCT_ATI_RAGE_XL_AGP
, 230000 },
174 { PCI_PRODUCT_ATI_RAGE_PRO_PCI_P
, 230000 },
175 { PCI_PRODUCT_ATI_RAGE_PRO_PCI_L
, 230000 },
176 { PCI_PRODUCT_ATI_RAGE_XL_PCI
, 230000 },
177 { PCI_PRODUCT_ATI_RAGE_II
, 135000 },
178 { PCI_PRODUCT_ATI_RAGE_IIP
, 200000 },
179 { PCI_PRODUCT_ATI_RAGE_IIC_PCI
, 230000 },
180 { PCI_PRODUCT_ATI_RAGE_IIC_AGP_B
, 230000 },
181 { 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 },
191 { PCI_PRODUCT_ATI_MACH64_VT
, 170000 },
192 { PCI_PRODUCT_ATI_MACH64_VTB
, 200000 },
193 { PCI_PRODUCT_ATI_MACH64_VT4
, 230000 }
196 static int mach64_chip_id
, mach64_chip_rev
;
197 static struct videomode default_mode
= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
199 static const char *mach64_memtype_names
[] = {
200 "(N/A)", "DRAM", "EDO DRAM", "EDO DRAM", "SDRAM", "SGRAM", "WRAM",
204 static struct videomode mach64_modes
[] = {
205 /* 640x400 @ 70 Hz, 31.5 kHz */
206 { 25175, 640, 664, 760, 800, 400, 409, 411, 450, 0, NULL
, },
207 /* 640x480 @ 72 Hz, 36.5 kHz */
208 { 25175, 640, 664, 760, 800, 480, 491, 493, 525, 0, NULL
, },
209 /* 800x600 @ 72 Hz, 48.0 kHz */
210 { 50000, 800, 856, 976, 1040, 600, 637, 643, 666,
211 VID_PHSYNC
| VID_PVSYNC
, NULL
, },
212 /* 1024x768 @ 70 Hz, 56.5 kHz */
213 { 75000, 1024, 1048, 1184, 1328, 768, 771, 777, 806,
214 VID_NHSYNC
| VID_NVSYNC
, NULL
, },
215 /* 1152x864 @ 70 Hz, 62.4 kHz */
216 { 92000, 1152, 1208, 1368, 1474, 864, 865, 875, 895, 0, NULL
, },
217 /* 1280x1024 @ 70 Hz, 74.59 kHz */
218 { 126500, 1280, 1312, 1472, 1696, 1024, 1032, 1040, 1068,
219 VID_NHSYNC
| VID_NVSYNC
, NULL
, }
222 extern const u_char rasops_cmap
[768];
224 static int mach64_match(device_t
, cfdata_t
, void *);
225 static void mach64_attach(device_t
, device_t
, void *);
227 CFATTACH_DECL(machfb
, sizeof(struct mach64_softc
), mach64_match
, mach64_attach
,
230 static void mach64_init(struct mach64_softc
*);
231 static int mach64_get_memsize(struct mach64_softc
*);
232 static int mach64_get_max_ramdac(struct mach64_softc
*);
234 #if defined(__sparc__) || defined(__powerpc__)
235 static void mach64_get_mode(struct mach64_softc
*, struct videomode
*);
238 static int mach64_calc_crtcregs(struct mach64_softc
*,
239 struct mach64_crtcregs
*,
241 static void mach64_set_crtcregs(struct mach64_softc
*,
242 struct mach64_crtcregs
*);
244 static int mach64_modeswitch(struct mach64_softc
*, struct videomode
*);
245 static void mach64_set_dsp(struct mach64_softc
*);
246 static void mach64_set_pll(struct mach64_softc
*, int);
247 static void mach64_reset_engine(struct mach64_softc
*);
248 static void mach64_init_engine(struct mach64_softc
*);
250 static void mach64_adjust_frame(struct mach64_softc
*, int, int);
252 static void mach64_init_lut(struct mach64_softc
*);
254 static void mach64_init_screen(void *, struct vcons_screen
*, int, long *);
255 static int mach64_set_screentype(struct mach64_softc
*,
256 const struct wsscreen_descr
*);
257 static int mach64_is_console(struct pci_attach_args
*);
259 static void mach64_cursor(void *, int, int, int);
261 static int mach64_mapchar(void *, int, u_int
*);
263 static void mach64_putchar(void *, int, int, u_int
, long);
264 static void mach64_copycols(void *, int, int, int, int);
265 static void mach64_erasecols(void *, int, int, int, long);
266 static void mach64_copyrows(void *, int, int, int);
267 static void mach64_eraserows(void *, int, int, long);
268 static int mach64_allocattr(void *, int, int, int, long *);
269 static void mach64_clearscreen(struct mach64_softc
*);
271 static int mach64_putcmap(struct mach64_softc
*, struct wsdisplay_cmap
*);
272 static int mach64_getcmap(struct mach64_softc
*, struct wsdisplay_cmap
*);
273 static int mach64_putpalreg(struct mach64_softc
*, uint8_t, uint8_t,
275 static void mach64_bitblt(struct mach64_softc
*, int, int, int, int, int,
277 static void mach64_rectfill(struct mach64_softc
*, int, int, int, int, int);
278 static void mach64_setup_mono(struct mach64_softc
*, int, int, int, int,
280 static void mach64_feed_bytes(struct mach64_softc
*, int, uint8_t *);
282 static void mach64_showpal(struct mach64_softc
*);
285 static void set_address(struct rasops_info
*, void *);
286 static void machfb_blank(struct mach64_softc
*, int);
289 static const struct wsdisplay_emulops mach64_emulops
= {
301 static struct wsscreen_descr mach64_defaultscreen
= {
306 WSSCREEN_WSCOLORS
| WSSCREEN_HILIT
,
308 }, mach64_80x25_screen
= {
312 WSSCREEN_WSCOLORS
| WSSCREEN_HILIT
,
314 }, mach64_80x30_screen
= {
318 WSSCREEN_WSCOLORS
| WSSCREEN_HILIT
,
320 }, mach64_80x40_screen
= {
324 WSSCREEN_WSCOLORS
| WSSCREEN_HILIT
,
326 }, mach64_80x50_screen
= {
330 WSSCREEN_WSCOLORS
| WSSCREEN_HILIT
,
332 }, mach64_100x37_screen
= {
336 WSSCREEN_WSCOLORS
| WSSCREEN_HILIT
,
338 }, mach64_128x48_screen
= {
342 WSSCREEN_WSCOLORS
| WSSCREEN_HILIT
,
344 }, mach64_144x54_screen
= {
348 WSSCREEN_WSCOLORS
| WSSCREEN_HILIT
,
350 }, mach64_160x64_screen
= {
354 WSSCREEN_WSCOLORS
| WSSCREEN_HILIT
,
358 static const struct wsscreen_descr
*_mach64_scrlist
[] = {
359 &mach64_defaultscreen
,
360 &mach64_80x25_screen
,
361 &mach64_80x30_screen
,
362 &mach64_80x40_screen
,
363 &mach64_80x50_screen
,
364 &mach64_100x37_screen
,
365 &mach64_128x48_screen
,
366 &mach64_144x54_screen
,
367 &mach64_160x64_screen
370 static struct wsscreen_list mach64_screenlist
= {
371 __arraycount(_mach64_scrlist
),
375 static int mach64_ioctl(void *, void *, u_long
, void *, int,
377 static paddr_t
mach64_mmap(void *, void *, off_t
, int);
380 static int mach64_load_font(void *, void *, struct wsdisplay_font
*);
383 static struct wsdisplay_accessops mach64_accessops
= {
386 NULL
, /* vcons_alloc_screen */
387 NULL
, /* vcons_free_screen */
388 NULL
, /* vcons_show_screen */
389 NULL
, /* load_font */
394 static struct vcons_screen mach64_console_screen
;
396 /* framebuffer device, SPARC-only so far */
399 static void machfb_unblank(device_t
);
400 static void machfb_fbattach(struct mach64_softc
*);
402 extern struct cfdriver machfb_cd
;
404 dev_type_open(machfb_fbopen
);
405 dev_type_close(machfb_fbclose
);
406 dev_type_ioctl(machfb_fbioctl
);
407 dev_type_mmap(machfb_fbmmap
);
409 /* frame buffer generic driver */
410 static struct fbdriver machfb_fbdriver
= {
411 machfb_unblank
, machfb_fbopen
, machfb_fbclose
, machfb_fbioctl
, nopoll
,
412 machfb_fbmmap
, nokqfilter
415 #endif /* __sparc__ */
418 * Inline functions for getting access to register aperture.
421 static inline uint32_t
422 regr(struct mach64_softc
*sc
, uint32_t index
)
424 return bus_space_read_4(sc
->sc_regt
, sc
->sc_regh
, index
);
427 static inline uint8_t
428 regrb(struct mach64_softc
*sc
, uint32_t index
)
430 return bus_space_read_1(sc
->sc_regt
, sc
->sc_regh
, index
);
434 regw(struct mach64_softc
*sc
, uint32_t index
, uint32_t data
)
436 bus_space_write_4(sc
->sc_regt
, sc
->sc_regh
, index
, data
);
437 bus_space_barrier(sc
->sc_regt
, sc
->sc_regh
, index
, 4,
438 BUS_SPACE_BARRIER_WRITE
);
442 regwb(struct mach64_softc
*sc
, uint32_t index
, uint8_t data
)
444 bus_space_write_1(sc
->sc_regt
, sc
->sc_regh
, index
, data
);
445 bus_space_barrier(sc
->sc_regt
, sc
->sc_regh
, index
, 1,
446 BUS_SPACE_BARRIER_WRITE
);
450 regwb_pll(struct mach64_softc
*sc
, uint32_t index
, uint8_t data
)
452 regwb(sc
, CLOCK_CNTL
+ 1, (index
<< 2) | PLL_WR_EN
);
453 regwb(sc
, CLOCK_CNTL
+ 2, data
);
454 regwb(sc
, CLOCK_CNTL
+ 1, (index
<< 2) & ~PLL_WR_EN
);
458 wait_for_fifo(struct mach64_softc
*sc
, uint8_t v
)
460 while ((regr(sc
, FIFO_STAT
) & 0xffff) > (0x8000 >> v
))
465 wait_for_idle(struct mach64_softc
*sc
)
467 wait_for_fifo(sc
, 16);
468 while ((regr(sc
, GUI_STAT
) & 1) != 0)
473 mach64_match(device_t parent
, cfdata_t match
, void *aux
)
475 struct pci_attach_args
*pa
= (struct pci_attach_args
*)aux
;
478 if (PCI_CLASS(pa
->pa_class
) != PCI_CLASS_DISPLAY
||
479 PCI_SUBCLASS(pa
->pa_class
) != PCI_SUBCLASS_DISPLAY_VGA
)
482 for (i
= 0; i
< __arraycount(mach64_info
); i
++)
483 if (PCI_PRODUCT(pa
->pa_id
) == mach64_info
[i
].chip_id
) {
484 mach64_chip_id
= PCI_PRODUCT(pa
->pa_id
);
485 mach64_chip_rev
= PCI_REVISION(pa
->pa_class
);
493 mach64_attach(device_t parent
, device_t self
, void *aux
)
495 struct mach64_softc
*sc
= device_private(self
);
496 struct pci_attach_args
*pa
= aux
;
497 struct rasops_info
*ri
;
500 struct wsemuldisplaydev_attach_args aa
;
505 sc
->sc_pc
= pa
->pa_pc
;
506 sc
->sc_pcitag
= pa
->pa_tag
;
508 sc
->sc_mode
= WSDISPLAYIO_MODE_EMUL
;
509 sc
->sc_nbus
= pa
->pa_bus
;
510 sc
->sc_ndev
= pa
->pa_device
;
511 sc
->sc_nfunc
= pa
->pa_function
;
514 pci_devinfo(pa
->pa_id
, pa
->pa_class
, 0, devinfo
, sizeof(devinfo
));
515 printf(": %s (rev. 0x%02x)\n", devinfo
, PCI_REVISION(pa
->pa_class
));
517 /* enable memory and IO access */
518 screg
= pci_conf_read(sc
->sc_pc
, sc
->sc_pcitag
, PCI_COMMAND_STATUS_REG
);
519 screg
|= PCI_FLAGS_IO_ENABLED
| PCI_FLAGS_MEM_ENABLED
;
520 pci_conf_write(sc
->sc_pc
, sc
->sc_pcitag
,PCI_COMMAND_STATUS_REG
,screg
);
522 for (bar
= 0; bar
< NBARS
; bar
++) {
523 reg
= PCI_MAPREG_START
+ (bar
* 4);
524 sc
->sc_bars
[bar
].vb_type
= pci_mapreg_type(sc
->sc_pc
,
526 (void)pci_mapreg_info(sc
->sc_pc
, sc
->sc_pcitag
, reg
,
527 sc
->sc_bars
[bar
].vb_type
, &sc
->sc_bars
[bar
].vb_base
,
528 &sc
->sc_bars
[bar
].vb_size
, &sc
->sc_bars
[bar
].vb_flags
);
529 sc
->sc_bars
[bar
].vb_busaddr
= pci_conf_read(sc
->sc_pc
,
530 sc
->sc_pcitag
, reg
)&0xfffffff0;
532 sc
->sc_memt
= pa
->pa_memt
;
536 printf("%s: %d MB aperture at 0x%08x, %d KB registers at 0x%08x\n",
537 device_xname(&sc
->sc_dev
), (u_int
)(sc
->sc_apersize
/ (1024 * 1024)),
538 (u_int
)sc
->sc_aperphys
, (u_int
)(sc
->sc_regsize
/ 1024),
539 (u_int
)sc
->sc_regphys
);
541 if (mach64_chip_id
== PCI_PRODUCT_ATI_MACH64_CT
||
542 ((mach64_chip_id
== PCI_PRODUCT_ATI_MACH64_VT
||
543 mach64_chip_id
== PCI_PRODUCT_ATI_RAGE_II
) &&
544 (mach64_chip_rev
& 0x07) == 0))
549 sc
->memsize
= mach64_get_memsize(sc
);
550 if (sc
->memsize
== 8192)
551 /* The last page is used as register aperture. */
553 sc
->memtype
= regr(sc
, CONFIG_STAT0
) & 0x07;
555 /* XXX is there any way to calculate reference frequency from
557 if ((mach64_chip_id
== PCI_PRODUCT_ATI_RAGE_XL_PCI
) ||
558 ((mach64_chip_id
>= PCI_PRODUCT_ATI_RAGE_LT_PRO_PCI
) &&
559 (mach64_chip_id
<= PCI_PRODUCT_ATI_RAGE_LT_PRO
))) {
560 printf("%s: ref_freq=29.498MHz\n", device_xname(&sc
->sc_dev
));
561 sc
->ref_freq
= 29498;
563 sc
->ref_freq
= 14318;
565 regwb(sc
, CLOCK_CNTL
+ 1, PLL_REF_DIV
<< 2);
566 sc
->ref_div
= regrb(sc
, CLOCK_CNTL
+ 2);
567 regwb(sc
, CLOCK_CNTL
+ 1, MCLK_FB_DIV
<< 2);
568 sc
->mclk_fb_div
= regrb(sc
, CLOCK_CNTL
+ 2);
569 sc
->mem_freq
= (2 * sc
->ref_freq
* sc
->mclk_fb_div
) /
571 sc
->mclk_post_div
= (sc
->mclk_fb_div
* 2 * sc
->ref_freq
) /
572 (sc
->mem_freq
* sc
->ref_div
);
573 sc
->ramdac_freq
= mach64_get_max_ramdac(sc
);
574 printf("%s: %ld KB %s %d.%d MHz, maximum RAMDAC clock %d MHz\n",
575 device_xname(&sc
->sc_dev
), (u_long
)sc
->memsize
,
576 mach64_memtype_names
[sc
->memtype
],
577 sc
->mem_freq
/ 1000, sc
->mem_freq
% 1000,
578 sc
->ramdac_freq
/ 1000);
580 id
= regr(sc
, CONFIG_CHIP_ID
) & 0xffff;
581 if (id
!= mach64_chip_id
) {
582 printf("%s: chip ID mismatch, 0x%x != 0x%x\n",
583 device_xname(&sc
->sc_dev
), id
, mach64_chip_id
);
587 sc
->sc_console
= mach64_is_console(pa
);
589 printf("gen_cntl: %08x\n", regr(sc
, CRTC_GEN_CNTL
));
591 #if defined(__sparc__) || defined(__powerpc__)
592 if (sc
->sc_console
) {
593 mach64_get_mode(sc
, &default_mode
);
595 sc
->sc_my_mode
= &default_mode
;
597 /* fill in default_mode if it's empty */
598 mach64_get_mode(sc
, &default_mode
);
599 if (default_mode
.dot_clock
== 0) {
600 memcpy(&default_mode
, &mach64_modes
[4],
601 sizeof(default_mode
));
603 sc
->sc_my_mode
= &default_mode
;
607 if (default_mode
.dot_clock
== 0) {
608 memcpy(&default_mode
, &mach64_modes
[0],
609 sizeof(default_mode
));
611 sc
->sc_my_mode
= &mach64_modes
[0];
615 sc
->bits_per_pixel
= 8;
616 sc
->virt_x
= sc
->sc_my_mode
->hdisplay
;
617 sc
->virt_y
= sc
->sc_my_mode
->vdisplay
;
618 sc
->max_x
= sc
->virt_x
- 1;
619 sc
->max_y
= (sc
->memsize
* 1024) /
620 (sc
->virt_x
* (sc
->bits_per_pixel
/ 8)) - 1;
622 sc
->color_depth
= CRTC_PIX_WIDTH_8BPP
;
624 mach64_init_engine(sc
);
626 mach64_adjust_frame(0, 0);
627 if (sc
->bits_per_pixel
== 8)
631 printf("%s: initial resolution %dx%d at %d bpp\n", device_xname(&sc
->sc_dev
),
632 sc
->sc_my_mode
->hdisplay
, sc
->sc_my_mode
->vdisplay
,
641 sc
->sc_bg
= WS_DEFAULT_BG
;
642 vcons_init(&sc
->vd
, sc
, &mach64_defaultscreen
, &mach64_accessops
);
643 sc
->vd
.init_screen
= mach64_init_screen
;
645 if (sc
->sc_console
) {
646 vcons_init_screen(&sc
->vd
, &mach64_console_screen
, 1,
648 mach64_console_screen
.scr_flags
|= VCONS_SCREEN_IS_STATIC
;
650 ri
= &mach64_console_screen
.scr_ri
;
651 mach64_defaultscreen
.textops
= &ri
->ri_ops
;
652 mach64_defaultscreen
.capabilities
= ri
->ri_caps
;
653 mach64_defaultscreen
.nrows
= ri
->ri_rows
;
654 mach64_defaultscreen
.ncols
= ri
->ri_cols
;
655 wsdisplay_cnattach(&mach64_defaultscreen
, ri
, 0, 0, defattr
);
658 * since we're not the console we can postpone the rest
659 * until someone actually allocates a screen for us
661 mach64_modeswitch(sc
, sc
->sc_my_mode
);
665 mach64_clearscreen(sc
);
666 machfb_blank(sc
, 0); /* unblank the screen */
668 aa
.console
= sc
->sc_console
;
669 aa
.scrdata
= &mach64_screenlist
;
670 aa
.accessops
= &mach64_accessops
;
671 aa
.accesscookie
= &sc
->vd
;
673 config_found(self
, &aa
, wsemuldisplaydevprint
);
677 mach64_init_screen(void *cookie
, struct vcons_screen
*scr
, int existing
,
680 struct mach64_softc
*sc
= cookie
;
681 struct rasops_info
*ri
= &scr
->scr_ri
;
686 ri
->ri_depth
= sc
->bits_per_pixel
;
687 ri
->ri_width
= sc
->sc_my_mode
->hdisplay
;
688 ri
->ri_height
= sc
->sc_my_mode
->vdisplay
;
689 ri
->ri_stride
= ri
->ri_width
;
690 ri
->ri_flg
= RI_CENTER
;
691 set_address(ri
, sc
->sc_aperture
);
694 ri
->ri_flg
|= RI_CLEAR
;
695 if (setmode
&& mach64_set_screentype(sc
, scr
->scr_type
)) {
696 panic("%s: failed to switch video mode",
697 device_xname(&sc
->sc_dev
));
701 rasops_init(ri
, sc
->sc_my_mode
->vdisplay
/8,
702 sc
->sc_my_mode
->hdisplay
/8);
703 ri
->ri_caps
= WSSCREEN_WSCOLORS
;
705 rasops_reconfig(ri
, sc
->sc_my_mode
->vdisplay
/ ri
->ri_font
->fontheight
,
706 sc
->sc_my_mode
->hdisplay
/ ri
->ri_font
->fontwidth
);
708 /* enable acceleration */
710 ri
->ri_ops
.copyrows
= mach64_copyrows
;
711 ri
->ri_ops
.copycols
= mach64_copycols
;
712 ri
->ri_ops
.eraserows
= mach64_eraserows
;
713 ri
->ri_ops
.erasecols
= mach64_erasecols
;
714 ri
->ri_ops
.cursor
= mach64_cursor
;
715 ri
->ri_ops
.putchar
= mach64_putchar
;
716 ri
->ri_ops
.allocattr
= mach64_allocattr
;
720 mach64_init(struct mach64_softc
*sc
)
722 uint32_t *p32
, saved_value
;
726 if (bus_space_map(sc
->sc_memt
, sc
->sc_aperbase
, sc
->sc_apersize
,
727 BUS_SPACE_MAP_LINEAR
, &sc
->sc_memh
)) {
728 panic("%s: failed to map aperture", device_xname(&sc
->sc_dev
));
730 sc
->sc_aperture
= (void *)bus_space_vaddr(sc
->sc_memt
, sc
->sc_memh
);
732 sc
->sc_regt
= sc
->sc_memt
;
733 bus_space_subregion(sc
->sc_regt
, sc
->sc_memh
, MACH64_REG_OFF
,
734 sc
->sc_regsize
, &sc
->sc_regh
);
735 sc
->sc_registers
= (char *)sc
->sc_aperture
+ 0x7ffc00;
738 * Test wether the aperture is byte swapped or not
740 p32
= (uint32_t*)sc
->sc_aperture
;
742 p
= (uint8_t*)(u_long
)sc
->sc_aperture
;
744 if (p
[0] == 0x12 && p
[1] == 0x34 && p
[2] == 0x56 && p
[3] == 0x78)
749 sc
->sc_aperture
= (char *)sc
->sc_aperture
+ 0x800000;
750 sc
->sc_aperbase
+= 0x800000;
751 sc
->sc_apersize
-= 0x800000;
759 mach64_get_memsize(struct mach64_softc
*sc
)
763 512, 1024, 2048, 4096, 6144, 8192, 12288, 16384
765 tmp
= regr(sc
, MEM_CNTL
);
767 printf("%s: memctl %08x\n", device_xname(&sc
->sc_dev
), tmp
);
772 memsize
= (tmp
+ 1) * 512;
774 memsize
= (tmp
- 3) * 1024;
776 memsize
= (tmp
- 7) * 2048;
778 memsize
= mem_tab
[tmp
& 0x07];
785 mach64_get_max_ramdac(struct mach64_softc
*sc
)
789 if ((mach64_chip_id
== PCI_PRODUCT_ATI_MACH64_VT
||
790 mach64_chip_id
== PCI_PRODUCT_ATI_RAGE_II
) &&
791 (mach64_chip_rev
& 0x07))
794 for (i
= 0; i
< __arraycount(mach64_info
); i
++)
795 if (mach64_chip_id
== mach64_info
[i
].chip_id
)
796 return mach64_info
[i
].ramdac_freq
;
798 if (sc
->bits_per_pixel
== 8)
804 #if defined(__sparc__) || defined(__powerpc__)
806 mach64_get_mode(struct mach64_softc
*sc
, struct videomode
*mode
)
808 struct mach64_crtcregs crtc
;
810 crtc
.h_total_disp
= regr(sc
, CRTC_H_TOTAL_DISP
);
811 crtc
.h_sync_strt_wid
= regr(sc
, CRTC_H_SYNC_STRT_WID
);
812 crtc
.v_total_disp
= regr(sc
, CRTC_V_TOTAL_DISP
);
813 crtc
.v_sync_strt_wid
= regr(sc
, CRTC_V_SYNC_STRT_WID
);
815 mode
->htotal
= ((crtc
.h_total_disp
& 0xffff) + 1) << 3;
816 mode
->hdisplay
= ((crtc
.h_total_disp
>> 16) + 1) << 3;
817 mode
->hsync_start
= ((crtc
.h_sync_strt_wid
& 0xffff) + 1) << 3;
818 mode
->hsync_end
= ((crtc
.h_sync_strt_wid
>> 16) << 3) +
820 mode
->vtotal
= (crtc
.v_total_disp
& 0xffff) + 1;
821 mode
->vdisplay
= (crtc
.v_total_disp
>> 16) + 1;
822 mode
->vsync_start
= (crtc
.v_sync_strt_wid
& 0xffff) + 1;
823 mode
->vsync_end
= (crtc
.v_sync_strt_wid
>> 16) + mode
->vsync_start
;
826 printf("mach64_get_mode: %d %d %d %d %d %d %d %d\n",
827 mode
->hdisplay
, mode
->hsync_start
, mode
->hsync_end
, mode
->htotal
,
828 mode
->vdisplay
, mode
->vsync_start
, mode
->vsync_end
, mode
->vtotal
);
834 mach64_calc_crtcregs(struct mach64_softc
*sc
, struct mach64_crtcregs
*crtc
,
835 struct videomode
*mode
)
838 if (mode
->dot_clock
> sc
->ramdac_freq
)
839 /* Clock too high. */
842 crtc
->h_total_disp
= (((mode
->hdisplay
>> 3) - 1) << 16) |
843 ((mode
->htotal
>> 3) - 1);
844 crtc
->h_sync_strt_wid
=
845 (((mode
->hsync_end
- mode
->hsync_start
) >> 3) << 16) |
846 ((mode
->hsync_start
>> 3) - 1);
848 crtc
->v_total_disp
= ((mode
->vdisplay
- 1) << 16) |
850 crtc
->v_sync_strt_wid
=
851 ((mode
->vsync_end
- mode
->vsync_start
) << 16) |
852 (mode
->vsync_start
- 1);
854 if (mode
->flags
& VID_NVSYNC
)
855 crtc
->v_sync_strt_wid
|= CRTC_VSYNC_NEG
;
857 switch (sc
->bits_per_pixel
) {
859 crtc
->color_depth
= CRTC_PIX_WIDTH_8BPP
;
862 crtc
->color_depth
= CRTC_PIX_WIDTH_16BPP
;
865 crtc
->color_depth
= CRTC_PIX_WIDTH_32BPP
;
870 if (mode
->flags
& VID_INTERLACE
)
871 crtc
->gen_cntl
|= CRTC_INTERLACE_EN
;
873 if (mode
->flags
& VID_CSYNC
)
874 crtc
->gen_cntl
|= CRTC_CSYNC_EN
;
876 crtc
->dot_clock
= mode
->dot_clock
;
882 mach64_set_crtcregs(struct mach64_softc
*sc
, struct mach64_crtcregs
*crtc
)
885 mach64_set_pll(sc
, crtc
->dot_clock
);
890 regw(sc
, CRTC_H_TOTAL_DISP
, crtc
->h_total_disp
);
891 regw(sc
, CRTC_H_SYNC_STRT_WID
, crtc
->h_sync_strt_wid
);
892 regw(sc
, CRTC_V_TOTAL_DISP
, crtc
->v_total_disp
);
893 regw(sc
, CRTC_V_SYNC_STRT_WID
, crtc
->v_sync_strt_wid
);
895 regw(sc
, CRTC_VLINE_CRNT_VLINE
, 0);
897 regw(sc
, CRTC_OFF_PITCH
, (sc
->virt_x
>> 3) << 22);
899 regw(sc
, CRTC_GEN_CNTL
, crtc
->gen_cntl
| crtc
->color_depth
|
900 /* XXX this unconditionally enables composite sync on SPARC */
904 CRTC_EXT_DISP_EN
| CRTC_EXT_EN
);
908 mach64_modeswitch(struct mach64_softc
*sc
, struct videomode
*mode
)
910 struct mach64_crtcregs crtc
;
912 memset(&crtc
, 0, sizeof crtc
); /* XXX gcc */
914 if (mach64_calc_crtcregs(sc
, &crtc
, mode
))
917 mach64_set_crtcregs(sc
, &crtc
);
922 mach64_reset_engine(struct mach64_softc
*sc
)
926 regw(sc
, GEN_TEST_CNTL
, regr(sc
, GEN_TEST_CNTL
) & ~GUI_ENGINE_ENABLE
);
929 regw(sc
, GEN_TEST_CNTL
, regr(sc
, GEN_TEST_CNTL
) | GUI_ENGINE_ENABLE
);
931 /* Ensure engine is not locked up by clearing any FIFO or
933 regw(sc
, BUS_CNTL
, regr(sc
, BUS_CNTL
) | BUS_HOST_ERR_ACK
|
938 mach64_init_engine(struct mach64_softc
*sc
)
940 uint32_t pitch_value
;
942 pitch_value
= sc
->virt_x
;
944 if (sc
->bits_per_pixel
== 24)
947 mach64_reset_engine(sc
);
949 wait_for_fifo(sc
, 14);
951 regw(sc
, CONTEXT_MASK
, 0xffffffff);
953 regw(sc
, DST_OFF_PITCH
, (pitch_value
/ 8) << 22);
955 regw(sc
, DST_Y_X
, 0);
956 regw(sc
, DST_HEIGHT
, 0);
957 regw(sc
, DST_BRES_ERR
, 0);
958 regw(sc
, DST_BRES_INC
, 0);
959 regw(sc
, DST_BRES_DEC
, 0);
961 regw(sc
, DST_CNTL
, DST_LAST_PEL
| DST_X_LEFT_TO_RIGHT
|
962 DST_Y_TOP_TO_BOTTOM
);
964 regw(sc
, SRC_OFF_PITCH
, (pitch_value
/ 8) << 22);
966 regw(sc
, SRC_Y_X
, 0);
967 regw(sc
, SRC_HEIGHT1_WIDTH1
, 1);
968 regw(sc
, SRC_Y_X_START
, 0);
969 regw(sc
, SRC_HEIGHT2_WIDTH2
, 1);
971 regw(sc
, SRC_CNTL
, SRC_LINE_X_LEFT_TO_RIGHT
);
973 wait_for_fifo(sc
, 13);
974 regw(sc
, HOST_CNTL
, 0);
976 regw(sc
, PAT_REG0
, 0);
977 regw(sc
, PAT_REG1
, 0);
978 regw(sc
, PAT_CNTL
, 0);
980 regw(sc
, SC_LEFT
, 0);
982 regw(sc
, SC_BOTTOM
, sc
->sc_my_mode
->vdisplay
- 1);
983 regw(sc
, SC_RIGHT
, pitch_value
- 1);
985 regw(sc
, DP_BKGD_CLR
, 0);
986 regw(sc
, DP_FRGD_CLR
, 0xffffffff);
987 regw(sc
, DP_WRITE_MASK
, 0xffffffff);
988 regw(sc
, DP_MIX
, (MIX_SRC
<< 16) | MIX_DST
);
990 regw(sc
, DP_SRC
, FRGD_SRC_FRGD_CLR
);
992 wait_for_fifo(sc
, 3);
993 regw(sc
, CLR_CMP_CLR
, 0);
994 regw(sc
, CLR_CMP_MASK
, 0xffffffff);
995 regw(sc
, CLR_CMP_CNTL
, 0);
997 wait_for_fifo(sc
, 2);
998 switch (sc
->bits_per_pixel
) {
1000 regw(sc
, DP_PIX_WIDTH
, HOST_8BPP
| SRC_8BPP
| DST_8BPP
);
1001 regw(sc
, DP_CHAIN_MASK
, DP_CHAIN_8BPP
);
1002 /* We want 8 bit per channel */
1003 regw(sc
, DAC_CNTL
, regr(sc
, DAC_CNTL
) | DAC_8BIT_EN
);
1007 regw(sc
, DP_PIX_WIDTH
, HOST_32BPP
| SRC_32BPP
| DST_32BPP
);
1008 regw(sc
, DP_CHAIN_MASK
, DP_CHAIN_32BPP
);
1009 regw(sc
, DAC_CNTL
, regr(sc
, DAC_CNTL
) | DAC_8BIT_EN
);
1014 wait_for_fifo(sc
, 5);
1015 regw(sc
, CRTC_INT_CNTL
, regr(sc
, CRTC_INT_CNTL
) & ~0x20);
1016 regw(sc
, GUI_TRAJ_CNTL
, DST_X_LEFT_TO_RIGHT
| DST_Y_TOP_TO_BOTTOM
);
1023 mach64_adjust_frame(struct mach64_softc
*sc
, int x
, int y
)
1027 offset
= ((x
+ y
* sc
->virt_x
) * (sc
->bits_per_pixel
>> 3)) >> 3;
1029 regw(sc
, CRTC_OFF_PITCH
, (regr(sc
, CRTC_OFF_PITCH
) & 0xfff00000) |
1035 mach64_set_dsp(struct mach64_softc
*sc
)
1037 uint32_t fifo_depth
, page_size
, dsp_precision
, dsp_loop_latency
;
1038 uint32_t dsp_off
, dsp_on
, dsp_xclks_per_qw
;
1039 uint32_t xclks_per_qw
, y
;
1040 uint32_t fifo_off
, fifo_on
;
1042 printf("%s: initializing the DSP\n", device_xname(&sc
->sc_dev
));
1043 if (mach64_chip_id
== PCI_PRODUCT_ATI_MACH64_VT
||
1044 mach64_chip_id
== PCI_PRODUCT_ATI_RAGE_II
||
1045 mach64_chip_id
== PCI_PRODUCT_ATI_RAGE_IIP
||
1046 mach64_chip_id
== PCI_PRODUCT_ATI_RAGE_IIC_PCI
||
1047 mach64_chip_id
== PCI_PRODUCT_ATI_RAGE_IIC_AGP_B
||
1048 mach64_chip_id
== PCI_PRODUCT_ATI_RAGE_IIC_AGP_P
) {
1049 dsp_loop_latency
= 0;
1052 dsp_loop_latency
= 2;
1057 xclks_per_qw
= (sc
->mclk_fb_div
* sc
->vclk_post_div
* 64 << 11) /
1058 (sc
->vclk_fb_div
* sc
->mclk_post_div
* sc
->bits_per_pixel
);
1059 y
= (xclks_per_qw
* fifo_depth
) >> 11;
1065 fifo_off
= ((xclks_per_qw
* (fifo_depth
- 1)) >> 5) + (3 << 6);
1067 switch (sc
->memtype
) {
1071 if (sc
->memsize
> 1024) {
1073 dsp_loop_latency
+= 6;
1076 if (sc
->memtype
== DRAM
)
1077 dsp_loop_latency
+= 8;
1079 dsp_loop_latency
+= 7;
1084 if (sc
->memsize
> 1024) {
1086 dsp_loop_latency
+= 8;
1089 dsp_loop_latency
+= 9;
1094 dsp_loop_latency
+= 9;
1098 if (xclks_per_qw
>= (page_size
<< 11))
1099 fifo_on
= ((2 * page_size
+ 1) << 6) + (xclks_per_qw
>> 5);
1101 fifo_on
= (3 * page_size
+ 2) << 6;
1103 dsp_xclks_per_qw
= xclks_per_qw
>> dsp_precision
;
1104 dsp_on
= fifo_on
>> dsp_precision
;
1105 dsp_off
= fifo_off
>> dsp_precision
;
1108 printf("dsp_xclks_per_qw = %d, dsp_on = %d, dsp_off = %d,\n"
1109 "dsp_precision = %d, dsp_loop_latency = %d,\n"
1110 "mclk_fb_div = %d, vclk_fb_div = %d,\n"
1111 "mclk_post_div = %d, vclk_post_div = %d\n",
1112 dsp_xclks_per_qw
, dsp_on
, dsp_off
, dsp_precision
, dsp_loop_latency
,
1113 sc
->mclk_fb_div
, sc
->vclk_fb_div
,
1114 sc
->mclk_post_div
, sc
->vclk_post_div
);
1117 regw(sc
, DSP_ON_OFF
, ((dsp_on
<< 16) & DSP_ON
) | (dsp_off
& DSP_OFF
));
1118 regw(sc
, DSP_CONFIG
, ((dsp_precision
<< 20) & DSP_PRECISION
) |
1119 ((dsp_loop_latency
<< 16) & DSP_LOOP_LATENCY
) |
1120 (dsp_xclks_per_qw
& DSP_XCLKS_PER_QW
));
1124 mach64_set_pll(struct mach64_softc
*sc
, int clock
)
1128 q
= (clock
* sc
->ref_div
* 100) / (2 * sc
->ref_freq
);
1130 printf("q = %d\n", q
);
1133 printf("Warning: q > 25500\n");
1135 sc
->vclk_post_div
= 1;
1136 sc
->log2_vclk_post_div
= 0;
1137 } else if (q
> 12750) {
1138 sc
->vclk_post_div
= 1;
1139 sc
->log2_vclk_post_div
= 0;
1140 } else if (q
> 6350) {
1141 sc
->vclk_post_div
= 2;
1142 sc
->log2_vclk_post_div
= 1;
1143 } else if (q
> 3150) {
1144 sc
->vclk_post_div
= 4;
1145 sc
->log2_vclk_post_div
= 2;
1146 } else if (q
>= 1600) {
1147 sc
->vclk_post_div
= 8;
1148 sc
->log2_vclk_post_div
= 3;
1150 printf("Warning: q < 1600\n");
1151 sc
->vclk_post_div
= 8;
1152 sc
->log2_vclk_post_div
= 3;
1154 sc
->vclk_fb_div
= q
* sc
->vclk_post_div
/ 100;
1156 regwb_pll(sc
, MCLK_FB_DIV
, sc
->mclk_fb_div
);
1157 regwb_pll(sc
, VCLK_POST_DIV
, sc
->log2_vclk_post_div
);
1158 regwb_pll(sc
, VCLK0_FB_DIV
, sc
->vclk_fb_div
);
1162 mach64_init_lut(struct mach64_softc
*sc
)
1167 for (i
= 0; i
< 256; i
++) {
1168 mach64_putpalreg(sc
, i
, rasops_cmap
[idx
], rasops_cmap
[idx
+ 1],
1169 rasops_cmap
[idx
+ 2]);
1175 mach64_putpalreg(struct mach64_softc
*sc
, uint8_t index
, uint8_t r
, uint8_t g
,
1178 sc
->sc_cmap_red
[index
] = r
;
1179 sc
->sc_cmap_green
[index
] = g
;
1180 sc
->sc_cmap_blue
[index
] = b
;
1182 * writing the dac index takes a while, in theory we can poll some
1183 * register to see when it's ready - but we better avoid writing it
1186 if (index
!= sc
->sc_dacw
) {
1187 regwb(sc
, DAC_MASK
, 0xff);
1188 regwb(sc
, DAC_WINDEX
, index
);
1190 sc
->sc_dacw
= index
+ 1;
1191 regwb(sc
, DAC_DATA
, r
);
1192 regwb(sc
, DAC_DATA
, g
);
1193 regwb(sc
, DAC_DATA
, b
);
1198 mach64_putcmap(struct mach64_softc
*sc
, struct wsdisplay_cmap
*cm
)
1200 uint index
= cm
->index
;
1201 uint count
= cm
->count
;
1203 uint8_t rbuf
[256], gbuf
[256], bbuf
[256];
1206 if (cm
->index
>= 256 || cm
->count
> 256 ||
1207 (cm
->index
+ cm
->count
) > 256)
1209 error
= copyin(cm
->red
, &rbuf
[index
], count
);
1212 error
= copyin(cm
->green
, &gbuf
[index
], count
);
1215 error
= copyin(cm
->blue
, &bbuf
[index
], count
);
1219 memcpy(&sc
->sc_cmap_red
[index
], &rbuf
[index
], count
);
1220 memcpy(&sc
->sc_cmap_green
[index
], &gbuf
[index
], count
);
1221 memcpy(&sc
->sc_cmap_blue
[index
], &bbuf
[index
], count
);
1223 r
= &sc
->sc_cmap_red
[index
];
1224 g
= &sc
->sc_cmap_green
[index
];
1225 b
= &sc
->sc_cmap_blue
[index
];
1227 for (i
= 0; i
< count
; i
++) {
1228 mach64_putpalreg(sc
, index
, *r
, *g
, *b
);
1236 mach64_getcmap(struct mach64_softc
*sc
, struct wsdisplay_cmap
*cm
)
1238 u_int index
= cm
->index
;
1239 u_int count
= cm
->count
;
1242 if (index
>= 255 || count
> 256 || index
+ count
> 256)
1245 error
= copyout(&sc
->sc_cmap_red
[index
], cm
->red
, count
);
1248 error
= copyout(&sc
->sc_cmap_green
[index
], cm
->green
, count
);
1251 error
= copyout(&sc
->sc_cmap_blue
[index
], cm
->blue
, count
);
1259 mach64_set_screentype(struct mach64_softc
*sc
, const struct wsscreen_descr
*des
)
1261 struct mach64_crtcregs regs
;
1263 if (mach64_calc_crtcregs(sc
, ®s
,
1264 (struct videomode
*)des
->modecookie
))
1267 mach64_set_crtcregs(sc
, ®s
);
1272 mach64_is_console(struct pci_attach_args
*pa
)
1277 node
= PCITAG_NODE(pa
->pa_tag
);
1281 return (node
== prom_instance_to_package(prom_stdout()));
1282 #elif defined(__powerpc__)
1283 /* check if we're the /chosen console device */
1284 int chosen
, stdout
, node
, us
;
1286 us
= pcidev_to_ofdev(pa
->pa_pc
, pa
->pa_tag
);
1287 chosen
= OF_finddevice("/chosen");
1288 OF_getprop(chosen
, "stdout", &stdout
, 4);
1289 node
= OF_instance_to_package(stdout
);
1290 return (us
== node
);
1301 mach64_cursor(void *cookie
, int on
, int row
, int col
)
1303 struct rasops_info
*ri
= cookie
;
1304 struct vcons_screen
*scr
= ri
->ri_hw
;
1305 struct mach64_softc
*sc
= scr
->scr_cookie
;
1308 wi
= ri
->ri_font
->fontwidth
;
1309 he
= ri
->ri_font
->fontheight
;
1311 if ((!sc
->sc_locked
) && (sc
->sc_mode
== WSDISPLAYIO_MODE_EMUL
)) {
1312 x
= ri
->ri_ccol
* wi
+ ri
->ri_xorigin
;
1313 y
= ri
->ri_crow
* he
+ ri
->ri_yorigin
;
1314 if (ri
->ri_flg
& RI_CURSOR
) {
1315 mach64_bitblt(sc
, x
, y
, x
, y
, wi
, he
, MIX_NOT_SRC
,
1317 ri
->ri_flg
&= ~RI_CURSOR
;
1322 x
= ri
->ri_ccol
* wi
+ ri
->ri_xorigin
;
1323 y
= ri
->ri_crow
* he
+ ri
->ri_yorigin
;
1324 mach64_bitblt(sc
, x
, y
, x
, y
, wi
, he
, MIX_NOT_SRC
,
1326 ri
->ri_flg
|= RI_CURSOR
;
1329 scr
->scr_ri
.ri_crow
= row
;
1330 scr
->scr_ri
.ri_ccol
= col
;
1331 scr
->scr_ri
.ri_flg
&= ~RI_CURSOR
;
1337 mach64_mapchar(void *cookie
, int uni
, u_int
*index
)
1344 mach64_putchar(void *cookie
, int row
, int col
, u_int c
, long attr
)
1346 struct rasops_info
*ri
= cookie
;
1347 struct vcons_screen
*scr
= ri
->ri_hw
;
1348 struct mach64_softc
*sc
= scr
->scr_cookie
;
1350 if (sc
->sc_mode
== WSDISPLAYIO_MODE_EMUL
) {
1354 wi
= ri
->ri_font
->fontwidth
;
1355 he
= ri
->ri_font
->fontheight
;
1357 if (!CHAR_IN_FONT(c
, ri
->ri_font
))
1359 bg
= (u_char
)ri
->ri_devcmap
[(attr
>> 16) & 0xf];
1360 fg
= (u_char
)ri
->ri_devcmap
[(attr
>> 24) & 0xf];
1361 x
= ri
->ri_xorigin
+ col
* wi
;
1362 y
= ri
->ri_yorigin
+ row
* he
;
1364 mach64_rectfill(sc
, x
, y
, wi
, he
, bg
);
1366 uc
= c
-ri
->ri_font
->firstchar
;
1367 data
= (uint8_t *)ri
->ri_font
->data
+ uc
*
1370 mach64_setup_mono(sc
, x
, y
, wi
, he
, fg
, bg
);
1371 mach64_feed_bytes(sc
, ri
->ri_fontscale
, data
);
1378 mach64_copycols(void *cookie
, int row
, int srccol
, int dstcol
, int ncols
)
1380 struct rasops_info
*ri
= cookie
;
1381 struct vcons_screen
*scr
= ri
->ri_hw
;
1382 struct mach64_softc
*sc
= scr
->scr_cookie
;
1383 int32_t xs
, xd
, y
, width
, height
;
1385 if ((sc
->sc_locked
== 0) && (sc
->sc_mode
== WSDISPLAYIO_MODE_EMUL
)) {
1386 xs
= ri
->ri_xorigin
+ ri
->ri_font
->fontwidth
* srccol
;
1387 xd
= ri
->ri_xorigin
+ ri
->ri_font
->fontwidth
* dstcol
;
1388 y
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* row
;
1389 width
= ri
->ri_font
->fontwidth
* ncols
;
1390 height
= ri
->ri_font
->fontheight
;
1391 mach64_bitblt(sc
, xs
, y
, xd
, y
, width
, height
, MIX_SRC
, 0xff);
1396 mach64_erasecols(void *cookie
, int row
, int startcol
, int ncols
, long fillattr
)
1398 struct rasops_info
*ri
= cookie
;
1399 struct vcons_screen
*scr
= ri
->ri_hw
;
1400 struct mach64_softc
*sc
= scr
->scr_cookie
;
1401 int32_t x
, y
, width
, height
, fg
, bg
, ul
;
1403 if ((sc
->sc_locked
== 0) && (sc
->sc_mode
== WSDISPLAYIO_MODE_EMUL
)) {
1404 x
= ri
->ri_xorigin
+ ri
->ri_font
->fontwidth
* startcol
;
1405 y
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* row
;
1406 width
= ri
->ri_font
->fontwidth
* ncols
;
1407 height
= ri
->ri_font
->fontheight
;
1408 rasops_unpack_attr(fillattr
, &fg
, &bg
, &ul
);
1410 mach64_rectfill(sc
, x
, y
, width
, height
, bg
);
1415 mach64_copyrows(void *cookie
, int srcrow
, int dstrow
, int nrows
)
1417 struct rasops_info
*ri
= cookie
;
1418 struct vcons_screen
*scr
= ri
->ri_hw
;
1419 struct mach64_softc
*sc
= scr
->scr_cookie
;
1420 int32_t x
, ys
, yd
, width
, height
;
1422 if ((sc
->sc_locked
== 0) && (sc
->sc_mode
== WSDISPLAYIO_MODE_EMUL
)) {
1424 ys
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* srcrow
;
1425 yd
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* dstrow
;
1426 width
= ri
->ri_emuwidth
;
1427 height
= ri
->ri_font
->fontheight
*nrows
;
1428 mach64_bitblt(sc
, x
, ys
, x
, yd
, width
, height
, MIX_SRC
, 0xff);
1433 mach64_eraserows(void *cookie
, int row
, int nrows
, long fillattr
)
1435 struct rasops_info
*ri
= cookie
;
1436 struct vcons_screen
*scr
= ri
->ri_hw
;
1437 struct mach64_softc
*sc
= scr
->scr_cookie
;
1438 int32_t x
, y
, width
, height
, fg
, bg
, ul
;
1440 if ((sc
->sc_locked
== 0) && (sc
->sc_mode
== WSDISPLAYIO_MODE_EMUL
)) {
1442 y
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* row
;
1443 width
= ri
->ri_emuwidth
;
1444 height
= ri
->ri_font
->fontheight
* nrows
;
1445 rasops_unpack_attr(fillattr
, &fg
, &bg
, &ul
);
1447 mach64_rectfill(sc
, x
, y
, width
, height
, bg
);
1452 mach64_bitblt(struct mach64_softc
*sc
, int xs
, int ys
, int xd
, int yd
, int width
, int height
, int rop
, int mask
)
1454 uint32_t dest_ctl
= 0;
1457 regw(sc
, DP_WRITE_MASK
, mask
); /* XXX only good for 8 bit */
1458 regw(sc
, DP_PIX_WIDTH
, DST_8BPP
| SRC_8BPP
| HOST_8BPP
);
1459 regw(sc
, DP_SRC
, FRGD_SRC_BLIT
);
1460 regw(sc
, DP_MIX
, (rop
& 0xffff) << 16);
1461 regw(sc
, CLR_CMP_CNTL
, 0); /* no transparency */
1463 dest_ctl
= DST_Y_TOP_TO_BOTTOM
;
1467 dest_ctl
= DST_Y_BOTTOM_TO_TOP
;
1470 dest_ctl
|= DST_X_LEFT_TO_RIGHT
;
1471 regw(sc
, SRC_CNTL
, SRC_LINE_X_LEFT_TO_RIGHT
);
1473 dest_ctl
|= DST_X_RIGHT_TO_LEFT
;
1476 regw(sc
, SRC_CNTL
, SRC_LINE_X_RIGHT_TO_LEFT
);
1478 regw(sc
, DST_CNTL
, dest_ctl
);
1480 regw(sc
, SRC_Y_X
, (xs
<< 16) | ys
);
1481 regw(sc
, SRC_WIDTH1
, width
);
1482 regw(sc
, DST_Y_X
, (xd
<< 16) | yd
);
1483 regw(sc
, DST_HEIGHT_WIDTH
, (width
<< 16) | height
);
1487 mach64_setup_mono(struct mach64_softc
*sc
, int xd
, int yd
, int width
,
1488 int height
, uint32_t fg
, uint32_t bg
)
1491 regw(sc
, DP_WRITE_MASK
, 0xff); /* XXX only good for 8 bit */
1492 regw(sc
, DP_PIX_WIDTH
, DST_8BPP
| SRC_1BPP
| HOST_1BPP
);
1493 regw(sc
, DP_SRC
, MONO_SRC_HOST
| BKGD_SRC_BKGD_CLR
| FRGD_SRC_FRGD_CLR
);
1494 regw(sc
, DP_MIX
, ((MIX_SRC
& 0xffff) << 16) | MIX_SRC
);
1495 regw(sc
, CLR_CMP_CNTL
,0); /* no transparency */
1496 regw(sc
, SRC_CNTL
, SRC_LINE_X_LEFT_TO_RIGHT
);
1497 regw(sc
, DST_CNTL
, DST_Y_TOP_TO_BOTTOM
| DST_X_LEFT_TO_RIGHT
);
1498 regw(sc
, HOST_CNTL
, HOST_BYTE_ALIGN
);
1499 regw(sc
, DP_BKGD_CLR
, bg
);
1500 regw(sc
, DP_FRGD_CLR
, fg
);
1501 regw(sc
, SRC_Y_X
, 0);
1502 regw(sc
, SRC_WIDTH1
, width
);
1503 regw(sc
, DST_Y_X
, (xd
<< 16) | yd
);
1504 regw(sc
, DST_HEIGHT_WIDTH
, (width
<< 16) | height
);
1505 /* now feed the data into the chip */
1509 mach64_feed_bytes(struct mach64_softc
*sc
, int count
, uint8_t *data
)
1512 uint32_t latch
= 0, bork
;
1516 for (i
=0;i
<count
;i
++) {
1518 latch
|= (bork
<< shift
);
1520 regw(sc
, HOST_DATA0
+ reg
, latch
);
1523 reg
= (reg
+ 4) & 0x3c;
1527 if (shift
!= 0) /* 24 */
1528 regw(sc
, HOST_DATA0
+ reg
, latch
);
1533 mach64_rectfill(struct mach64_softc
*sc
, int x
, int y
, int width
, int height
,
1537 regw(sc
, DP_WRITE_MASK
, 0xff);
1538 regw(sc
, DP_FRGD_CLR
, colour
);
1539 regw(sc
, DP_PIX_WIDTH
, DST_8BPP
| SRC_8BPP
| HOST_8BPP
);
1540 regw(sc
, DP_SRC
, FRGD_SRC_FRGD_CLR
);
1541 regw(sc
, DP_MIX
, MIX_SRC
<< 16);
1542 regw(sc
, CLR_CMP_CNTL
, 0); /* no transparency */
1543 regw(sc
, SRC_CNTL
, SRC_LINE_X_LEFT_TO_RIGHT
);
1544 regw(sc
, DST_CNTL
, DST_X_LEFT_TO_RIGHT
| DST_Y_TOP_TO_BOTTOM
);
1546 regw(sc
, SRC_Y_X
, (x
<< 16) | y
);
1547 regw(sc
, SRC_WIDTH1
, width
);
1548 regw(sc
, DST_Y_X
, (x
<< 16) | y
);
1549 regw(sc
, DST_HEIGHT_WIDTH
, (width
<< 16) | height
);
1553 mach64_clearscreen(struct mach64_softc
*sc
)
1555 mach64_rectfill(sc
, 0, 0, sc
->virt_x
, sc
->virt_y
, sc
->sc_bg
);
1561 mach64_showpal(struct mach64_softc
*sc
)
1565 for (i
= 0; i
< 16; i
++) {
1566 mach64_rectfill(sc
, x
, 0, 64, 64, i
);
1573 mach64_allocattr(void *cookie
, int fg
, int bg
, int flags
, long *attrp
)
1575 if ((fg
== 0) && (bg
== 0))
1580 *attrp
= (fg
& 0xf) << 24 | (bg
& 0xf) << 16 | (flags
& 0xff) << 8;
1585 * wsdisplay_accessops
1589 mach64_ioctl(void *v
, void *vs
, u_long cmd
, void *data
, int flag
,
1592 struct vcons_data
*vd
= v
;
1593 struct mach64_softc
*sc
= vd
->cookie
;
1594 struct wsdisplay_fbinfo
*wdf
;
1595 struct vcons_screen
*ms
= vd
->active
;
1598 case WSDISPLAYIO_GTYPE
:
1599 /* XXX is this the right type to return? */
1600 *(u_int
*)data
= WSDISPLAY_TYPE_PCIMISC
;
1603 case WSDISPLAYIO_LINEBYTES
:
1604 *(u_int
*)data
= sc
->virt_x
* sc
->bits_per_pixel
/ 8;
1607 case WSDISPLAYIO_GINFO
:
1609 wdf
->height
= sc
->virt_y
;
1610 wdf
->width
= sc
->virt_x
;
1611 wdf
->depth
= sc
->bits_per_pixel
;
1615 case WSDISPLAYIO_GETCMAP
:
1616 return mach64_getcmap(sc
,
1617 (struct wsdisplay_cmap
*)data
);
1619 case WSDISPLAYIO_PUTCMAP
:
1620 return mach64_putcmap(sc
,
1621 (struct wsdisplay_cmap
*)data
);
1623 /* PCI config read/write passthrough. */
1624 case PCI_IOC_CFGREAD
:
1625 case PCI_IOC_CFGWRITE
:
1626 return (pci_devioctl(sc
->sc_pc
, sc
->sc_pcitag
,
1627 cmd
, data
, flag
, l
));
1629 case WSDISPLAYIO_SMODE
:
1631 int new_mode
= *(int*)data
;
1633 if (new_mode
!= sc
->sc_mode
)
1635 sc
->sc_mode
= new_mode
;
1636 if ((new_mode
== WSDISPLAYIO_MODE_EMUL
)
1639 vcons_redraw_screen(ms
);
1646 return EPASSTHROUGH
;
1650 mach64_mmap(void *v
, void *vs
, off_t offset
, int prot
)
1652 struct vcons_data
*vd
= v
;
1653 struct mach64_softc
*sc
= vd
->cookie
;
1659 *'regular' framebuffer mmap()ing
1660 * disabled on sparc64 because some ATI firmware likes to map some PCI
1661 * resources to addresses that would collide with this ( like some Rage
1662 * IIc which uses 0x2000 for the 2nd register block )
1663 * Other 64bit architectures might run into similar problems.
1665 if (offset
<sc
->sc_apersize
) {
1666 pa
= bus_space_mmap(sc
->sc_memt
, sc
->sc_aperbase
, offset
,
1667 prot
, BUS_SPACE_MAP_LINEAR
);
1673 * restrict all other mappings to processes with superuser privileges
1674 * or the kernel itself
1676 if (kauth_authorize_generic(kauth_cred_get(), KAUTH_GENERIC_ISSUSER
,
1678 printf("%s: mmap() rejected.\n", device_xname(&sc
->sc_dev
));
1682 reg
= (pci_conf_read(sc
->sc_pc
, sc
->sc_pcitag
, 0x18) & 0xffffff00);
1683 if (reg
!= sc
->sc_regphys
) {
1685 printf("%s: BAR 0x18 changed! (%x %x)\n",
1686 device_xname(&sc
->sc_dev
), (uint32_t)sc
->sc_regphys
,
1689 sc
->sc_regphys
= reg
;
1692 reg
= (pci_conf_read(sc
->sc_pc
, sc
->sc_pcitag
, 0x10) & 0xffffff00);
1693 if (reg
!= sc
->sc_aperphys
) {
1695 printf("%s: BAR 0x10 changed! (%x %x)\n",
1696 device_xname(&sc
->sc_dev
), (uint32_t)sc
->sc_aperphys
,
1699 sc
->sc_aperphys
= reg
;
1703 /* evil hack to allow mmap()ing other devices as well */
1704 if ((offset
> 0x80000000) && (offset
<= 0xffffffff)) {
1705 pa
= bus_space_mmap(sc
->sc_memt
, offset
, 0, prot
,
1706 BUS_SPACE_MAP_LINEAR
);
1711 if ((offset
>= sc
->sc_aperphys
) &&
1712 (offset
< (sc
->sc_aperphys
+ sc
->sc_apersize
))) {
1713 pa
= bus_space_mmap(sc
->sc_memt
, offset
, 0, prot
,
1714 BUS_SPACE_MAP_LINEAR
);
1718 if ((offset
>= sc
->sc_regphys
) &&
1719 (offset
< (sc
->sc_regphys
+ sc
->sc_regsize
))) {
1720 pa
= bus_space_mmap(sc
->sc_memt
, offset
, 0, prot
,
1721 BUS_SPACE_MAP_LINEAR
);
1728 /* set ri->ri_bits according to fb, ri_xorigin and ri_yorigin */
1730 set_address(struct rasops_info
*ri
, void *fb
)
1733 printf(" %d %d %d\n", ri
->ri_xorigin
, ri
->ri_yorigin
, ri
->ri_stride
);
1735 ri
->ri_bits
= (void *)((char *)fb
+ ri
->ri_stride
* ri
->ri_yorigin
+
1741 mach64_load_font(void *v
, void *cookie
, struct wsdisplay_font
*data
)
1749 machfb_blank(struct mach64_softc
*sc
, int blank
)
1753 #define MACH64_BLANK (CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS | CRTC_VSYNC_DIS)
1758 reg
= regr(sc
, CRTC_GEN_CNTL
);
1759 regw(sc
, CRTC_GEN_CNTL
, reg
& ~(MACH64_BLANK
));
1763 reg
= regr(sc
, CRTC_GEN_CNTL
);
1764 regw(sc
, CRTC_GEN_CNTL
, reg
| (MACH64_BLANK
));
1772 /* framebuffer device support */
1776 machfb_unblank(device_t dev
)
1778 struct mach64_softc
*sc
= device_private(dev
);
1780 machfb_blank(sc
, 0);
1784 machfb_fbattach(struct mach64_softc
*sc
)
1786 struct fbdevice
*fb
= &sc
->sc_fb
;
1788 fb
->fb_device
= &sc
->sc_dev
;
1789 fb
->fb_driver
= &machfb_fbdriver
;
1791 fb
->fb_type
.fb_cmsize
= 256;
1792 fb
->fb_type
.fb_size
= sc
->memsize
;
1794 fb
->fb_type
.fb_type
= FBTYPE_GENERIC_PCI
;
1795 fb
->fb_flags
= sc
->sc_dev
.dv_cfdata
->cf_flags
& FB_USERMASK
;
1796 fb
->fb_type
.fb_depth
= sc
->bits_per_pixel
;
1797 fb
->fb_type
.fb_width
= sc
->virt_x
;
1798 fb
->fb_type
.fb_height
= sc
->virt_y
;
1800 fb
->fb_pixels
= sc
->sc_aperture
;
1801 fb_attach(fb
, sc
->sc_console
);
1805 machfb_fbopen(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
1807 struct mach64_softc
*sc
;
1809 sc
= device_lookup_private(&machfb_cd
, minor(dev
));
1815 printf("machfb_fbopen(%d)\n", minor(dev
));
1821 machfb_fbclose(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
1823 struct mach64_softc
*sc
= device_lookup_private(&machfb_cd
, minor(dev
));
1826 printf("machfb_fbclose()\n");
1828 mach64_init_engine(sc
);
1829 mach64_init_lut(sc
);
1835 machfb_fbioctl(dev_t dev
, u_long cmd
, void *data
, int flags
, struct lwp
*l
)
1837 struct mach64_softc
*sc
= device_lookup_private(&machfb_cd
, minor(dev
));
1840 printf("machfb_fbioctl(%d, %lx)\n", minor(dev
), cmd
);
1844 *(struct fbtype
*)data
= sc
->sc_fb
.fb_type
;
1848 #define fba ((struct fbgattr *)data)
1849 fba
->real_type
= sc
->sc_fb
.fb_type
.fb_type
;
1850 fba
->owner
= 0; /* XXX ??? */
1851 fba
->fbtype
= sc
->sc_fb
.fb_type
;
1852 fba
->sattr
.flags
= 0;
1853 fba
->sattr
.emu_type
= sc
->sc_fb
.fb_type
.fb_type
;
1854 fba
->sattr
.dev_specific
[0] = sc
->sc_nbus
;
1855 fba
->sattr
.dev_specific
[1] = sc
->sc_ndev
;
1856 fba
->sattr
.dev_specific
[2] = sc
->sc_nfunc
;
1857 fba
->sattr
.dev_specific
[3] = -1;
1858 fba
->emu_types
[0] = sc
->sc_fb
.fb_type
.fb_type
;
1859 fba
->emu_types
[1] = -1;
1865 #define p ((struct fbcmap *)data)
1866 return (bt_getcmap(p
, &sc
->sc_cmap
, 256, 1));
1869 /* copy to software map */
1870 error
= bt_putcmap(p
, &sc
->sc_cmap
, 256, 1);
1873 /* now blast them into the chip */
1874 /* XXX should use retrace interrupt */
1875 cg6_loadcmap(sc
, p
->index
, p
->count
);
1880 *(int *)data
= sc
->sc_blanked
;
1884 machfb_blank(sc
, *(int *)data
);
1895 *(struct fbcurpos
*)data
= sc
->sc_cursor
.cc_pos
;
1899 sc
->sc_cursor
.cc_pos
= *(struct fbcurpos
*)data
;
1903 /* max cursor size is 32x32 */
1904 ((struct fbcurpos
*)data
)->x
= 32;
1905 ((struct fbcurpos
*)data
)->y
= 32;
1908 case PCI_IOC_CFGREAD
:
1909 case PCI_IOC_CFGWRITE
:
1913 ret
= pci_devioctl(sc
->sc_pc
, sc
->sc_pcitag
,
1914 cmd
, data
, flags
, l
);
1917 printf("pci_devioctl: %d\n", ret
);
1923 log(LOG_NOTICE
, "machfb_fbioctl(0x%lx) (%s[%d])\n", cmd
,
1924 p
->p_comm
, p
->p_pid
);
1929 printf("machfb_fbioctl done\n");
1935 machfb_fbmmap(dev_t dev
, off_t off
, int prot
)
1937 struct mach64_softc
*sc
= device_lookup_private(&machfb_cd
, minor(dev
));
1940 return mach64_mmap(&sc
->vd
, NULL
, off
, prot
);
1945 #endif /* __sparc__ */