1 // SPDX-License-Identifier: GPL-2.0-only 1 2 /* -*- linux-c -*- --------------------------- 3 * 4 * Copyright (C) 1991, 1992 Linus Torvalds 5 * Copyright 2007 rPath, Inc. - All Rights R 6 * Copyright 2009 Intel Corporation; author 7 * 8 * ------------------------------------------- 9 10 /* 11 * VESA text modes 12 */ 13 14 #include "boot.h" 15 #include "video.h" 16 #include "vesa.h" 17 #include "string.h" 18 19 /* VESA information */ 20 static struct vesa_general_info vginfo; 21 static struct vesa_mode_info vminfo; 22 23 static __videocard video_vesa; 24 25 #ifndef _WAKEUP 26 static void vesa_store_mode_params_graphics(vo 27 #else /* _WAKEUP */ 28 static inline void vesa_store_mode_params_grap 29 #endif /* _WAKEUP */ 30 31 static int vesa_probe(void) 32 { 33 struct biosregs ireg, oreg; 34 u16 mode; 35 addr_t mode_ptr; 36 struct mode_info *mi; 37 int nmodes = 0; 38 39 video_vesa.modes = GET_HEAP(struct mod 40 41 initregs(&ireg); 42 ireg.ax = 0x4f00; 43 ireg.di = (size_t)&vginfo; 44 intcall(0x10, &ireg, &oreg); 45 46 if (oreg.ax != 0x004f || 47 vginfo.signature != VESA_MAGIC || 48 vginfo.version < 0x0102) 49 return 0; /* Not present 50 51 set_fs(vginfo.video_mode_ptr.seg); 52 mode_ptr = vginfo.video_mode_ptr.off; 53 54 while ((mode = rdfs16(mode_ptr)) != 0x 55 mode_ptr += 2; 56 57 if (!heap_free(sizeof(struct m 58 break; /* Heap full, 59 60 if (mode & ~0x1ff) 61 continue; 62 63 memset(&vminfo, 0, sizeof(vmin 64 65 ireg.ax = 0x4f01; 66 ireg.cx = mode; 67 ireg.di = (size_t)&vminfo; 68 intcall(0x10, &ireg, &oreg); 69 70 if (oreg.ax != 0x004f) 71 continue; 72 73 if ((vminfo.mode_attr & 0x15) 74 /* Text Mode, TTY BIOS 75 supported by hardwa 76 mi = GET_HEAP(struct m 77 mi->mode = mode + VID 78 mi->depth = 0; /* text 79 mi->x = vminfo.h_r 80 mi->y = vminfo.v_r 81 nmodes++; 82 } else if ((vminfo.mode_attr & 83 (vminfo.memory_layo 84 vminfo.memory_layo 85 vminfo.memory_plane 86 #ifdef CONFIG_BOOT_VESA_SUPPORT 87 /* Graphics mode, colo 88 supported. Only re 89 if framebuffer is c 90 otherwise the user 91 mi = GET_HEAP(struct m 92 mi->mode = mode + VIDE 93 mi->depth = vminfo.bpp 94 mi->x = vminfo.h_res; 95 mi->y = vminfo.v_res; 96 nmodes++; 97 #endif 98 } 99 } 100 101 return nmodes; 102 } 103 104 static int vesa_set_mode(struct mode_info *mod 105 { 106 struct biosregs ireg, oreg; 107 int is_graphic; 108 u16 vesa_mode = mode->mode - VIDEO_FIR 109 110 memset(&vminfo, 0, sizeof(vminfo)); /* 111 112 initregs(&ireg); 113 ireg.ax = 0x4f01; 114 ireg.cx = vesa_mode; 115 ireg.di = (size_t)&vminfo; 116 intcall(0x10, &ireg, &oreg); 117 118 if (oreg.ax != 0x004f) 119 return -1; 120 121 if ((vminfo.mode_attr & 0x15) == 0x05) 122 /* It's a supported text mode 123 is_graphic = 0; 124 #ifdef CONFIG_BOOT_VESA_SUPPORT 125 } else if ((vminfo.mode_attr & 0x99) = 126 /* It's a graphics mode with l 127 is_graphic = 1; 128 vesa_mode |= 0x4000; /* Reques 129 #endif 130 } else { 131 return -1; /* Invalid mod 132 } 133 134 135 initregs(&ireg); 136 ireg.ax = 0x4f02; 137 ireg.bx = vesa_mode; 138 intcall(0x10, &ireg, &oreg); 139 140 if (oreg.ax != 0x004f) 141 return -1; 142 143 graphic_mode = is_graphic; 144 if (!is_graphic) { 145 /* Text mode */ 146 force_x = mode->x; 147 force_y = mode->y; 148 do_restore = 1; 149 } else { 150 /* Graphics mode */ 151 vesa_store_mode_params_graphic 152 } 153 154 return 0; 155 } 156 157 158 #ifndef _WAKEUP 159 160 /* Switch DAC to 8-bit mode */ 161 static void vesa_dac_set_8bits(void) 162 { 163 struct biosregs ireg, oreg; 164 u8 dac_size = 6; 165 166 /* If possible, switch the DAC to 8-bi 167 if (vginfo.capabilities & 1) { 168 initregs(&ireg); 169 ireg.ax = 0x4f08; 170 ireg.bh = 0x08; 171 intcall(0x10, &ireg, &oreg); 172 if (oreg.ax == 0x004f) 173 dac_size = oreg.bh; 174 } 175 176 /* Set the color sizes to the DAC size 177 boot_params.screen_info.red_size = d 178 boot_params.screen_info.green_size = d 179 boot_params.screen_info.blue_size = d 180 boot_params.screen_info.rsvd_size = d 181 182 boot_params.screen_info.red_pos = 0 183 boot_params.screen_info.green_pos = 0 184 boot_params.screen_info.blue_pos = 0 185 boot_params.screen_info.rsvd_pos = 0 186 } 187 188 /* Save the VESA protected mode info */ 189 static void vesa_store_pm_info(void) 190 { 191 struct biosregs ireg, oreg; 192 193 initregs(&ireg); 194 ireg.ax = 0x4f0a; 195 intcall(0x10, &ireg, &oreg); 196 197 if (oreg.ax != 0x004f) 198 return; 199 200 boot_params.screen_info.vesapm_seg = o 201 boot_params.screen_info.vesapm_off = o 202 } 203 204 /* 205 * Save video mode parameters for graphics mod 206 */ 207 static void vesa_store_mode_params_graphics(vo 208 { 209 /* Tell the kernel we're in VESA graph 210 boot_params.screen_info.orig_video_isV 211 212 /* Mode parameters */ 213 boot_params.screen_info.vesa_attribute 214 boot_params.screen_info.lfb_linelength 215 boot_params.screen_info.lfb_width = vm 216 boot_params.screen_info.lfb_height = v 217 boot_params.screen_info.lfb_depth = vm 218 boot_params.screen_info.pages = vminfo 219 boot_params.screen_info.lfb_base = vmi 220 memcpy(&boot_params.screen_info.red_si 221 &vminfo.rmask, 8); 222 223 /* General parameters */ 224 boot_params.screen_info.lfb_size = vgi 225 226 if (vminfo.bpp <= 8) 227 vesa_dac_set_8bits(); 228 229 vesa_store_pm_info(); 230 } 231 232 /* 233 * Save EDID information for the kernel; this 234 * after mode-setting. 235 */ 236 void vesa_store_edid(void) 237 { 238 #ifdef CONFIG_FIRMWARE_EDID 239 struct biosregs ireg, oreg; 240 241 /* Apparently used as a nonsense token 242 memset(&boot_params.edid_info, 0x13, s 243 244 if (vginfo.version < 0x0200) 245 return; /* EDID requir 246 247 initregs(&ireg); 248 ireg.ax = 0x4f15; /* VBE 249 /* ireg.bx = 0x0000; */ /* Rep 250 /* ireg.cx = 0; */ /* Con 251 ireg.es = 0; /* ES: 252 intcall(0x10, &ireg, &oreg); 253 254 if (oreg.ax != 0x004f) 255 return; /* No EDID */ 256 257 /* BH = time in seconds to transfer ED 258 /* BL = DDC level supported */ 259 260 ireg.ax = 0x4f15; /* VBE 261 ireg.bx = 0x0001; /* Rea 262 /* ireg.cx = 0; */ /* Con 263 /* ireg.dx = 0; */ /* EDI 264 ireg.es = ds(); 265 ireg.di =(size_t)&boot_params.edid_inf 266 intcall(0x10, &ireg, &oreg); 267 #endif /* CONFIG_FIRMWARE_EDID */ 268 } 269 270 #endif /* not _WAKEUP */ 271 272 static __videocard video_vesa = 273 { 274 .card_name = "VESA", 275 .probe = vesa_probe, 276 .set_mode = vesa_set_mode, 277 .xmode_first = VIDEO_FIRST_VESA, 278 .xmode_n = 0x200, 279 }; 280
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.