1117N/A/*
1368N/A * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
1117N/A *
1117N/A * Permission is hereby granted, free of charge, to any person obtaining a
1117N/A * copy of this software and associated documentation files (the "Software"),
1117N/A * to deal in the Software without restriction, including without limitation
1117N/A * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1117N/A * and/or sell copies of the Software, and to permit persons to whom the
1117N/A * Software is furnished to do so, subject to the following conditions:
1117N/A *
1117N/A * The above copyright notice and this permission notice (including the next
1117N/A * paragraph) shall be included in all copies or substantial portions of the
1117N/A * Software.
1117N/A *
1117N/A * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1117N/A * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1117N/A * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1117N/A * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1117N/A * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1117N/A * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
1117N/A * DEALINGS IN THE SOFTWARE.
1117N/A */
1117N/A
1117N/A#include "libvtsSUNWefb.h" /* Common VTS library definitions */
1117N/A#include "efb.h"
1117N/A
1117N/A
1117N/Aint
1368N/Aefb_map_mem(
1368N/A register return_packet *const rp,
1368N/A register int const test)
1117N/A{
1368N/A register int const pagesize = getpagesize();
1368N/A
1368N/A if (efb_get_pci_info() != 0) {
1368N/A gfx_vts_set_message(rp, 1, test, "get pci info failed");
1368N/A return (-1);
1368N/A }
1117N/A
1368N/A /*
1368N/A * Map MMIO
1368N/A */
1368N/A efb_info.efb_mmio_size = (efb_info.efb_mmio_size + pagesize - 1) /
1368N/A pagesize * pagesize;
1368N/A
1368N/A if (efb_map_mmio() != 0) {
1368N/A gfx_vts_set_message(rp, 1, test, "map MMIO failed");
1368N/A return (-1);
1117N/A }
1117N/A
1368N/A switch (efb_info.efb_device) {
1368N/A case 20825:
1368N/A case 20830:
1368N/A case 23396:
1368N/A efb_info.efb_fb_size = REGR(RADEON_CONFIG_MEMSIZE);
1368N/A break;
1368N/A default:
1368N/A efb_info.efb_fb_size = REGR(R600_CONFIG_MEMSIZE);
1368N/A break;
1368N/A }
1368N/A efb_info.efb_fb_size = (efb_info.efb_fb_size + (pagesize - 1)) /
1368N/A pagesize * pagesize;
1368N/A
1368N/A /*
1368N/A * Map framebuffer
1368N/A */
1368N/A
1368N/A if (efb_map_fb() != 0) {
1368N/A gfx_vts_set_message(rp, 1, test, "map framebuffer failed");
1368N/A return (-1);
1368N/A }
1368N/A
1368N/A return (0);
1368N/A}
1368N/A
1368N/Aint
1368N/Aefb_get_pci_info(
1368N/A void)
1368N/A{
1368N/A struct gfx_pci_cfg pciconfig;
1368N/A int i;
1368N/A uint_t bar;
1368N/A uint_t bar_hi;
1368N/A offset_t mem_base[6];
1368N/A offset_t io_base[6];
1368N/A int type[6];
1368N/A
1368N/A if (ioctl(efb_info.efb_fd, GFX_IOCTL_GET_PCI_CONFIG,
1368N/A &pciconfig) != 0) {
1368N/A return (-1);
1368N/A }
1368N/A
1368N/A efb_info.efb_vendor = pciconfig.VendorID;
1368N/A efb_info.efb_device = pciconfig.DeviceID;
1117N/A
1117N/A for (i = 0; i < 6; i++) {
1368N/A type[i] = 0;
1368N/A mem_base[i] = 0;
1368N/A io_base[i] = 0;
1368N/A }
1368N/A
1368N/A for (i = 0; i < 6; i++) {
1368N/A bar = pciconfig.bar[i];
1368N/A if (bar != 0) {
1368N/A if (bar & PCI_MAP_IO) {
1368N/A io_base[i] = PCIGETIO(bar);
1368N/A type[i] = bar & PCI_MAP_IO_ATTR_MASK;
1117N/A } else {
1368N/A type[i] = bar & PCI_MAP_MEMORY_ATTR_MASK;
1368N/A mem_base[i] = PCIGETMEMORY(bar);
1368N/A if (PCI_MAP_IS64BITMEM(bar)) {
1368N/A if (i == 5) {
1368N/A mem_base[i] = 0;
1368N/A } else {
1368N/A bar_hi = pciconfig.bar[i+1];
1368N/A mem_base[i] |=
1368N/A ((offset_t)bar_hi << 32);
1368N/A ++i;
1368N/A }
1368N/A }
1117N/A }
1117N/A }
1117N/A }
1117N/A
1368N/A efb_info.efb_fb_addr = mem_base[0] & 0xfff00000;
1368N/A efb_info.efb_fb_size = 0;
1368N/A
1368N/A efb_info.efb_mmio_addr = mem_base[2] & 0xffff0000;
1368N/A efb_info.efb_mmio_size = 1 << EFB_REG_SIZE_LOG2;
1368N/A
1368N/A if (gfx_vts_debug_mask & VTS_DEBUG) {
1368N/A printf("efb_vendor = 0x%04x, efb_device = 0x%04x\n",
1368N/A efb_info.efb_vendor, efb_info.efb_device);
1368N/A printf("efb_fb_addr 0x%llx, efb_fb_size 0x%lx\n",
1368N/A (unsigned long long)efb_info.efb_fb_addr,
1368N/A (unsigned long)efb_info.efb_fb_size);
1368N/A printf("efb_mmio_addr 0x%llx, efb_mmio_size 0x%lx\n",
1368N/A (unsigned long long)efb_info.efb_mmio_addr,
1368N/A (unsigned long)efb_info.efb_mmio_size);
1368N/A }
1368N/A
1368N/A return (0);
1368N/A}
1368N/A
1368N/Aint
1368N/Aefb_map_mmio(
1368N/A void)
1368N/A{
1368N/A register void *ptr;
1368N/A
1368N/A if (efb_info.efb_mmio_ptr == NULL) {
1368N/A ptr = mmap(NULL, efb_info.efb_mmio_size,
1368N/A PROT_READ | PROT_WRITE, MAP_SHARED,
1368N/A efb_info.efb_fd, efb_info.efb_mmio_addr);
1368N/A
1368N/A if (ptr == MAP_FAILED)
1368N/A return (-1);
1368N/A }
1368N/A
1368N/A efb_info.efb_mmio_ptr = (uchar_t *)ptr;
1368N/A
1368N/A if (gfx_vts_debug_mask & VTS_DEBUG)
1368N/A printf("efb_mmio_ptr = 0x%llx\n",
1368N/A (unsigned long long)efb_info.efb_mmio_ptr);
1368N/A
1368N/A return (0);
1117N/A}
1117N/A
1117N/Aint
1368N/Aefb_map_fb(
1368N/A void)
1117N/A{
1368N/A register void *ptr;
1368N/A
1368N/A if (efb_info.efb_fb_ptr == NULL) {
1368N/A ptr = mmap(NULL, efb_info.efb_fb_size,
1368N/A PROT_READ | PROT_WRITE, MAP_SHARED,
1368N/A efb_info.efb_fd, efb_info.efb_fb_addr);
1368N/A
1368N/A if (ptr == MAP_FAILED)
1368N/A return (-1);
1368N/A
1368N/A efb_info.efb_fb_ptr = (uchar_t *)ptr;
1368N/A }
1368N/A
1368N/A if (gfx_vts_debug_mask & VTS_DEBUG)
1368N/A printf("efb_fb_ptr = 0x%llx\n",
1368N/A (unsigned long long)efb_info.efb_fb_ptr);
1368N/A
1368N/A return (0);
1368N/A}
1368N/A
1117N/A
1368N/Aint
1368N/Aefb_init_info(
1368N/A register return_packet *const rp,
1368N/A register int const test)
1368N/A{
1368N/A register uint32_t crtc_h_total_disp;
1368N/A register uint32_t crtc_v_total_disp;
1368N/A register uint32_t crtc_gen_cntl;
1368N/A register uint32_t crtc_pitch;
1368N/A register uint_t width;
1368N/A register uint_t height;
1368N/A register uint_t depth;
1368N/A register uint_t pixelsize;
1368N/A register uint_t pitch;
1368N/A
1368N/A /* Get the gen cntl */
1368N/A
1368N/A crtc_gen_cntl = REGR(CRTC_GEN_CNTL);
1368N/A
1368N/A /* Get the horizontal total display end */
1368N/A
1368N/A crtc_h_total_disp = REGR(CRTC_H_TOTAL_DISP);
1368N/A
1368N/A /* Get the vertical total display end */
1117N/A
1368N/A crtc_v_total_disp = REGR(CRTC_V_TOTAL_DISP);
1368N/A
1368N/A /* Get the pitch */
1368N/A
1368N/A crtc_pitch = REGR(CRTC_PITCH);
1368N/A
1368N/A /* Compute the width. */
1368N/A
1368N/A width = (((crtc_h_total_disp & CRTC_H_TOTAL_DISP__CRTC_H_DISP_MASK) >>
1368N/A CRTC_H_TOTAL_DISP__CRTC_H_DISP__SHIFT) + 1) * 8;
1368N/A
1368N/A /* Compute the height. */
1368N/A
1368N/A height = ((crtc_v_total_disp & CRTC_V_TOTAL_DISP__CRTC_V_DISP_MASK) >>
1368N/A CRTC_V_TOTAL_DISP__CRTC_V_DISP__SHIFT) + 1;
1368N/A
1368N/A if (crtc_gen_cntl & CRTC_GEN_CNTL__CRTC_INTERLACE_EN_MASK)
1368N/A height *= 2;
1368N/A
1368N/A /* Compute the pitch */
1368N/A
1368N/A pitch = crtc_pitch & CRTC_PITCH__CRTC_PITCH_MASK;
1368N/A
1368N/A /* Compute the depth. */
1368N/A
1368N/A switch ((crtc_gen_cntl & CRTC_GEN_CNTL__CRTC_PIX_WIDTH_MASK) >>
1368N/A CRTC_GEN_CNTL__CRTC_PIX_WIDTH__SHIFT) {
1117N/A
1368N/A case 2:
1368N/A depth = 8;
1368N/A pixelsize = 1;
1368N/A pitch *= 8;
1368N/A break;
1368N/A
1368N/A case 3:
1368N/A depth = 15;
1368N/A pixelsize = 2;
1368N/A pitch *= 16;
1368N/A break;
1368N/A
1368N/A case 4:
1368N/A depth = 16;
1368N/A pixelsize = 2;
1368N/A pitch *= 16;
1368N/A break;
1117N/A
1368N/A case 5:
1368N/A depth = 24;
1368N/A pixelsize = 3;
1368N/A pitch *= 24;
1368N/A break;
1368N/A
1368N/A case 6:
1368N/A depth = 32;
1368N/A pixelsize = 4;
1368N/A pitch *= 32;
1368N/A break;
1368N/A
1368N/A default:
1368N/A gfx_vts_set_message(rp, 1, test, "unsupported depth");
1368N/A return (-1);
1368N/A }
1368N/A
1368N/A efb_info.efb_width = width;
1368N/A efb_info.efb_height = height;
1368N/A efb_info.efb_depth = depth;
1368N/A efb_info.efb_pixelsize = pixelsize;
1368N/A efb_info.efb_linesize = pitch;
1117N/A
1368N/A if (gfx_vts_debug_mask & VTS_DEBUG) {
1368N/A printf("width=%d height=%d depth=%d pitch=%d\n",
1368N/A efb_info.efb_width, efb_info.efb_height,
1368N/A efb_info.efb_depth, efb_info.efb_linesize);
1368N/A }
1368N/A return (0);
1368N/A}
1368N/A
1368N/Aint
1368N/Aefb_unmap_mem(
1368N/A register return_packet *const rp,
1368N/A register int const test)
1368N/A{
1368N/A if (efb_unmap_fb() != 0) {
1368N/A gfx_vts_set_message(rp, 1, test, "unmap framebuffer failed");
1368N/A return (-1);
1368N/A }
1117N/A
1368N/A if (efb_unmap_mmio() != 0) {
1368N/A gfx_vts_set_message(rp, 1, test, "unmap MMIO failed");
1368N/A return (-1);
1368N/A }
1368N/A
1368N/A return (0);
1368N/A}
1368N/A
1368N/A
1368N/Aint
1368N/Aefb_unmap_fb(
1368N/A void)
1368N/A{
1368N/A register int status;
1368N/A
1368N/A if (efb_info.efb_fb_ptr == NULL)
1368N/A return (0);
1368N/A
1368N/A status = munmap((char *)efb_info.efb_fb_ptr, efb_info.efb_fb_size);
1368N/A efb_info.efb_fb_ptr = NULL;
1368N/A
1368N/A return (status);
1117N/A}
1117N/A
1117N/A
1117N/Aint
1368N/Aefb_unmap_mmio(
1368N/A void)
1117N/A{
1368N/A register int status;
1117N/A
1368N/A if (efb_info.efb_mmio_ptr == NULL)
1368N/A return (0);
1117N/A
1368N/A status = munmap((char *)efb_info.efb_mmio_ptr,
1368N/A efb_info.efb_mmio_size);
1368N/A efb_info.efb_mmio_ptr = NULL;
1117N/A
1368N/A return (status);
1117N/A}
1117N/A
1117N/Aint
1368N/Aefb_init_graphics(void)
1117N/A{
1368N/A uint_t pitch_offset;
1368N/A uint_t pitch;
1368N/A uint_t offset;
1368N/A uint_t gmc_bpp;
1368N/A uint_t v;
1368N/A
1368N/A switch (efb_info.efb_depth) {
1368N/A case 8:
1368N/A gmc_bpp = GMC_DST_8BPP;
1368N/A break;
1368N/A case 15:
1368N/A gmc_bpp = GMC_DST_15BPP;
1368N/A break;
1368N/A
1368N/A case 16:
1368N/A gmc_bpp = GMC_DST_16BPP;
1368N/A break;
1368N/A
1368N/A case 24:
1368N/A gmc_bpp = GMC_DST_24BPP;
1368N/A break;
1368N/A
1368N/A case 32:
1368N/A gmc_bpp = GMC_DST_32BPP;
1368N/A break;
1368N/A }
1368N/A
1368N/A offset = REGR(CRTC_OFFSET) & 0x7ffffff;
1368N/A pitch = REGR(CRTC_PITCH) & 0x7ff;
1368N/A
1368N/A pitch = pitch * 8; /* was in groups of 8 pixels */
1368N/A
1368N/A pitch_offset =
1368N/A ((pitch * efb_info.efb_pixelsize / 64) << 22) |
1368N/A (offset / 1024);
1368N/A
1368N/A /*
1368N/A * Initialize GUI engine
1368N/A */
1368N/A if (!efb_wait_idle())
1368N/A return (0);
1117N/A
1368N/A if (!efb_wait_fifo(5))
1368N/A return (0);
1368N/A
1368N/A REGW(DEFAULT_PITCH_OFFSET, pitch_offset);
1368N/A REGW(RADEON_DST_PITCH_OFFSET, pitch_offset);
1368N/A REGW(RADEON_SRC_PITCH_OFFSET, pitch_offset);
1368N/A
1368N/A REGW(DEFAULT_SC_BOTTOM_RIGHT,
1368N/A (efb_info.efb_height << 16) | (efb_info.efb_width));
1368N/A
1368N/A v = (GMC_SRC_PITCH_OFFSET_DEFAULT |
1368N/A GMC_DST_PITCH_OFFSET_LEAVE |
1368N/A GMC_SRC_CLIP_DEFAULT |
1368N/A GMC_DST_CLIP_DEFAULT |
1368N/A GMC_BRUSH_SOLIDCOLOR |
1368N/A gmc_bpp |
1368N/A GMC_SRC_DSTCOLOR |
1368N/A RADEON_ROP3_P |
1368N/A GMC_WRITE_MASK_LEAVE);
1368N/A
1368N/A REGW(RADEON_DP_GUI_MASTER_CNTL, v);
1368N/A
1368N/A#ifdef DEBUG
1368N/A printf("v=0x%x\n", v);
1368N/A#endif
1368N/A return (1);
1368N/A}
1368N/A
1368N/A
1368N/Avoid
1368N/Aefb_save_palet(
1368N/A void)
1368N/A{
1368N/A register uint_t coloron;
1368N/A register uint_t const save_palette_index =
1368N/A REGR(RADEON_PALETTE_INDEX);
1368N/A
1368N/A REGW(RADEON_PALETTE_INDEX, 0);
1368N/A
1368N/A for (coloron = 0; coloron < 256; coloron++)
1368N/A efb_info.efb_palet[coloron] = REGR(RADEON_PALETTE_30_DATA);
1368N/A
1368N/A REGW(RADEON_PALETTE_INDEX, save_palette_index);
1368N/A}
1117N/A
1117N/A
1368N/Aint
1368N/Aefb_set_palet(
1368N/A void)
1368N/A{
1368N/A register uint_t coloron;
1368N/A register uint_t save_palette_index;
1368N/A uint_t new_red;
1368N/A uint_t new_green;
1368N/A uint_t new_blue;
1368N/A uint_t new_palet[256];
1117N/A
1368N/A switch (efb_info.efb_depth) {
1368N/A case 8: /* 3, 3, 2 */
1368N/A for (coloron = 0; coloron < 256; coloron++) {
1368N/A new_red = ((coloron >> 5) & 0x7) * 1023 / 7;
1368N/A new_green = ((coloron >> 2) & 0x7) * 1023 / 7;
1368N/A new_blue = (coloron & 0x3) * 1023 / 3;
1368N/A new_palet[coloron] =
1368N/A (new_red <<
1368N/A PALETTE_30_DATA__PALETTE_DATA_R__SHIFT) |
1368N/A (new_green <<
1368N/A PALETTE_30_DATA__PALETTE_DATA_G__SHIFT) |
1368N/A (new_blue <<
1368N/A PALETTE_30_DATA__PALETTE_DATA_B__SHIFT);
1368N/A }
1368N/A break;
1117N/A
1368N/A case 15: /* 5, 5, 5 */
1368N/A for (coloron = 0; coloron < 256; coloron++) {
1368N/A new_red = (coloron / 8) * 1023 / 31;
1368N/A new_green = (coloron / 8) * 1023 / 31;
1368N/A new_blue = (coloron / 8) * 1023 / 31;
1368N/A new_palet[coloron] =
1368N/A (new_red <<
1368N/A PALETTE_30_DATA__PALETTE_DATA_R__SHIFT) |
1368N/A (new_green <<
1368N/A PALETTE_30_DATA__PALETTE_DATA_G__SHIFT) |
1368N/A (new_blue <<
1368N/A PALETTE_30_DATA__PALETTE_DATA_B__SHIFT);
1368N/A }
1368N/A break;
1117N/A
1368N/A case 16: /* 5, 6, 5 */
1368N/A for (coloron = 0; coloron < 256; coloron++) {
1368N/A new_red = (coloron / 8) * 1023 / 31;
1368N/A new_green = (coloron / 4) * 1023 / 63;
1368N/A new_blue = (coloron / 8) * 1023 / 31;
1368N/A new_palet[coloron] =
1368N/A (new_red <<
1368N/A PALETTE_30_DATA__PALETTE_DATA_R__SHIFT) |
1368N/A (new_green <<
1368N/A PALETTE_30_DATA__PALETTE_DATA_G__SHIFT) |
1368N/A (new_blue <<
1368N/A PALETTE_30_DATA__PALETTE_DATA_B__SHIFT);
1368N/A }
1117N/A break;
1368N/A
1368N/A default: /* 8, 8, 8 */
1368N/A for (coloron = 0; coloron < 256; coloron++) {
1368N/A new_red = (coloron * 1023) / 255;
1368N/A new_green = (coloron * 1023) / 255;
1368N/A new_blue = (coloron * 1023) / 255;
1368N/A new_palet[coloron] =
1368N/A (new_red <<
1368N/A PALETTE_30_DATA__PALETTE_DATA_R__SHIFT) |
1368N/A (new_green <<
1368N/A PALETTE_30_DATA__PALETTE_DATA_G__SHIFT) |
1368N/A (new_blue <<
1368N/A PALETTE_30_DATA__PALETTE_DATA_B__SHIFT);
1368N/A }
1117N/A break;
1117N/A }
1117N/A
1368N/A /* Don't set the palet if it matches what we will set. */
1117N/A
1368N/A for (coloron = 0; coloron < 256; coloron++) {
1368N/A if ((efb_info.efb_palet[coloron] &
1368N/A (PALETTE_30_DATA__PALETTE_DATA_R_MASK |
1368N/A PALETTE_30_DATA__PALETTE_DATA_G_MASK |
1368N/A PALETTE_30_DATA__PALETTE_DATA_B_MASK)) !=
1368N/A (new_palet[coloron] &
1368N/A (PALETTE_30_DATA__PALETTE_DATA_R_MASK |
1368N/A PALETTE_30_DATA__PALETTE_DATA_G_MASK |
1368N/A PALETTE_30_DATA__PALETTE_DATA_B_MASK)))
1368N/A break;
1368N/A }
1117N/A
1368N/A if (coloron == 256)
1368N/A return (0);
1368N/A
1368N/A efb_info.efb_palet_changed = 1;
1368N/A save_palette_index = REGR(RADEON_PALETTE_INDEX);
1117N/A
1368N/A REGW(RADEON_PALETTE_INDEX, 0);
1117N/A
1368N/A for (coloron = 0; coloron < 256; coloron++)
1368N/A REGW(RADEON_PALETTE_30_DATA, new_palet[coloron]);
1368N/A
1368N/A REGW(RADEON_PALETTE_INDEX, save_palette_index);
1368N/A return (1);
1117N/A}
1117N/A
1117N/Aint
1368N/Aefb_restore_palet(
1368N/A void)
1117N/A{
1368N/A register uint_t coloron;
1368N/A register uint_t save_palette_index;
1368N/A
1368N/A if (!efb_info.efb_palet_changed)
1368N/A return (0);
1368N/A
1368N/A save_palette_index = REGR(RADEON_PALETTE_INDEX);
1368N/A
1368N/A REGW(RADEON_PALETTE_INDEX, 0);
1368N/A
1368N/A for (coloron = 0; coloron < 256; coloron++)
1368N/A REGW(RADEON_PALETTE_30_DATA, efb_info.efb_palet[coloron]);
1368N/A
1368N/A REGW(RADEON_PALETTE_INDEX, save_palette_index);
1368N/A
1368N/A efb_info.efb_palet_changed = 0;
1368N/A return (1);
1368N/A}
1368N/A
1117N/A
1368N/Auint_t
1368N/Aefb_color(
1368N/A register uint_t const red,
1368N/A register uint_t const green,
1368N/A register uint_t const blue)
1368N/A{
1368N/A register uint_t value;
1368N/A
1368N/A switch (efb_info.efb_depth) {
1368N/A case 8: /* 3, 3, 2 */
1368N/A value = ((red >> 5) & 0x7) << 5;
1368N/A value |= ((green >> 5) & 0x7) << 2;
1368N/A value |= (blue >> 6) & 0x3;
1368N/A break;
1117N/A
1368N/A case 15: /* 5, 5, 5 */
1368N/A value = ((red >> 3) & 0x1f) << 10;
1368N/A value |= ((green >> 3) & 0x1f) << 5;
1368N/A value |= (blue >> 3) & 0x1f;
1368N/A break;
1117N/A
1368N/A case 16: /* 5, 6, 5 */
1368N/A value = ((red >> 3) & 0x1f) << 11;
1368N/A value |= ((green >> 2) & 0x3f) << 5;
1368N/A value |= (blue >> 3) & 0x1f;
1368N/A break;
1368N/A
1368N/A default: /* 8, 8, 8 */
1368N/A value = (red & 0xff) << 16;
1368N/A value |= (green & 0xff) << 8;
1368N/A value |= blue & 0xff;
1368N/A break;
1368N/A }
1368N/A
1368N/A return (value);
1117N/A}
1117N/A
1117N/A
1368N/Aint
1368N/Aefb_fill_solid_rect(
1368N/A register uint_t const x1,
1368N/A register uint_t const y1,
1368N/A register uint_t const x2,
1368N/A register uint_t const y2,
1368N/A register uint_t const fg)
1117N/A{
1368N/A register int width;
1368N/A register int height;
1368N/A
1368N/A width = x2 - x1;
1368N/A height = y2 - y1;
1368N/A
1368N/A if ((width <= 0) || (height <= 0)) {
1368N/A#ifdef DEBUG
1368N/A printf("x1=%d x2=%d y1=%d y2=%d\n", x1, x2, y1, y2);
1368N/A#endif
1368N/A return (0);
1368N/A }
1368N/A
1368N/A if (!efb_wait_fifo(5))
1368N/A return (0);
1368N/A
1368N/A REGW(RADEON_DP_WRITE_MASK, 0xffffffff);
1368N/A REGW(RADEON_DP_CNTL,
1368N/A (RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM));
1368N/A
1368N/A REGW(RADEON_DP_BRUSH_FRGD_CLR, fg);
1368N/A REGW(DST_Y_X, (x1 << DST_Y_X__DST_X__SHIFT) |
1368N/A (y1 << DST_Y_X__DST_Y__SHIFT));
1368N/A REGW(DST_WIDTH_HEIGHT,
1368N/A (height << DST_WIDTH_HEIGHT__DST_HEIGHT__SHIFT) |
1368N/A (width << DST_WIDTH_HEIGHT__DST_WIDTH__SHIFT));
1368N/A
1368N/A return (1);
1117N/A}
1117N/A
1368N/Aint
1368N/Aefb_draw_solid_line(
1368N/A register uint_t const x1,
1368N/A register uint_t const y1,
1368N/A register uint_t const x2,
1368N/A register uint_t const y2,
1368N/A register uint_t const fg)
1117N/A{
1368N/A if (!efb_wait_fifo(5))
1368N/A return (0);
1368N/A
1368N/A REGW(RADEON_DP_WRITE_MASK, 0xffffffff);
1368N/A REGW(RADEON_DP_CNTL,
1368N/A (RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM));
1117N/A
1368N/A REGW(RADEON_DP_BRUSH_FRGD_CLR, fg);
1368N/A REGW(DST_LINE_START,
1368N/A (x1 << DST_LINE_START__DST_START_X__SHIFT) |
1368N/A (y1 << DST_LINE_START__DST_START_Y__SHIFT));
1368N/A REGW(DST_LINE_END,
1368N/A (x2 << DST_LINE_END__DST_END_X__SHIFT) |
1368N/A (y2 << DST_LINE_END__DST_END_Y__SHIFT));
1368N/A
1368N/A return (1);
1368N/A} /* line() */
1117N/A
1368N/Aint
1368N/Aefb_flush_pixel_cache(
1368N/A void)
1368N/A{
1368N/A register int i;
1368N/A
1368N/A /* initiate flush */
1368N/A REGW(RADEON_RB2D_DSTCACHE_CTLSTAT,
1368N/A REGR(RADEON_RB2D_DSTCACHE_CTLSTAT) | 0xf);
1368N/A
1368N/A /* check for completion but limit looping to 16384 reads */
1368N/A for (i = 16384; i > 0; i--) {
1368N/A if ((REGR(RADEON_RB2D_DSTCACHE_CTLSTAT) &
1368N/A (uint_t)RADEON_RB2D_DC_BUSY) != (uint_t)RADEON_RB2D_DC_BUSY)
1368N/A break;
1368N/A }
1368N/A return ((REGR(RADEON_RB2D_DSTCACHE_CTLSTAT) &
1368N/A (uint_t)RADEON_RB2D_DC_BUSY) != (uint_t)RADEON_RB2D_DC_BUSY);
1117N/A}
1117N/A
1368N/Avoid
1368N/Aefb_reset_engine(
1368N/A void)
1117N/A{
1368N/A register uint_t save_genresetcntl;
1368N/A register uint_t save_clockcntlindex;
1368N/A static ulong_t term_count;
1117N/A
1368N/A efb_flush_pixel_cache();
1117N/A
1117N/A save_clockcntlindex = REGR(RADEON_CLOCK_CNTL_INDEX);
1117N/A
1368N/A /* save GEN_RESET_CNTL register */
1117N/A save_genresetcntl = REGR(RADEON_DISP_MISC_CNTL);
1117N/A
1368N/A /* reset by setting bit, add read delay, then clear bit, */
1368N/A /* add read delay */
1117N/A REGW(RADEON_DISP_MISC_CNTL, save_genresetcntl |
1368N/A RADEON_DISP_MISC_CNTL__SOFT_RESET_GRPH_PP);
1117N/A REGR(RADEON_DISP_MISC_CNTL);
1117N/A REGW(RADEON_DISP_MISC_CNTL, save_genresetcntl &
1368N/A ~(RADEON_DISP_MISC_CNTL__SOFT_RESET_GRPH_PP));
1117N/A REGR(RADEON_DISP_MISC_CNTL);
1117N/A
1368N/A /* restore the two registers we changed */
1117N/A REGW(RADEON_CLOCK_CNTL_INDEX, save_clockcntlindex);
1117N/A REGW(RADEON_DISP_MISC_CNTL, save_genresetcntl);
1117N/A
1368N/A term_count++; /* for monitoring engine hangs */
1117N/A}
1117N/A
1368N/Aint
1368N/Aefb_wait_fifo(
1368N/A register int const c)
1117N/A{
1368N/A register int limit;
1368N/A register hrtime_t timeout;
1117N/A
1368N/A /* First a short loop, just in case fifo clears out quickly */
1368N/A for (limit = 100; limit >= 0; limit--) {
1368N/A if ((REGR(RBBM_STATUS) &
1368N/A RBBM_STATUS__CMDFIFO_AVAIL_MASK) >= c)
1368N/A break;
1368N/A }
1117N/A
1368N/A if ((REGR(RBBM_STATUS) & RBBM_STATUS__CMDFIFO_AVAIL_MASK) < c) {
1368N/A timeout = gethrtime() + 3 * (hrtime_t)1000000000;
1368N/A while (gethrtime() < timeout) {
1368N/A if ((REGR(RBBM_STATUS) &
1368N/A RBBM_STATUS__CMDFIFO_AVAIL_MASK) >= c)
1368N/A break;
1368N/A yield();
1368N/A }
1368N/A if ((REGR(RBBM_STATUS) &
1368N/A RBBM_STATUS__CMDFIFO_AVAIL_MASK) < c)
1368N/A efb_reset_engine();
1117N/A }
1368N/A return ((REGR(RBBM_STATUS) &
1368N/A RBBM_STATUS__CMDFIFO_AVAIL_MASK) >= c);
1117N/A}
1117N/A
1368N/Aint
1368N/Aefb_wait_idle(
1368N/A void)
1368N/A{
1368N/A register int limit;
1368N/A register hrtime_t timeout;
1117N/A
1368N/A efb_wait_fifo(64);
1368N/A
1368N/A for (limit = 10000; limit > 0; limit--) {
1368N/A if (!(REGR(RBBM_STATUS) & GUI_ACTIVE))
1368N/A break;
1368N/A }
1368N/A
1368N/A if (REGR(RBBM_STATUS) & GUI_ACTIVE) {
1368N/A timeout = gethrtime() + 3 * (hrtime_t)1000000000;
1368N/A while (gethrtime() < timeout) {
1368N/A if (!(REGR(RBBM_STATUS) & GUI_ACTIVE))
1368N/A break;
1368N/A yield();
1368N/A }
1368N/A
1368N/A if ((REGR(RBBM_STATUS) & GUI_ACTIVE) != 0)
1368N/A efb_reset_engine();
1368N/A }
1368N/A return ((REGR(RBBM_STATUS) & GUI_ACTIVE) == 0);
1368N/A}