1*cc8875d1SJohn Floren #include "kvm/segment.h" 2*cc8875d1SJohn Floren #include "kvm/bios.h" 3*cc8875d1SJohn Floren #include "kvm/util.h" 4*cc8875d1SJohn Floren #include "kvm/vesa.h" 5*cc8875d1SJohn Floren #include <stdint.h> 6*cc8875d1SJohn Floren 7*cc8875d1SJohn Floren #define VESA_MAGIC ('V' + ('E' << 8) + ('S' << 16) + ('A' << 24)) 8*cc8875d1SJohn Floren 9*cc8875d1SJohn Floren struct int10_args { 10*cc8875d1SJohn Floren u32 eax; 11*cc8875d1SJohn Floren u32 ebx; 12*cc8875d1SJohn Floren u32 ecx; 13*cc8875d1SJohn Floren u32 edx; 14*cc8875d1SJohn Floren u32 esp; 15*cc8875d1SJohn Floren u32 ebp; 16*cc8875d1SJohn Floren u32 esi; 17*cc8875d1SJohn Floren u32 edi; 18*cc8875d1SJohn Floren u32 es; 19*cc8875d1SJohn Floren }; 20*cc8875d1SJohn Floren 21*cc8875d1SJohn Floren /* VESA General Information table */ 22*cc8875d1SJohn Floren struct vesa_general_info { 23*cc8875d1SJohn Floren u32 signature; /* 0 Magic number = "VESA" */ 24*cc8875d1SJohn Floren u16 version; /* 4 */ 25*cc8875d1SJohn Floren void *vendor_string; /* 6 */ 26*cc8875d1SJohn Floren u32 capabilities; /* 10 */ 27*cc8875d1SJohn Floren void *video_mode_ptr; /* 14 */ 28*cc8875d1SJohn Floren u16 total_memory; /* 18 */ 29*cc8875d1SJohn Floren 30*cc8875d1SJohn Floren u8 reserved[236]; /* 20 */ 31*cc8875d1SJohn Floren } __attribute__ ((packed)); 32*cc8875d1SJohn Floren 33*cc8875d1SJohn Floren 34*cc8875d1SJohn Floren struct vminfo { 35*cc8875d1SJohn Floren u16 mode_attr; /* 0 */ 36*cc8875d1SJohn Floren u8 win_attr[2]; /* 2 */ 37*cc8875d1SJohn Floren u16 win_grain; /* 4 */ 38*cc8875d1SJohn Floren u16 win_size; /* 6 */ 39*cc8875d1SJohn Floren u16 win_seg[2]; /* 8 */ 40*cc8875d1SJohn Floren u32 win_scheme; /* 12 */ 41*cc8875d1SJohn Floren u16 logical_scan; /* 16 */ 42*cc8875d1SJohn Floren 43*cc8875d1SJohn Floren u16 h_res; /* 18 */ 44*cc8875d1SJohn Floren u16 v_res; /* 20 */ 45*cc8875d1SJohn Floren u8 char_width; /* 22 */ 46*cc8875d1SJohn Floren u8 char_height; /* 23 */ 47*cc8875d1SJohn Floren u8 memory_planes; /* 24 */ 48*cc8875d1SJohn Floren u8 bpp; /* 25 */ 49*cc8875d1SJohn Floren u8 banks; /* 26 */ 50*cc8875d1SJohn Floren u8 memory_layout; /* 27 */ 51*cc8875d1SJohn Floren u8 bank_size; /* 28 */ 52*cc8875d1SJohn Floren u8 image_planes; /* 29 */ 53*cc8875d1SJohn Floren u8 page_function; /* 30 */ 54*cc8875d1SJohn Floren 55*cc8875d1SJohn Floren u8 rmask; /* 31 */ 56*cc8875d1SJohn Floren u8 rpos; /* 32 */ 57*cc8875d1SJohn Floren u8 gmask; /* 33 */ 58*cc8875d1SJohn Floren u8 gpos; /* 34 */ 59*cc8875d1SJohn Floren u8 bmask; /* 35 */ 60*cc8875d1SJohn Floren u8 bpos; /* 36 */ 61*cc8875d1SJohn Floren u8 resv_mask; /* 37 */ 62*cc8875d1SJohn Floren u8 resv_pos; /* 38 */ 63*cc8875d1SJohn Floren u8 dcm_info; /* 39 */ 64*cc8875d1SJohn Floren 65*cc8875d1SJohn Floren u32 lfb_ptr; /* 40 Linear frame buffer address */ 66*cc8875d1SJohn Floren u32 offscreen_ptr; /* 44 Offscreen memory address */ 67*cc8875d1SJohn Floren u16 offscreen_size; /* 48 */ 68*cc8875d1SJohn Floren 69*cc8875d1SJohn Floren u8 reserved[206]; /* 50 */ 70*cc8875d1SJohn Floren }; 71*cc8875d1SJohn Floren 72*cc8875d1SJohn Floren char oemstring[11] = "KVM VESA"; 73*cc8875d1SJohn Floren u16 modes[2] = { 0x0112, 0xffff }; 74*cc8875d1SJohn Floren 75*cc8875d1SJohn Floren static inline void outb(unsigned short port, unsigned char val) 76*cc8875d1SJohn Floren { 77*cc8875d1SJohn Floren asm volatile("outb %0, %1" : : "a"(val), "Nd"(port)); 78*cc8875d1SJohn Floren } 79*cc8875d1SJohn Floren 80*cc8875d1SJohn Floren /* 81*cc8875d1SJohn Floren * It's probably much more useful to make this print to the serial 82*cc8875d1SJohn Floren * line rather than print to a non-displayed VGA memory 83*cc8875d1SJohn Floren */ 84*cc8875d1SJohn Floren static inline void int10_putchar(struct int10_args *args) 85*cc8875d1SJohn Floren { 86*cc8875d1SJohn Floren u8 al, ah; 87*cc8875d1SJohn Floren 88*cc8875d1SJohn Floren al = args->eax & 0xFF; 89*cc8875d1SJohn Floren ah = (args->eax & 0xFF00) >> 8; 90*cc8875d1SJohn Floren 91*cc8875d1SJohn Floren outb(0x3f8, al); 92*cc8875d1SJohn Floren } 93*cc8875d1SJohn Floren 94*cc8875d1SJohn Floren static void int10_vesa(struct int10_args *args) 95*cc8875d1SJohn Floren { 96*cc8875d1SJohn Floren u8 al, ah; 97*cc8875d1SJohn Floren struct vesa_general_info *destination; 98*cc8875d1SJohn Floren struct vminfo *vi; 99*cc8875d1SJohn Floren 100*cc8875d1SJohn Floren al = args->eax; 101*cc8875d1SJohn Floren ah = args->eax >> 8; 102*cc8875d1SJohn Floren 103*cc8875d1SJohn Floren switch (al) { 104*cc8875d1SJohn Floren case 0: 105*cc8875d1SJohn Floren /* Set controller info */ 106*cc8875d1SJohn Floren 107*cc8875d1SJohn Floren destination = (struct vesa_general_info *)args->edi; 108*cc8875d1SJohn Floren *destination = (struct vesa_general_info) { 109*cc8875d1SJohn Floren .signature = VESA_MAGIC, 110*cc8875d1SJohn Floren .version = 0x102, 111*cc8875d1SJohn Floren .vendor_string = oemstring, 112*cc8875d1SJohn Floren .capabilities = 0x10, 113*cc8875d1SJohn Floren .video_mode_ptr = modes, 114*cc8875d1SJohn Floren .total_memory = (4*VESA_WIDTH * VESA_HEIGHT) / 0x10000, 115*cc8875d1SJohn Floren }; 116*cc8875d1SJohn Floren 117*cc8875d1SJohn Floren break; 118*cc8875d1SJohn Floren case 1: 119*cc8875d1SJohn Floren vi = (struct vminfo *)args->edi; 120*cc8875d1SJohn Floren *vi = (struct vminfo) { 121*cc8875d1SJohn Floren .mode_attr = 0xd9, /* 11011011 */ 122*cc8875d1SJohn Floren .logical_scan = VESA_WIDTH*4, 123*cc8875d1SJohn Floren .h_res = VESA_WIDTH, 124*cc8875d1SJohn Floren .v_res = VESA_HEIGHT, 125*cc8875d1SJohn Floren .bpp = VESA_BPP, 126*cc8875d1SJohn Floren .memory_layout = 6, 127*cc8875d1SJohn Floren .memory_planes = 1, 128*cc8875d1SJohn Floren .lfb_ptr = VESA_MEM_ADDR, 129*cc8875d1SJohn Floren .rmask = 8, 130*cc8875d1SJohn Floren .gmask = 8, 131*cc8875d1SJohn Floren .bmask = 8, 132*cc8875d1SJohn Floren .resv_mask = 8, 133*cc8875d1SJohn Floren .resv_pos = 24, 134*cc8875d1SJohn Floren .bpos = 16, 135*cc8875d1SJohn Floren .gpos = 8, 136*cc8875d1SJohn Floren }; 137*cc8875d1SJohn Floren 138*cc8875d1SJohn Floren break; 139*cc8875d1SJohn Floren } 140*cc8875d1SJohn Floren 141*cc8875d1SJohn Floren args->eax = 0x004f; /* return success every time */ 142*cc8875d1SJohn Floren 143*cc8875d1SJohn Floren } 144*cc8875d1SJohn Floren 145*cc8875d1SJohn Floren bioscall void int10_handler(struct int10_args *args) 146*cc8875d1SJohn Floren { 147*cc8875d1SJohn Floren u8 ah; 148*cc8875d1SJohn Floren 149*cc8875d1SJohn Floren ah = (args->eax & 0xff00) >> 8; 150*cc8875d1SJohn Floren 151*cc8875d1SJohn Floren switch (ah) { 152*cc8875d1SJohn Floren case 0x0e: 153*cc8875d1SJohn Floren int10_putchar(args); 154*cc8875d1SJohn Floren break; 155*cc8875d1SJohn Floren case 0x4f: 156*cc8875d1SJohn Floren int10_vesa(args); 157*cc8875d1SJohn Floren break; 158*cc8875d1SJohn Floren } 159*cc8875d1SJohn Floren 160*cc8875d1SJohn Floren } 161