qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH] Add resolutions via the command-line


From: Alfonso Gamboa
Subject: Re: [Qemu-devel] [PATCH] Add resolutions via the command-line
Date: Mon, 19 Sep 2016 16:56:54 -0700

John,

http://mirror.informatimago.com/next/developer.apple.com/qa/dv/dv43.html
perhaps yields some insight:

*Note:*
An example of this is the video 'ndrv' support in Mac OS X. Mac OS X can
load and run native video drivers from the ROM of PCI video cards. This
allows Mac OS X to provide basic video functionality on any card that
supports traditional Mac OS boot-time video, without having a real Mac OS X
video driver available. In order for this to work your video driver must:

   - link with only the standard libraries (DriverServicesLib,
   NameRegistryLib, VideoServicesLib, and PCILib)
   - not access low-memory globals
   - recognize that it's possible for the logical and physical addresses of
   its PCI hardware to be different, and always access the appropriate
   addresses through the appropriate Name Registry properties.


On Mon, Sep 19, 2016 at 3:44 PM, Benjamin Herrenschmidt <
address@hidden> wrote:

> On Mon, 2016-09-19 at 08:44 -0400, G 3 wrote:
> > On Sep 19, 2016, at 2:24 AM, Benjamin Herrenschmidt wrote:
> >
> > >
> > > On Sat, 2016-09-17 at 23:31 -0400, G 3 wrote:
> > > >
> > > > Add the ability to add resolutions from the command-line. This
> > > > patch
> > > > works by
> > > > looking for a property called 'resolutions' in the options node
> > > > of
> > > > OpenBIOS.
> > > > If it is found all the resolutions are parsed and loaded.
> > > >
> > > > Example command-line:
> > >
> > > You must not use the C library in the ndrv (malloc, atoi, ...)
> > >
> > > Stick to what's in DriverServicesLib and NameRegistryLib.
> >
> > I originally thought that, but was wrong. Those C library functions
> > work.
>
> No, don't use them. They "seem" to work but bad thing will happen,
> especially on OS X.
>
> Cheers,
> Ben.
>
> >
> > >
> > >
> > > >
> > > > -prom-env
> > > > resolutions=512x342,640x480,800x600,1024x600,1200x700,1440x900
> > > >
> > > > Signed-off-by: John Arbuckle <address@hidden>
> > > > ---
> > > >   QemuVGADriver/src/QemuVga.c | 227
> > > > ++++++++++++++++++++++++++++++++++
> > > > +++++++++-
> > > >   1 file changed, 225 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/QemuVGADriver/src/QemuVga.c
> > > > b/QemuVGADriver/src/QemuVga.c
> > > > index 4584242..d74fa41 100644
> > > > --- a/QemuVGADriver/src/QemuVga.c
> > > > +++ b/QemuVGADriver/src/QemuVga.c
> > > > @@ -3,6 +3,7 @@
> > > >   #include "DriverQDCalls.h"
> > > >   #include "QemuVga.h"
> > > >   #include <Timer.h>
> > > > +#include <stdlib.h>
> > > >
> > > >   /* List of supported modes */
> > > >   struct vMode {
> > > > @@ -18,7 +19,21 @@ static struct vMode vModes[] =  {
> > > >           { 1600, 1200 },
> > > >           { 1920, 1080 },
> > > >           { 1920, 1200 },
> > > > - { 0,0 }
> > > > +
> > > > + /* The rest are place holders */
> > > > + { 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 },
> > > >   };
> > > >
> > > >   static void VgaWriteB(UInt16 port, UInt8 val)
> > > > @@ -147,11 +162,219 @@ static InterruptMemberNumber
> > > > PCIInterruptHandler(InterruptSetMember ISTmember,
> > > >   }
> > > >   #endif
> > > >
> > > > +/*
> > > > + * Get the resolution set at the specified index.
> > > > + * The string returned needs to be freed when no longer used.
> > > > + */
> > > > +static char *get_set(const char *resolution_set_str, int
> > > > set_number)
> > > > +{
> > > > + const int max_buf_size = 100;
> > > > + char c, *buffer;
> > > > + int index, comma_count;
> > > > +
> > > > + buffer = (char *) malloc(max_buf_size);
> > > > + comma_count = 0;
> > > > + index = 0;
> > > > + set_number++; /* Makes things easier to understand */
> > > > +
> > > > + c = *(resolution_set_str++);
> > > > + while (c != '\0') {
> > > > +         buffer[index++] = c;
> > > > +         c = *(resolution_set_str++);
> > > > +         if (c == ',') {
> > > > +                 comma_count++;
> > > > +                 if (comma_count == set_number || index
> > > > >=
> > > > max_buf_size) {
> > > > +                         buffer[index] = '\0';
> > > > +                         return buffer;
> > > > +                 }
> > > > +
> > > > +                 else {
> > > > +                         /* reset the buffer */
> > > > +                         index = 0;
> > > > +                         c = *(resolution_set_str++);
> > > > +                 }
> > > > +         }
> > > > + }
> > > > +
> > > > + buffer[index] = '\0';
> > > > +
> > > > + return buffer;
> > > > +}
> > > > +
> > > > +/*
> > > > + * Get the number of resolution sets
> > > > + */
> > > > +
> > > > +static int get_set_count(const char *resolution_sets_str)
> > > > +{
> > > > + char c;
> > > > + int count;
> > > > +
> > > > + /* Count the number of commas */
> > > > + count = 0;
> > > > + c = *(resolution_sets_str++);
> > > > + while (c != '\0') {
> > > > +         if (c == ',') {
> > > > +                 count++;
> > > > +         }
> > > > +         c = *(resolution_sets_str++);
> > > > + }
> > > > +
> > > > + return count + 1;
> > > > +}
> > > > +
> > > > +/*
> > > > + * Returns the width value of a resolution set
> > > > + * Example:
> > > > + * input: 16000x9000
> > > > + * output: 16000
> > > > + */
> > > > +
> > > > +static int get_width(const char *resolution_str)
> > > > +{
> > > > + int index;
> > > > + char c;
> > > > + const int max_buf_size = 25;
> > > > + char buffer[max_buf_size];
> > > > + c = *(resolution_str++);
> > > > + index = 0;
> > > > + while (c != 'x' && index < max_buf_size) {
> > > > +         buffer[index++] = c;
> > > > +         c = *(resolution_str++);
> > > > + }
> > > > +
> > > > + /* Terminate string */
> > > > + buffer[index] = '\0';
> > > > +
> > > > + return atoi(buffer);
> > > > +}
> > > > +
> > > > +/*
> > > > + * Returns the height value of a resolution set
> > > > + * Example
> > > > + * input: 16000x9000
> > > > + * output: 9000
> > > > + */
> > > > +
> > > > +static int get_height(const char *resolution_str)
> > > > +{
> > > > + int index;
> > > > + char c;
> > > > + const int max_buf_size = 25;
> > > > + char buffer[max_buf_size];
> > > > +
> > > > + /* skip to character after x */
> > > > + while (*resolution_str != 'x') {
> > > > +         resolution_str++;
> > > > + }
> > > > + resolution_str++;
> > > > +
> > > > + /* Add digits of the height to the buffer */
> > > > + index = 0;
> > > > + c = *(resolution_str++);
> > > > + while (c != '\0') {
> > > > +         buffer[index++] = c;
> > > > +         c = *(resolution_str++);
> > > > +         if(index >= max_buf_size) {
> > > > +                 break;
> > > > +         }
> > > > + }
> > > > +
> > > > + /* Terminate string */
> > > > + buffer[index] = '\0';
> > > > +
> > > > + return atoi(buffer);
> > > > +}
> > > > +
> > > > +/*
> > > > + * Looks in the /chosen node for the value of the resolutions
> > > > property
> > > > + */
> > > > +static int add_user_resolutions(void)
> > > > +{
> > > > + RegEntryID *entry_id;
> > > > + OSErr err;
> > > > + Boolean is_done;
> > > > + void *value;
> > > > + RegPropertyValueSize property_size;
> > > > + int index, res_set_count;
> > > > + char *set_str;
> > > > +
> > > > + #define PROPERTY_NAME "resolutions"
> > > > + #define NODE_PATH "Devices:device-tree:options"
> > > > +
> > > > + /* init the entry variable */
> > > > + err = RegistryEntryIDInit(entry_id);
> > > > + if (err != noErr) {
> > > > +         lprintf("Error: Failed to init entry variable!
> > > > (%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
> > > > (%d)\n",
> > > > err);
> > > > +         return err;
> > > > + }
> > > > +
> > > > + /* Get the size of the property */
> > > > + err = RegistryPropertyGetSize(entry_id, PROPERTY_NAME,
> > > > &property_size);
> > > > + if (err != noErr) {
> > > > +         lprintf("Error: Failed to get property size!
> > > > (%d)\n", err);
> > > > +         return err;
> > > > + }
> > > > +
> > > > + /* allocate memory to the value variable */
> > > > + value = (void *) malloc(property_size);
> > > > +
> > > > + /* 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!\n", PROPERTY_NAME);
> > > > +         return err;
> > > > + }
> > > > +
> > > > + /* Limit the number of resolutions to 20 */
> > > > + #define sane_number_of_resolutions 20
> > > > + res_set_count = get_set_count(value);
> > > > + res_set_count = (res_set_count >
> > > > sane_number_of_resolutions
> > > > ?
> > > > sane_number_of_resolutions : res_set_count);
> > > > +
> > > > + /* Add each resolution set */
> > > > + for(index = 0; index < res_set_count; index++) {
> > > > +         set_str = get_set(value, index);
> > > > +         vModes[index].width = get_width(set_str);
> > > > +         vModes[index].height = get_height(set_str);
> > > > +         free(set_str);
> > > > + }
> > > > +
> > > > + free(value);
> > > > +}
> > > > +
> > > > +/* Returns the number of resolutions */
> > > > +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++)
> > > > + {
> > > > +         /* Don't count any place holders */
> > > > +         if (vModes[index].width != 0) {
> > > > +                 num_of_resolutions++;
> > > > +         }
> > > > + }
> > > > +
> > > > + return num_of_resolutions;
> > > > +}
> > > >
> > > >   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);
> > > > @@ -183,7 +406,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);
> > > >
>
>


-- 
Alfonso Gamboa
Gran Turismo Enterprises, Inc.   |   Director, Global Operations
4660 La Jolla Village Drive    -     La Jolla, CA 92122  -  USA
www.gtxent.com  -=-  www.blue-foundation.org -=- profiles.gtxent.com/aag


reply via email to

[Prev in Thread] Current Thread [Next in Thread]