/* $Id$ */
/** @file
* VBoxVgaMiniPortDxe.c - VgaMiniPort Protocol Implementation.
*/
/*
* Copyright (C) 2009-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL) only, as it comes in the "COPYING.CDDL" file of the
* VirtualBox OSE distribution, in which case the provisions of the
* CDDL are applicable instead of those of the GPL.
*
* You may elect to license modified versions of this file under the
* terms and conditions of either the GPL or the CDDL or both.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include <Protocol/ComponentName.h>
#include <Protocol/ComponentName2.h>
#include <Protocol/DriverBinding.h>
#include <Protocol/VgaMiniPort.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <IndustryStandard/Pci22.h>
#include "VBoxPkg.h"
#include "VBoxVgaFonts.h"
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
/**
* Instance data for a VGA device this driver handles.
*/
typedef struct VBOXVGAMINIPORT
{
/** The VGA Mini Port Protocol. */
/** Magic value, VBOX_VGA_MINI_PORT_MAGIC. */
/** The controller handle of the device. */
/** The PciIo protocol for the device. */
/** Pointer to a VBOXVGAMINIPORT structure. */
/** VBOXVGAMINIPORT::u32Magic value (Isaac Asimov). */
/** VBOXVGAMINIPORT::u32Magic dead value. */
/*******************************************************************************
* Internal Functions *
*******************************************************************************/
static EFI_STATUS EFIAPI
static EFI_STATUS EFIAPI
static EFI_STATUS EFIAPI
static EFI_STATUS EFIAPI
static EFI_STATUS EFIAPI
static EFI_STATUS EFIAPI
static EFI_STATUS EFIAPI
static EFI_STATUS EFIAPI
/*******************************************************************************
* Global Variables *
*******************************************************************************/
/** EFI Driver Binding Protocol. */
{
/* .ImageHandle = */ NULL,
/* .DriverBindingHandle = */ NULL
};
/** EFI Component Name Protocol. */
{
"eng"
};
/** EFI Component Name 2 Protocol. */
{
"en"
};
/** Driver name translation table. */
{
{ "eng;en", L"PCI VGA Mini Port Driver" },
};
/**
* VBoxVgaMiniPort entry point.
*
* @returns EFI status code.
*
* @param ImageHandle The image handle.
* @param SystemTable The system table pointer.
*/
{
return rc;
}
/**
* @copydoc EFI_DRIVER_BINDING_SUPPORTED
*/
static EFI_STATUS EFIAPI
{
/*
* To perform the test we need to check some PCI configuration registers,
* just read all the standard ones to make life simpler.
*/
{
0 /* Offset */,
&CfgRegs);
{
/*
* Perform the test.
*/
if (IS_PCI_VGA(&CfgRegs))
{
#if 0 /** @todo this doesn't quite work with our DevVGA since it doesn't flag I/O access. */
#else
if (1)
#endif
{
rcRet = EFI_SUCCESS;
}
else
}
else
}
else
gBS->CloseProtocol(ControllerHandle, &gEfiPciIoProtocolGuid, This->DriverBindingHandle, ControllerHandle);
}
else
return rcRet;
}
/**
* @copydoc EFI_DRIVER_BINDING_START
*/
static EFI_STATUS EFIAPI
{
/*
* We need the PCI I/O abstraction protocol.
*/
{
/*
* Allocate and initialize the instance data.
*/
{
/*
* Register the VGA Mini Port Protocol.
*/
{
return EFI_SUCCESS;
}
}
else
gBS->CloseProtocol(ControllerHandle, &gEfiPciIoProtocolGuid, This->DriverBindingHandle, ControllerHandle);
}
else
return rc;
}
/**
* @copydoc EFI_DRIVER_BINDING_STOP
*/
static EFI_STATUS EFIAPI
{
DEBUG((DEBUG_INFO, "%a: ControllerHandle=%p NumberOfChildren=%u\n", __FUNCTION__, ControllerHandle, NumberOfChildren));
/*
* Get the miniport driver instance associated with the controller.
*/
{
{
/*
* Uninstall the VgaMiniPort interface.
*/
&pThisDev->VgaMiniPort);
{
/*
* Invalidate and release sources associated with the device instance.
*/
}
else
}
else
{
}
}
else
return rc;
}
/**
* @copydoc EFI_VGA_MINI_PORT_SET_MODE
*/
static EFI_STATUS EFIAPI
{
UINT8 r[64];
int i;
/*
* Check input.
*/
{
DEBUG((DEBUG_INFO, "%a: u32Magic=%x/%x\n", __FUNCTION__, pThisDev->u32Magic, VBOX_VGA_MINI_PORT_MAGIC));
return EFI_DEVICE_ERROR;
}
{
return EFI_UNSUPPORTED;
}
/* some initialization */
/*
* inb(r63, 0x3da); // reset attr F/F
* outb(0x3c0, 0); // disable palette
* outb(0x3d4, 0x11); outb(0x3d5, 0); // unprotect crtc regs 0 - 7
*/
ASMOutU8(0x3c0, 0);
do { \
for (i = 0 ; i < count; ++i) \
{ \
} \
} while (0)
/*
* Reset and set sequencer registers
*
* r0 = 0x01; r1 = 0x00; r2 = 0x03; r3 = 0x00; r4 = 0x02;
* boutb(5, 0x3c4, 0x3c5);
*/
r[0] = 0x01;
r[1] = 0x00;
r[2] = 0x03;
r[3] = 0x00;
r[4] = 0x02;
/*
* set misc out register
*
* outb(0x3c2, 0x67);
*
* r0 = 3
* boutb(1, 0x3c4, 0x3c5); // enable sequencer
*/
r[0] = 3;
/* set all crtc registers */
r[0] = 0x5f; r[1] = 0x4f; r[2] = 0x50; r[3] = 0x82;
r[4] = 0x55; r[5] = 0x81; r[6] = 0xbf; r[7] = 0x1f;
r[8] = 0x00; r[9] = 0x4f; r[10]= 0x0d; r[11]= 0x0e;
r[12]= 0x00; r[13]= 0x00; r[14]= 0x03; r[15]= 0xc0;
r[16]= 0x9c; r[17]= 0x0e; r[18]= 0x8f; r[19]= 0x28;
r[20]= 0x1f; r[21]= 0x96; r[22]= 0xb9; r[23]= 0xa3;
r[24]= 0xff;
/* set all graphics controller registers */
r[0]= 0x00; r[1]= 0x00; r[2]= 0x00; r[3]= 0x00;
r[4]= 0x00; r[5]= 0x10; r[6]= 0x0e; r[7]= 0x00;
r[8]= 0xff;
/* set all attribute registers */
r[0] = 0x00; r[1] = 0x01; r[2] = 0x02; r[3] = 0x03;
r[4] = 0x04; r[5] = 0x05; r[6] = 0x14; r[7] = 0x07;
r[8] = 0x38; r[9] = 0x39; r[10]= 0x3a; r[11]= 0x3b;
r[12]= 0x3c; r[13]= 0x3d; r[14]= 0x3e; r[15]= 0x3f;
r[16]= 0x0c; r[17]= 0x00; r[18]= 0x0f; r[19]= 0x08;
r[20]= 0x00;
/* set all VBox extended registers */
r[0] = 1;
r[0] = 3;
/* Load default values into the first 16 entries of the DAC */
{
{
0x00, 0x00, 0x00,
0x00, 0x00, 0x2A,
0x00, 0x2A, 0x00,
0x00, 0x2A, 0x2A,
0x2A, 0x00, 0x00,
0x2A, 0x00, 0x2A,
0x2A, 0x2A, 0x00,
0x2A, 0x2A, 0x2A,
0x00, 0x00, 0x15,
0x00, 0x00, 0x3F,
0x00, 0x2A, 0x15,
0x00, 0x2A, 0x3F,
0x2A, 0x00, 0x15,
0x2A, 0x00, 0x3F,
0x2A, 0x2A, 0x15,
0x2A, 0x2A, 0x3F,
0x00, 0x15, 0x00,
0x00, 0x15, 0x2A,
0x00, 0x3F, 0x00,
0x00, 0x3F, 0x2A,
0x2A, 0x15, 0x00,
0x2A, 0x15, 0x2A,
0x2A, 0x3F, 0x00,
0x2A, 0x3F, 0x2A,
0x00, 0x15, 0x15,
0x00, 0x15, 0x3F,
0x00, 0x3F, 0x15,
0x00, 0x3F, 0x3F,
0x2A, 0x15, 0x15,
0x2A, 0x15, 0x3F,
0x2A, 0x3F, 0x15,
0x2A, 0x3F, 0x3F,
0x15, 0x00, 0x00,
0x15, 0x00, 0x2A,
0x15, 0x2A, 0x00,
0x15, 0x2A, 0x2A,
0x3F, 0x00, 0x00,
0x3F, 0x00, 0x2A,
0x3F, 0x2A, 0x00,
0x3F, 0x2A, 0x2A,
0x15, 0x00, 0x15,
0x15, 0x00, 0x3F,
0x15, 0x2A, 0x15,
0x15, 0x2A, 0x3F,
0x3F, 0x00, 0x15,
0x3F, 0x00, 0x3F,
0x3F, 0x2A, 0x15,
0x3F, 0x2A, 0x3F,
0x15, 0x15, 0x00,
0x15, 0x15, 0x2A,
0x15, 0x3F, 0x00,
0x15, 0x3F, 0x2A,
0x3F, 0x15, 0x00,
0x3F, 0x15, 0x2A,
0x3F, 0x3F, 0x00,
0x3F, 0x3F, 0x2A,
0x15, 0x15, 0x15,
0x15, 0x15, 0x3F,
0x15, 0x3F, 0x15,
0x15, 0x3F, 0x3F,
0x3F, 0x15, 0x15,
0x3F, 0x15, 0x3F,
0x3F, 0x3F, 0x15,
0x3F, 0x3F, 0x3F
};
for (i = 0; i < 64; ++i)
{
}
}
/* Load the appropriate font into the first map */
{
unsigned offBase = 0;
switch (ModeNumber) {
case 0: // 80x25 mode, uses 8x16 font
height = 16;
break;
case 1: // 80x50 mode, uses 8x8 font
height = 8;
break;
default:
ASSERT(0); // Valid mode numbers checked above
return EFI_UNSUPPORTED;
}
// Enable font map access
{
/* Write sequencer registers */
/* Write graphics controller registers */
}
for (i = 0; i < 256; ++i)
{
}
// Set the CRTC Maximum Scan Line register
// Disable font map access again
{
/* Write sequencer registers */
/* Write graphics controller registers */
}
}
return EFI_SUCCESS;
}
/** @copydoc EFI_COMPONENT_NAME_GET_DRIVER_NAME */
static EFI_STATUS EFIAPI
{
return LookupUnicodeString2(Language,
TRUE);
}
/** @copydoc EFI_COMPONENT_NAME_GET_CONTROLLER_NAME */
static EFI_STATUS EFIAPI
{
/** @todo try query the protocol from the controller and forward the query. */
return EFI_UNSUPPORTED;
}
/** @copydoc EFI_COMPONENT_NAME2_GET_DRIVER_NAME */
static EFI_STATUS EFIAPI
{
return LookupUnicodeString2(Language,
FALSE);
}
/** @copydoc EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME */
static EFI_STATUS EFIAPI
{
/** @todo try query the protocol from the controller and forward the query. */
return EFI_UNSUPPORTED;
}