* Sasha Levin <[email protected]> wrote:

> INT10 handler is a basic implementation of BIOS video services.
> 
> The handler implements a VESA interface which is initialized at
> the very beginning of loading the kernel.
> 
> Signed-off-by: John Floren <[email protected]>
> [ turning code into patches and cleanup ]
> Signed-off-by: Sasha Levin <[email protected]>
> ---
>  tools/kvm/bios/bios-rom.S |   56 ++++++++--------
>  tools/kvm/bios/int10.c    |  161 
> +++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 189 insertions(+), 28 deletions(-)
>  create mode 100644 tools/kvm/bios/int10.c
> 
> diff --git a/tools/kvm/bios/bios-rom.S b/tools/kvm/bios/bios-rom.S
> index 8a53dcd..b636cb8 100644
> --- a/tools/kvm/bios/bios-rom.S
> +++ b/tools/kvm/bios/bios-rom.S
> @@ -27,36 +27,36 @@ ENTRY_END(bios_intfake)
>   * We ignore bx settings
>   */
>  ENTRY(bios_int10)
> -     test $0x0e, %ah
> -     jne 1f
> +     pushw   %fs
> +     pushl   %es
> +     pushl   %edi
> +     pushl   %esi
> +     pushl   %ebp
> +     pushl   %esp
> +     pushl   %edx
> +     pushl   %ecx
> +     pushl   %ebx
> +     pushl   %eax
> +
> +     movl            %esp, %eax
> +     /* this is way easier than doing it in assembly */
> +     /* just push all the regs and jump to a C handler */
> +     call    int10handler
> +
> +     popl    %eax
> +     popl    %ebx
> +     popl    %ecx
> +     popl    %edx
> +     popl    %esp
> +     popl    %ebp
> +     popl    %esi
> +     popl    %edi
> +     popl    %es
> +     popw    %fs
>  
> -/*
> - * put char in AL at current cursor and
> - * increment cursor position
> - */
> -putchar:
> -     stack_swap
> -
> -     push %fs
> -     push %bx
> -
> -     mov $VGA_RAM_SEG, %bx
> -     mov %bx, %fs
> -     mov %cs:(cursor), %bx
> -     mov %al, %fs:(%bx)
> -     inc %bx
> -     test $VGA_PAGE_SIZE, %bx
> -     jb putchar_new
> -     xor %bx, %bx
> -putchar_new:
> -     mov %bx, %fs:(cursor)
> -
> -     pop %bx
> -     pop %fs
> -
> -     stack_restore
> -1:
>       IRET
> +
> +
>  /*
>   * private IRQ data
>   */
> diff --git a/tools/kvm/bios/int10.c b/tools/kvm/bios/int10.c
> new file mode 100644
> index 0000000..98205c3
> --- /dev/null
> +++ b/tools/kvm/bios/int10.c
> @@ -0,0 +1,161 @@
> +#include "kvm/segment.h"
> +#include "kvm/bios.h"
> +#include "kvm/util.h"
> +#include "kvm/vesa.h"
> +#include <stdint.h>
> +
> +#define VESA_MAGIC ('V' + ('E' << 8) + ('S' << 16) + ('A' << 24))
> +
> +struct int10args {
> +     u32     eax;
> +     u32     ebx;
> +     u32     ecx;
> +     u32     edx;
> +     u32     esp;
> +     u32     ebp;
> +     u32     esi;
> +     u32     edi;
> +     u32     es;
> +};
> +
> +/* VESA General Information table */
> +struct vesa_general_info {
> +     u32 signature;                  /* 0 Magic number = "VESA" */
> +     u16 version;                    /* 4 */
> +     void *vendor_string;            /* 6 */
> +     u32 capabilities;               /* 10 */
> +     void *video_mode_ptr;           /* 14 */
> +     u16 total_memory;               /* 18 */
> +
> +     u8 reserved[236];               /* 20 */
> +} __attribute__ ((packed));
> +
> +
> +struct vminfo {
> +     u16     mode_attr;              /* 0 */
> +     u8      win_attr[2];            /* 2 */
> +     u16     win_grain;              /* 4 */
> +     u16     win_size;               /* 6 */
> +     u16     win_seg[2];             /* 8 */
> +     u32     win_scheme;             /* 12 */
> +     u16     logical_scan;           /* 16 */
> +
> +     u16     h_res;                  /* 18 */
> +     u16     v_res;                  /* 20 */
> +     u8      char_width;             /* 22 */
> +     u8      char_height;            /* 23 */
> +     u8      memory_planes;          /* 24 */
> +     u8      bpp;                    /* 25 */
> +     u8      banks;                  /* 26 */
> +     u8      memory_layout;          /* 27 */
> +     u8      bank_size;              /* 28 */
> +     u8      image_planes;           /* 29 */
> +     u8      page_function;          /* 30 */
> +
> +     u8      rmask;                  /* 31 */
> +     u8      rpos;                   /* 32 */
> +     u8      gmask;                  /* 33 */
> +     u8      gpos;                   /* 34 */
> +     u8      bmask;                  /* 35 */
> +     u8      bpos;                   /* 36 */
> +     u8      resv_mask;              /* 37 */
> +     u8      resv_pos;               /* 38 */
> +     u8      dcm_info;               /* 39 */
> +
> +     u32     lfb_ptr;                /* 40 Linear frame buffer address */
> +     u32     offscreen_ptr;          /* 44 Offscreen memory address */
> +     u16     offscreen_size;         /* 48 */
> +
> +     u8      reserved[206];          /* 50 */
> +};
> +
> +char oemstring[11] = "KVM VESA";
> +u16 modes[2] = { 0x0112, 0xffff };
> +
> +static inline void outb(unsigned short port, unsigned char val)
> +{
> +     asm volatile("outb %0, %1" : : "a"(val), "Nd"(port));
> +}
> +
> +/*
> + * It's probably much more useful to make this print to the serial
> + * line rather than print to a non-displayed VGA memory
> + */
> +static inline void int10putchar(struct int10args *args)
> +{
> +     u8 al, ah;
> +
> +     al = args->eax & 0xFF;
> +     ah = (args->eax & 0xFF00) >> 8;
> +
> +     outb(0x3f8, al);
> +}
> +
> +static void int10vesa(struct int10args *args)
> +{
> +     u8 al, ah;
> +     struct vesa_general_info *destination;
> +     struct vminfo *vi;
> +
> +     al = args->eax;
> +     ah = args->eax >> 8;
> +
> +     switch (al) {
> +     case 0:
> +             /* Set controller info */
> +
> +             destination = (struct vesa_general_info *)args->edi;
> +             *destination = (struct vesa_general_info) {
> +                     .signature      = VESA_MAGIC,
> +                     .version        = 0x102,
> +                     .vendor_string  = oemstring,
> +                     .capabilities   = 0x10,
> +                     .video_mode_ptr = modes,
> +                     .total_memory   = (4*VESA_WIDTH * VESA_HEIGHT) / 
> 0x10000,
> +             };
> +
> +             break;
> +     case 1:
> +             vi = (struct vminfo *)args->edi;
> +             *vi = (struct vminfo) {
> +                     .mode_attr      = 0xd9, /* 11011011 */
> +                     .logical_scan   = VESA_WIDTH*4,
> +                     .h_res          = VESA_WIDTH,
> +                     .v_res          = VESA_HEIGHT,
> +                     .bpp            = VESA_BPP,
> +                     .memory_layout  = 6,
> +                     .memory_planes  = 1,
> +                     .lfb_ptr        = VESA_MEM_ADDR,
> +                     .rmask          = 8,
> +                     .gmask          = 8,
> +                     .bmask          = 8,
> +                     .resv_mask      = 8,
> +                     .resv_pos       = 24,
> +                     .bpos           = 16,
> +                     .gpos           = 8,
> +             };
> +
> +             break;
> +     }
> +
> +     args->eax                       = 0x004f; /* return success every time 
> */
> +
> +}
> +
> +bioscall void int10handler(struct int10args *args)
> +{
> +     u8 ah;
> +
> +     ah = (args->eax & 0xff00) >> 8;
> +
> +     switch (ah) {
> +     case 0x0e:
> +             int10putchar(args);
> +             break;
> +     case 0x4f:
> +             int10vesa(args);
> +             break;
> +     }

Why are these functions prefixed in such a weird way? Why not int10_putchar(), 
int10_vesa(), etc. like all other bits in tools/kvm/?

Thanks,

        Ingo
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to