1247N/A/*
1247N/A * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
1247N/A *
1247N/A * Permission is hereby granted, free of charge, to any person obtaining a
1247N/A * copy of this software and associated documentation files (the "Software"),
1247N/A * to deal in the Software without restriction, including without limitation
1247N/A * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1247N/A * and/or sell copies of the Software, and to permit persons to whom the
1247N/A * Software is furnished to do so, subject to the following conditions:
1247N/A *
1247N/A * The above copyright notice and this permission notice (including the next
1247N/A * paragraph) shall be included in all copies or substantial portions of the
1247N/A * Software.
1247N/A *
1247N/A * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1247N/A * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1247N/A * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1247N/A * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1247N/A * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1247N/A * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
1247N/A * DEALINGS IN THE SOFTWARE.
1247N/A */
1247N/A
1247N/A#include "libvtsSUNWmga.h" /* Common VTS library definitions */
1247N/A
1247N/Atypedef union MemType {
1247N/A uint64_t val[8];
1247N/A uint32_t word[16];
1247N/A uint16_t halfwd[32];
1247N/A uint8_t byte[64];
1247N/A} MemType;
1247N/A
1247N/Astatic const int access_mode[] = {
1247N/A 1, 2, 4, 8, 0
1247N/A};
1247N/A
1247N/Astatic MemType data[32 * 8];
1247N/Astatic MemType cdata[32 * 8];
1247N/Astatic MemType rdval[4];
1247N/A
1247N/A/*
1247N/A * mga_test_memory()
1247N/A *
1247N/A * This test will open the device and read and write to all memory
1247N/A * addresses.
1247N/A */
1247N/A
1247N/Areturn_packet *
1247N/Amga_test_memory(
1247N/A register int const fd)
1247N/A{
1247N/A static return_packet rp;
1247N/A
1247N/A memset(&rp, 0, sizeof (return_packet));
1247N/A
1247N/A if (gfx_vts_debug_mask & GRAPHICS_VTS_MEM_OFF) {
1247N/A return (&rp);
1247N/A }
1247N/A
1247N/A TraceMessage(VTS_DEBUG, "mga_test_memory",
1247N/A "mga_test_memory running\n");
1247N/A
1247N/A mga_block_signals();
1247N/A
1247N/A mga_lock_display();
1247N/A
1247N/A memory_test(&rp, fd);
1247N/A
1247N/A TraceMessage(VTS_DEBUG, "mga_test_memory",
1247N/A "mga_test_memory completed\n");
1247N/A
1247N/A mga_unlock_display();
1247N/A
1247N/A mga_restore_signals();
1247N/A
1247N/A return (&rp);
1247N/A}
1247N/A
1247N/A
1247N/Aint
1247N/Amemory_test(
1247N/A register return_packet *const rp,
1247N/A register int const fd)
1247N/A{
1247N/A register size_t i;
1247N/A register int signo;
1247N/A struct sigaction oldhup;
1247N/A struct sigaction oldint;
1247N/A struct sigaction oldalrm;
1247N/A struct sigaction oldterm;
1247N/A struct sigaction newsigact;
1247N/A sigset_t oldprocmask;
1247N/A
1247N/A memset(&mga_info, 0, sizeof (mga_info));
1247N/A mga_info.mga_fd = fd;
1247N/A
1247N/A if (mga_map_mem(rp, GRAPHICS_ERR_MEMORY_MSG) != 0) {
1247N/A close(fd);
1247N/A return (-1);
1247N/A }
1247N/A
1247N/A if (mga_init_info(rp, GRAPHICS_ERR_MEMORY_MSG) != 0) {
1247N/A mga_unmap_mem(NULL, GRAPHICS_ERR_MEMORY_MSG);
1247N/A close(fd);
1247N/A return (-1);
1247N/A }
1247N/A
1247N/A mga_save_palet();
1247N/A mga_set_palet();
1247N/A
1247N/A /*
1247N/A * Allow a SIGHUP, SIGINT, SIGALRM, or SIGTERM to interrupt our
1247N/A * memory_test. These signals should already be masked from a
1247N/A * call to mga_block_signals.
1247N/A */
1247N/A
1247N/A /* Save the current signals. */
1247N/A
1247N/A sigaction(SIGHUP, NULL, &oldhup);
1247N/A sigaction(SIGINT, NULL, &oldint);
1247N/A sigaction(SIGALRM, NULL, &oldalrm);
1247N/A sigaction(SIGTERM, NULL, &oldterm);
1247N/A
1247N/A /* Setup up new signal action. */
1247N/A
1247N/A newsigact.sa_handler = mga_signal_routine;
1247N/A sigemptyset(&newsigact.sa_mask);
1247N/A newsigact.sa_flags = 0;
1247N/A
1247N/A signo = sigsetjmp(mga_xw.xw_sigjmpbuf, 1);
1247N/A if (!signo) {
1247N/A /* First time goes here. */
1247N/A
1247N/A /* Set signal routines. */
1247N/A
1247N/A if (oldhup.sa_handler != SIG_IGN)
1247N/A sigaction(SIGHUP, &newsigact, NULL);
1247N/A if (oldint.sa_handler != SIG_IGN)
1247N/A sigaction(SIGINT, &newsigact, NULL);
1247N/A if (oldalrm.sa_handler != SIG_IGN)
1247N/A sigaction(SIGALRM, &newsigact, NULL);
1247N/A if (oldterm.sa_handler != SIG_IGN)
1247N/A sigaction(SIGTERM, &newsigact, NULL);
1247N/A
1247N/A /* Unmask SIGHUP, SIGINT, SIGALRM, SIGTERM. */
1247N/A
1247N/A sigprocmask(SIG_SETMASK, &mga_xw.xw_procmask, &oldprocmask);
1247N/A
1247N/A for (i = 0; access_mode[i] != 0; i++) {
1247N/A check_plane(mga_info.mga_depth, access_mode[i],
1247N/A mga_info.mga_linesize / mga_info.mga_pixelsize,
1247N/A mga_info.mga_height,
1247N/A mga_info.mga_width, mga_info.mga_pixelsize,
1247N/A mga_info.mga_fb_ptr);
1247N/A }
1247N/A
1247N/A /* Mask SIGHUP, SIGINT, SIGALRM, SIGTERM. */
1247N/A
1247N/A sigprocmask(SIG_SETMASK, &oldprocmask, NULL);
1247N/A
1247N/A /* Restore the signals. */
1247N/A
1247N/A if (oldhup.sa_handler != SIG_IGN)
1247N/A sigaction(SIGHUP, &oldhup, NULL);
1247N/A if (oldint.sa_handler != SIG_IGN)
1247N/A sigaction(SIGINT, &oldint, NULL);
1247N/A if (oldalrm.sa_handler != SIG_IGN)
1247N/A sigaction(SIGALRM, &oldalrm, NULL);
1247N/A if (oldterm.sa_handler != SIG_IGN)
1247N/A sigaction(SIGTERM, &oldterm, NULL);
1247N/A }
1247N/A
1247N/A else {
1247N/A /* We come here from the siglongjmp in mga_signal_routine. */
1247N/A
1247N/A /* Mask SIGHUP, SIGINT, SIGALRM, SIGTERM. */
1247N/A
1247N/A sigprocmask(SIG_SETMASK, &oldprocmask, NULL);
1247N/A
1247N/A /* Restore the signals. */
1247N/A
1247N/A if (oldhup.sa_handler != SIG_IGN)
1247N/A sigaction(SIGHUP, &oldhup, NULL);
1247N/A if (oldint.sa_handler != SIG_IGN)
1247N/A sigaction(SIGINT, &oldint, NULL);
1247N/A if (oldalrm.sa_handler != SIG_IGN)
1247N/A sigaction(SIGALRM, &oldalrm, NULL);
1247N/A if (oldterm.sa_handler != SIG_IGN)
1247N/A sigaction(SIGTERM, &oldterm, NULL);
1247N/A
1247N/A /* Cause us to get the signal, when we unmask the signals. */
1247N/A
1247N/A kill(getpid(), signo);
1247N/A }
1247N/A
1247N/A mga_restore_palet();
1247N/A
1247N/A if (mga_unmap_mem(rp, GRAPHICS_ERR_MEMORY_MSG) != 0) {
1247N/A close(fd);
1247N/A return (-1);
1247N/A }
1247N/A
1247N/A
1247N/A if (close(fd) != 0) {
1247N/A gfx_vts_set_message(rp, 1, GRAPHICS_ERR_MEMORY_MSG,
1247N/A "error closing device\n");
1247N/A return (-1);
1247N/A }
1247N/A
1247N/A return (0);
1247N/A}
1247N/A
1247N/A
1247N/Avoid
1247N/Acheck_plane(
1247N/A register int const num_planes,
1247N/A register int const access_mode,
1247N/A register int const fb_pitch,
1247N/A register int const fb_height,
1247N/A register int const fb_width,
1247N/A register int const bytepp,
1247N/A register caddr_t const base)
1247N/A{
1247N/A register int x;
1247N/A register int y;
1247N/A register int complement;
1247N/A
1247N/A /* Set up raster for this plane group */
1247N/A
1247N/A init_data(num_planes);
1247N/A
1247N/A /* Cover each 64x64 chunk of screen space */
1247N/A
1247N/A y = 0;
1247N/A while (y < fb_height) {
1247N/A x = 0;
1247N/A while (x < fb_width) {
1247N/A if (x + 63 > fb_width) x = fb_width - 64;
1247N/A if (y + 63 > fb_height) y = fb_height - 64;
1247N/A
1247N/A /* Do each chunk twice - once normal, once complement */
1247N/A
1247N/A for (complement = B_FALSE;
1247N/A complement <= B_TRUE;
1247N/A complement++) {
1247N/A write_read(x, y,
1247N/A (boolean_t)complement,
1247N/A access_mode,
1247N/A B_TRUE,
1247N/A fb_pitch,
1247N/A bytepp,
1247N/A base) ||
1247N/A write_read(x, y,
1247N/A (boolean_t)complement,
1247N/A access_mode,
1247N/A B_FALSE,
1247N/A fb_pitch,
1247N/A bytepp,
1247N/A base);
1247N/A }
1247N/A
1247N/A /* Move over one 64x64 chunk */
1247N/A
1247N/A x += 64;
1247N/A }
1247N/A
1247N/A /* Move down one 64x64 chunk */
1247N/A
1247N/A y += 64;
1247N/A }
1247N/A}
1247N/A
1247N/A
1247N/Avoid
1247N/Ainit_data(
1247N/A register int const num_planes)
1247N/A{
1247N/A register int i;
1247N/A register int j;
1247N/A
1247N/A /* Get memory to store data */
1247N/A
1247N/A /* Write data to memory */
1247N/A
1247N/A for (i = 0; i < num_planes * 8; i++) {
1247N/A for (j = 0; j < 8; j++) {
1247N/A
1247N/A /* Figure out the value to write */
1247N/A
1247N/A data[i].val[j] = ((unsigned long long)
1247N/A test_data() << 32) | test_data();
1247N/A cdata[i].val[j] = ~data[i].val[j];
1247N/A }
1247N/A }
1247N/A}
1247N/A
1247N/A
1247N/Au_int
1247N/Atest_data(
1247N/A void)
1247N/A{
1247N/A register u_int ret;
1247N/A
1247N/A ret = (u_int)mrand48();
1247N/A return (ret);
1247N/A}
1247N/A
1247N/A
1247N/Aboolean_t
1247N/Awrite_read(
1247N/A register int const xoff,
1247N/A register int const yoff,
1247N/A register boolean_t const complement,
1247N/A register int const access_mode,
1247N/A register boolean_t const pass,
1247N/A register int const fb_pitch,
1247N/A register int const bytepp,
1247N/A register caddr_t const base)
1247N/A{
1247N/A register MemType *const dp = complement ? cdata : data;
1247N/A register int const pitch = fb_pitch;
1247N/A register int x;
1247N/A register int y;
1247N/A register int i;
1247N/A register caddr_t mem_addr;
1247N/A register int subscr = 0;
1247N/A
1247N/A /* Write Data to Screen */
1247N/A
1247N/A for (y = yoff; y < yoff + 64; y++) {
1247N/A for (x = xoff * bytepp, i = 0;
1247N/A x < ((xoff + 64) *bytepp);
1247N/A x += access_mode, i++) {
1247N/A mem_addr = (y*pitch*bytepp) + x + base;
1247N/A
1247N/A /* Check which access mode to use for write */
1247N/A
1247N/A switch (access_mode) {
1247N/A case 8: /* long long (8-byte) access mode */
1247N/A *(uint64_t volatile *)mem_addr =
1247N/A dp[subscr].val[i];
1247N/A break;
1247N/A
1247N/A case 4: /* word (4-byte) access mode */
1247N/A *(uint32_t volatile *)mem_addr =
1247N/A dp[subscr].word[i];
1247N/A break;
1247N/A
1247N/A case 2: /* short (2-byte) access mode */
1247N/A *(uint16_t volatile *)mem_addr =
1247N/A dp[subscr].halfwd[i];
1247N/A break;
1247N/A
1247N/A default: /* default to byte access */
1247N/A *(uint8_t volatile *)mem_addr =
1247N/A dp[subscr].byte[i];
1247N/A break;
1247N/A }
1247N/A }
1247N/A subscr++;
1247N/A }
1247N/A
1247N/A /* Read the Data From the Screen */
1247N/A
1247N/A for (y = yoff; y < yoff + 64; y++) {
1247N/A for (x = xoff * bytepp, i = 0;
1247N/A x < ((xoff + 64) * bytepp);
1247N/A x += access_mode, i++) {
1247N/A mem_addr = (y*pitch*bytepp) + x + base;
1247N/A
1247N/A switch (access_mode) {
1247N/A case 8: /* long long (8-byte) access mode */
1247N/A rdval[0].val[i] =
1247N/A *(uint64_t volatile const *)mem_addr;
1247N/A break;
1247N/A
1247N/A case 4: /* word (4-byte) access mode */
1247N/A rdval[0].word[i] =
1247N/A *(uint32_t volatile const *)mem_addr;
1247N/A break;
1247N/A
1247N/A case 2: /* short (2-byte) access mode */
1247N/A rdval[0].halfwd[i] =
1247N/A *(uint16_t volatile const *)mem_addr;
1247N/A break;
1247N/A
1247N/A default: /* default to byte access */
1247N/A rdval[0].byte[i] =
1247N/A *(uint8_t volatile const *)mem_addr;
1247N/A break;
1247N/A }
1247N/A }
1247N/A
1247N/A /* TODO: verification */
1247N/A
1247N/A if (memcmp(rdval, dp[subscr].byte, 64 * bytepp) != 0) {
1247N/A switch (access_mode) {
1247N/A case 8: /* long long (8-byte) access mode */
1247N/A for (i = 0; i < (8 * bytepp); i++) {
1247N/A if (rdval[0].val[i] != dp[subscr].val[i]) {
1247N/A return (B_FALSE);
1247N/A }
1247N/A }
1247N/A break;
1247N/A
1247N/A case 4: /* word (4-byte) access mode */
1247N/A for (i = 0; i < (16 * bytepp); i++) {
1247N/A if (rdval[0].word[i] != dp[subscr].word[i]) {
1247N/A return (B_FALSE);
1247N/A }
1247N/A }
1247N/A break;
1247N/A
1247N/A case 2: /* short (2-byte) access mode */
1247N/A for (i = 0; i < (32 * bytepp); i++) {
1247N/A if (rdval[0].halfwd[i] != dp[subscr].halfwd[i]) {
1247N/A return (B_FALSE);
1247N/A }
1247N/A }
1247N/A break;
1247N/A
1247N/A default: /* default to byte access */
1247N/A for (i = 0; i < (64 * bytepp); i++) {
1247N/A if (rdval[0].byte[i] != dp[subscr].byte[i]) {
1247N/A return (B_FALSE);
1247N/A }
1247N/A }
1247N/A break;
1247N/A }
1247N/A }
1247N/A subscr++;
1247N/A }
1247N/A
1247N/A return (B_TRUE);
1247N/A}