@@ -18,9 +18,25 @@ static struct vMode vModes[] = {
{ 1600, 1200 },
{ 1920, 1080 },
{ 1920, 1200 },
- { 0,0 }
+ { 0,0 },
+ { 0,0 },
+ { 0,0 },
+ { 0,0 },
+ { 0,0 },
+ { 0,0 },
+ { 0,0 },
+ { 0,0 },
+ { 0,0 },
+ { 0,0 },
+ { 0,0 },
+ { 0,0 },
+ { 0,0 },
};
+/* The number of width-height pairs in the above vModes structure */
+#define AVAILABLE_SLOTS 20
+
+
static void VgaWriteB(UInt16 port, UInt8 val)
{
UInt8 *ptr;
@@ -148,11 +164,98 @@ static InterruptMemberNumber PCIInterruptHandler
(InterruptSetMember ISTmember,
#endif
+/* Returns the number of resolutions in the vModes array */
+static int get_number_of_resolutions()
+{
+ int size_of_array, num_of_resolutions, index;
+
+ num_of_resolutions = 0;
+ size_of_array = sizeof(vModes) / sizeof(struct vMode);
+
+ for(index = 0; index < size_of_array; index++)
+ {
+ if (vModes[index].width != 0) {
+ num_of_resolutions++;
+ }
+ }
+
+ return num_of_resolutions;
+}
+
+
+/* Looks in the /options node for the value of the resolutions
property */
+static int add_user_resolutions(void)
+{
+ RegEntryID entry_id;
+ OSErr err;
+ OSStatus os_status = noErr;
+ Boolean is_done;
+ void *value;
+ RegPropertyValueSize property_size = -1;
+ int index, res_set_count, *res_values;
+
+ #define PROPERTY_NAME "resolutions"
+ #define NODE_PATH "Devices:device-tree:pci:QEMU,VGA"
+
+ /* init the entry variable */
+ err = RegistryEntryIDInit(&entry_id);
+ if (err != noErr) {
+ lprintf("Error: Failed to init entry variable! (Error: %d)\n", err);
+ return err;
+ }
+ is_done = false;
+
+ /* Get the entry ID value */
+ err = RegistryCStrEntryLookup(NULL /* start root */, NODE_PATH,
&entry_id);
+ if (err != noErr) {
+ lprintf("RegistryCStrEntryLookup() failure (Error: %d)\n", err);
+ return err;
+ }
+
+ /* Get the size of the property */
+ os_status = RegistryPropertyGetSize(&entry_id, PROPERTY_NAME,
&property_size);
+ if (os_status != noErr) {
+ lprintf("Error: Failed to get property size! (Error: %d)\n",
os_status);
+ return os_status;
+ }
+
+ /* Allocate memory to the value variable */
+ value = (void *) PoolAllocateResident(property_size, false);
+ if (value == NULL) {
+ lprintf("Error: Failed to allocate memory to value variable\n");
+ return -1;
+ }
+
+ /* Get the value of the property */
+ err = RegistryPropertyGet(&entry_id, PROPERTY_NAME, value,
&property_size);
+ if (err != noErr) {
+ lprintf("Error: Failed to find property value %s! (Error: %d)\n",
PROPERTY_NAME, err);
+ return err;
+ }
+
+ res_values = value;
+ res_set_count = property_size/4/2; /* divide by bytes per cell then
by cells per set */
+
+ /* Limit the number of resolutions to number of available slots in
vMode */
+ res_set_count = (res_set_count > AVAILABLE_SLOTS ?
AVAILABLE_SLOTS : res_set_count);
+
+ /* Load each resolution set */
+ for(index = 0; index < res_set_count; index++)
+ {
+ vModes[index].width = *(res_values++);
+ vModes[index].height = *(res_values++);
+ }
+ return 0;
+}
+
+
Add the ability to add resolutions from the command-line. This patch works by looking for a property called 'resolutions' in the QEMU,VGA node of OpenBIOS. If it is found all the resolutions are parsed and loaded. Example command-line: -prom-env resolutions=512x342,640x480,800x600,1024x600,1200x700,1440x900 Signed-off-by: John Arbuckle <programmingkidx@gmail.com> --- v4 Removed all ASCII text processing code and replaced it with integer processing code. v3 Changed implementation of atoi(). Removed strlen() implementation. Removed pow() implementation. Changed entry_id from pointer to automatic variable. v2 Implemented my own malloc(), strlen(), pow(), and atoi() functions. Removed free() calls. Changed get_set_count() to get_resolution_set_count(). QemuVGADriver/src/QemuVga.c | 107 ++++++++++++++++++++++++++++++++++ +++++++++- 1 file changed, 105 insertions(+), 2 deletions(-) OSStatus QemuVga_Init(void) { UInt16 id, i; UInt32 mem, width, height, depth; + add_user_resolutions(); + lprintf("First MMIO read...\n"); id = DispiReadW(VBE_DISPI_INDEX_ID); mem = DispiReadW(VBE_DISPI_INDEX_VIDEO_MEMORY_64K); @@ -183,7 +286,7 @@ OSStatus QemuVga_Init(void) i = 0; } GLOBAL.bootMode = i; - GLOBAL.numModes = sizeof(vModes) / sizeof(struct vMode) - 1; + GLOBAL.numModes = get_number_of_resolutions(); QemuVga_SetMode(GLOBAL.bootMode, depth, 0);