/*~*~*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*~*/ /* */ /* Developed by: Peter Armistead Dennett */ /* PADSOFT, Inc */ /* 61 Harbor Lane */ /* Kemah, Texas 77565 */ /* */ /* pdennett@padsoft.com */ /* (281) 334 3800 */ /* http://www.padsoft.com */ /* */ /* NO rights reserved */ /* */ /*~*~*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*~*/ // vmware-vga.c Interface routines for VMWare frame buffer under eCos // Revision History // Oct 2006 by Peter Dennett // - Initial version, based on documents from the xfree86 VMWare driver //=========================================================================== // VMWARE-VGA is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 or (at your option) any later version. // // VMWARE-VGA is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // // You should have received a copy of the GNU General Public License along // with PW; if not, write to the Free Software Foundation, Inc., // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. // // As a special exception, if other files instantiate templates or use macros // or inline functions from this file, or you compile this file and link it // with other works to produce a work based on this file, this file does not // by itself cause the resulting work to be covered by the GNU General Public // License. However the source code for this file must still be made available // in accordance with section (3) of the GNU General Public License. // // This exception does not invalidate any other reasons why a work based on // this file might be covered by the GNU General Public License. //=========================================================================== #include // sleep() #include // memset() #include #include #include #include #include // HAL_DISABLE_INTERRUPT #include #include // HAL_WRITE & READ #include // diag_printf #include // thread defines #include "vmware-vga.h" ////////////////////////////////////////////////////////////////////////////// // Register operations static uint32 vmwareReadReg(pVMWareVGA pVMWARE, uint32 index) { uint32 ret; CYG_INTERRUPT_STATE interruptState; HAL_DISABLE_INTERRUPTS(interruptState); // Dont allow interrupts between ops HAL_WRITE_UINT32(pVMWARE->indexReg, index); HAL_READ_UINT32(pVMWARE->valueReg, ret); HAL_RESTORE_INTERRUPTS(interruptState); return ret; } static void vmwareWriteReg(pVMWareVGA pVMWARE, uint32 index, uint32 value) { CYG_INTERRUPT_STATE interruptState; HAL_DISABLE_INTERRUPTS(interruptState); // Dont allow interrupts between ops HAL_WRITE_UINT32(pVMWARE->indexReg, index); HAL_WRITE_UINT32(pVMWARE->valueReg, value); HAL_RESTORE_INTERRUPTS(interruptState); return; } ////////////////////////////////////////////////////////////////////////////// // FIFO operations static void vmwareWaitForFIFO(pVMWareVGA pVMWARE) { vmwareWriteReg(pVMWARE, SVGA_REG_SYNC, 1); while (vmwareReadReg(pVMWARE, SVGA_REG_BUSY)) ; return; } static void vmwareWriteWordToFIFO(pVMWareVGA pVMWARE, uint32 value) { uint32 *vmwareFIFO = pVMWARE->FIFO; // Need to sync? if ((vmwareFIFO[SVGA_FIFO_NEXT_CMD] + sizeof(uint32) == vmwareFIFO[SVGA_FIFO_STOP]) || (vmwareFIFO[SVGA_FIFO_NEXT_CMD] == vmwareFIFO[SVGA_FIFO_MAX] - sizeof(uint32) && vmwareFIFO[SVGA_FIFO_STOP] == vmwareFIFO[SVGA_FIFO_MIN])) { diag_printf("vmware-vga: Syncing because of full fifo\n"); vmwareWaitForFIFO(pVMWARE); } vmwareFIFO[vmwareFIFO[SVGA_FIFO_NEXT_CMD] / sizeof(uint32)] = value; if (vmwareFIFO[SVGA_FIFO_NEXT_CMD] == (vmwareFIFO[SVGA_FIFO_MAX] - sizeof(uint32))) vmwareFIFO[SVGA_FIFO_NEXT_CMD] = vmwareFIFO[SVGA_FIFO_MIN]; else vmwareFIFO[SVGA_FIFO_NEXT_CMD] += sizeof(uint32); #if 0 diag_printf("FIFO MIN: %08X MAX: %08X NEXT %08X STOP %08X VALUE %08X\n", vmwareFIFO[SVGA_FIFO_MIN], vmwareFIFO[SVGA_FIFO_MAX], vmwareFIFO[SVGA_FIFO_NEXT_CMD], vmwareFIFO[SVGA_FIFO_STOP], value); #endif return; } static void vmwareInitFIFO(pVMWareVGA pVMWARE) { uint32 *vmwareFIFO; vmwareFIFO = pVMWARE->FIFO; vmwareFIFO[SVGA_FIFO_MIN] = 4 * sizeof(uint32); vmwareFIFO[SVGA_FIFO_MAX] = pVMWARE->FIFOSize; vmwareFIFO[SVGA_FIFO_NEXT_CMD] = 4 * sizeof(uint32); vmwareFIFO[SVGA_FIFO_STOP] = 4 * sizeof(uint32); #if 0 diag_printf("FIFO MIN: %08X MAX: %08X NEXT %08X STOP %08X\n", vmwareFIFO[SVGA_FIFO_MIN], vmwareFIFO[SVGA_FIFO_MAX], vmwareFIFO[SVGA_FIFO_NEXT_CMD], vmwareFIFO[SVGA_FIFO_STOP]); #endif vmwareWriteReg(pVMWARE, SVGA_REG_CONFIG_DONE, 1); return; } static void vmwareStopFIFO(pVMWareVGA pVMWARE) { vmwareWriteReg(pVMWARE, SVGA_REG_CONFIG_DONE, 0); } ////////////////////////////////////////////////////////////////////////////// // FIFO commands static void vmwareSendSVGACmdUpdate(pVMWareVGA pVMWARE, pBoxRec pBB) { vmwareWriteWordToFIFO(pVMWARE, SVGA_CMD_UPDATE); vmwareWriteWordToFIFO(pVMWARE, pBB->x1); vmwareWriteWordToFIFO(pVMWARE, pBB->y1); vmwareWriteWordToFIFO(pVMWARE, pBB->x2 - pBB->x1); vmwareWriteWordToFIFO(pVMWARE, pBB->y2 - pBB->y1); return; } static void vmwareSendSVGACmdUpdateFullScreen(pVMWareVGA pVMWARE) { BoxRec BB; BB.x1 = 0; BB.y1 = 0; BB.x2 = pVMWARE->FBWidth; BB.y2 = pVMWARE->FBHeight; vmwareSendSVGACmdUpdate(pVMWARE, &BB); return; } static void vmwareSolidFill(pVMWareVGA pVMWARE, uint32 x, uint32 y, uint32 w, uint32 h, uint32 color) { vmwareWriteWordToFIFO(pVMWARE, SVGA_CMD_RECT_FILL); vmwareWriteWordToFIFO(pVMWARE, color); vmwareWriteWordToFIFO(pVMWARE, x); vmwareWriteWordToFIFO(pVMWARE, y); vmwareWriteWordToFIFO(pVMWARE, w); vmwareWriteWordToFIFO(pVMWARE, h); return; } static void vmwareRectCopy(pVMWareVGA pVMWARE, uint32 x1, uint32 y1, uint32 x2, uint32 y2, uint32 w, uint32 h) { vmwareWriteWordToFIFO(pVMWARE, SVGA_CMD_RECT_COPY); vmwareWriteWordToFIFO(pVMWARE, x1); vmwareWriteWordToFIFO(pVMWARE, y1); vmwareWriteWordToFIFO(pVMWARE, x2); vmwareWriteWordToFIFO(pVMWARE, y2); vmwareWriteWordToFIFO(pVMWARE, w); vmwareWriteWordToFIFO(pVMWARE, h); return; } ////////////////////////////////////////////////////////////////////////////// // External interface routines pVMWareVGA vmwareInitialize(void) { static VMWareVGA VMWARE; cyg_pci_device dev_info; cyg_pci_device_id devid; cyg_uint16 cmd; int i; // Find and configuring PCI VGA devices cyg_pci_init(); for (devid=CYG_PCI_NULL_DEVID; cyg_pci_find_next(devid, &devid); ) { cyg_pci_get_device_info(devid, &dev_info); // Get device info if ((dev_info.vendor == PCI_VENDOR_ID_VMWARE) && ((dev_info.device == PCI_DEVICE_ID_VMWARE_SVGA2) || (dev_info.device == PCI_DEVICE_ID_VMWARE_SVGA))) { // Configure the device if (cyg_pci_configure_device(&dev_info)) { // Don't use cyg_pci_set_device_info since it clears // some of the fields we want to print out below. cyg_pci_read_config_uint16(dev_info.devid, CYG_PCI_CFG_COMMAND, &cmd); cmd |= CYG_PCI_CFG_COMMAND_IO|CYG_PCI_CFG_COMMAND_MEMORY; cyg_pci_write_config_uint16(dev_info.devid, CYG_PCI_CFG_COMMAND, cmd); } else { diag_printf(" Device configuration failed"); if (dev_info.command & CYG_PCI_CFG_COMMAND_ACTIVE) diag_printf(" - device already enabled\n"); else diag_printf(" - resource problem\n"); continue; } #if 0 for (i=0; iFB; *(FB+x+y*pVMWARE->FBBytesPerLine) = color; } void vmwareClear(pVMWareVGA pVMWARE, uint32 color) { uint8 *FB = pVMWARE->FB; memset(FB, (uint8)color, pVMWARE->FBWidth*pVMWARE->FBHeight); return; } void vmwareLoadPalette(pVMWareVGA pVMWARE, int numColors, int *indeces, vmwareColors *colors) { int i; for (i=0; iFBHeight; i++) vmwareDrawPoint(pVMWARE, i, i, 255); vmwareSendSVGACmdUpdateFullScreen(pVMWARE); sleep(5); for (i=0; iFBHeight; i++) vmwareDrawPoint(pVMWARE, i, pVMWARE->FBHeight-1-i, 255); vmwareSendSVGACmdUpdateFullScreen(pVMWARE); sleep(5); if (pVMWARE->Capabilities & SVGA_CAP_RECT_FILL) { diag_printf("Test solid fill\n"); vmwareSolidFill(pVMWARE, 50, 50, 35, 35, 255); vmwareSendSVGACmdUpdateFullScreen(pVMWARE); sleep(5); } if (pVMWARE->Capabilities & SVGA_CAP_RECT_COPY) { diag_printf("Test rect copy\n"); vmwareRectCopy(pVMWARE, 25, 25, 100, 50, 100, 100); vmwareSendSVGACmdUpdateFullScreen(pVMWARE); sleep(5); } #if 1 diag_printf("FBWidth: %d\n", pVMWARE->FBWidth); diag_printf("FBHeight: %d\n", pVMWARE->FBHeight); diag_printf("FBBitsPerPixel: %d\n", pVMWARE->FBBitsPerPixel); diag_printf("FBRedMask: 0x%X\n", pVMWARE->FBRedMask); diag_printf("FBGreenMask: 0x%X\n", pVMWARE->FBGreenMask); diag_printf("FBBlueMask: 0x%X\n", pVMWARE->FBBlueMask); diag_printf("FBDepth: %d\n", pVMWARE->FBDepth); diag_printf("FBOffset: %d\n", pVMWARE->FBOffset); diag_printf("FBBytesPerLine: %d\n", pVMWARE->FBBytesPerLine); diag_printf("FBSize: %d\n", pVMWARE->FBSize); diag_printf("Capabilities: 0x%X\n", pVMWARE->Capabilities); #endif vmwareTerminate(pVMWARE); } else { diag_printf("Did not find VMWare VGA\n"); } while (1) sleep(1); } void cyg_start(void) { cyg_thread_create(10, // Priority - just a number (cyg_thread_entry_t*)vmware_vga_test, // entry 0, // "vga_thread", // Name &stack[0], // Stack CYGNUM_HAL_STACK_SIZE_TYPICAL, // Size &thread_handle, // Handle &thread_data ); cyg_thread_resume(thread_handle); cyg_scheduler_start(); } #endif