]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/hwinfo/src/int10/int10.c
Kleiner netter neuer Versuch.
[people/teissler/ipfire-2.x.git] / src / hwinfo / src / int10 / int10.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <stdarg.h>
6
7 #include "vbios.h"
8
9 #include "hd.h"
10 #include "hd_int.h"
11 #include "bios.h"
12
13 static unsigned segofs2addr(unsigned char *segofs);
14 static unsigned get_data(unsigned char *buf, unsigned buf_size, unsigned addr);
15 static void read_vbe_info(hd_data_t *hd_data, vbe_info_t *vbe, unsigned char *vbeinfo, unsigned cpuemu);
16
17 static hd_data_t *log_hd_data;
18 void log_err(char *format, ...) __attribute__ ((format (printf, 1, 2)));
19
20 void get_vbe_info(hd_data_t *hd_data, vbe_info_t *vbe)
21 {
22 int i;
23 unsigned char vbeinfo[0x200];
24 int ax, bx, cx;
25 unsigned cpuemu = hd_data->flags.cpuemu;
26
27 log_hd_data = hd_data;
28
29 if(InitInt10(hd_data, hd_data->pci_config_type)) {
30 ADD2LOG("VBE: Could not init Int10\n");
31 return;
32 }
33
34 memset(vbeinfo, 0, sizeof vbeinfo);
35 strcpy(vbeinfo, "VBE2");
36
37 PROGRESS(4, 1, "vbe info");
38
39 if(hd_probe_feature(hd_data, pr_cpuemu_debug)) cpuemu |= 2;
40
41 #ifdef __i386__
42 if(hd_data->flags.cpuemu)
43 #endif
44 ADD2LOG("vm86: using CPU emulation\n");
45
46 ax = 0x4f00; bx = 0; cx = 0;
47 i = CallInt10(&ax, &bx, &cx, vbeinfo, sizeof vbeinfo, cpuemu) & 0xffff;
48
49 if(i != 0x4f) {
50 ADD2LOG("VBE: Error (0x4f00): 0x%04x\n", i);
51 FreeInt10();
52 return;
53 }
54
55 if(hd_probe_feature(hd_data, pr_bios_fb)) {
56 PROGRESS(4, 2, "mode info");
57
58 read_vbe_info(hd_data, vbe, vbeinfo, cpuemu);
59 }
60
61 if(hd_probe_feature(hd_data, pr_bios_ddc)) {
62 PROGRESS(4, 3, "ddc info");
63
64 memset(vbeinfo, 0, sizeof vbeinfo);
65 ax = 0x4f15; bx = 1; cx = 0;
66 i = CallInt10(&ax, &bx, &cx, vbeinfo, sizeof vbeinfo, cpuemu) & 0xffff;
67
68 if(i != 0x4f) {
69 ADD2LOG("Error (0x4f15): 0x%04x\n", i);
70 } else {
71 vbe->ok = 1;
72 memcpy(vbe->ddc, vbeinfo, sizeof vbe->ddc);
73
74 ADD2LOG("edid record:\n");
75 for(i = 0; (unsigned) i < sizeof vbe->ddc; i += 0x10) {
76 ADD2LOG(" ");
77 hexdump(&hd_data->log, 1, 0x10, vbe->ddc + i);
78 ADD2LOG("\n");
79 }
80 }
81 }
82
83 if(hd_probe_feature(hd_data, pr_bios_mode)) {
84 PROGRESS(4, 4, "gfx mode");
85
86 ax = 0x4f03; bx = 0; cx = 0;
87 i = CallInt10(&ax, &bx, &cx, vbeinfo, sizeof vbeinfo, cpuemu) & 0xffff;
88
89 if(i != 0x4f) {
90 ADD2LOG("Error (0x4f03): 0x%04x\n", i);
91 } else {
92 vbe->current_mode = bx;
93 vbe->ok = 1;
94 }
95 }
96
97 FreeInt10();
98 }
99
100
101 unsigned segofs2addr(unsigned char *segofs)
102 {
103 return segofs[0] + (segofs[1] << 8) + (segofs[2] << 4)+ (segofs[3] << 12);
104 }
105
106
107 unsigned get_data(unsigned char *buf, unsigned buf_size, unsigned addr)
108 {
109 unsigned bufferaddr = 0x7e00;
110 unsigned len;
111
112 *buf = 0;
113 len = 0;
114
115 if(addr >= bufferaddr && addr < bufferaddr + 0x200) {
116 len = bufferaddr + 0x200 - addr;
117 if(len >= buf_size) len = buf_size - 1;
118 memcpy(buf, addr + (char *) 0, len);
119 }
120 else if(addr >= 0x0c0000 && addr < 0x100000) {
121 len = 0x100000 - addr;
122 if(len >= buf_size) len = buf_size - 1;
123 memcpy(buf, addr + (char *) 0, len);
124 }
125
126 buf[len] = 0;
127
128 return len;
129 }
130
131
132 void read_vbe_info(hd_data_t *hd_data, vbe_info_t *vbe, unsigned char *v, unsigned cpuemu)
133 {
134 unsigned char tmp[1024], s[64];
135 unsigned i, l, u;
136 unsigned modelist[0x100];
137 unsigned bpp, res_bpp, fb, clock;
138 vbe_mode_info_t *mi;
139 int ax, bx, cx;
140
141 vbe->ok = 1;
142
143 vbe->version = v[0x04] + (v[0x05] << 8);
144 vbe->oem_version = v[0x14] + (v[0x15] << 8);
145 vbe->memory = (v[0x12] + (v[0x13] << 8)) << 16;
146
147 ADD2LOG(
148 "version = %u.%u, oem version = %u.%u\n",
149 vbe->version >> 8, vbe->version & 0xff, vbe->oem_version >> 8, vbe->oem_version & 0xff
150 );
151
152 ADD2LOG("memory = %uk\n", vbe->memory >> 10);
153
154 l = get_data(tmp, sizeof tmp, u = segofs2addr(v + 0x06));
155 vbe->oem_name = canon_str(tmp, l);
156 ADD2LOG("oem name [0x%05x] = \"%s\"\n", u, vbe->oem_name);
157
158 l = get_data(tmp, sizeof tmp, u = segofs2addr(v + 0x16));
159 vbe->vendor_name = canon_str(tmp, l);
160 ADD2LOG("vendor name [0x%05x] = \"%s\"\n", u, vbe->vendor_name);
161
162 l = get_data(tmp, sizeof tmp, u = segofs2addr(v + 0x1a));
163 vbe->product_name = canon_str(tmp, l);
164 ADD2LOG("product name [0x%05x] = \"%s\"\n", u, vbe->product_name);
165
166 l = get_data(tmp, sizeof tmp, u = segofs2addr(v + 0x1e));
167 vbe->product_revision = canon_str(tmp, l);
168 ADD2LOG("product revision [0x%05x] = \"%s\"\n", u, vbe->product_revision);
169
170 l = get_data(tmp, sizeof tmp, u = segofs2addr(v + 0x0e)) >> 1;
171
172 for(i = vbe->modes = 0; i < l && i < sizeof modelist / sizeof *modelist; i++) {
173 u = tmp[2 * i] + (tmp[2 * i + 1] << 8);
174 if(u != 0xffff)
175 modelist[vbe->modes++] = u;
176 else
177 break;
178 }
179
180 ADD2LOG("%u video modes:\n", vbe->modes);
181
182 vbe->mode = new_mem(vbe->modes * sizeof *vbe->mode);
183
184 if(!vbe->mode) return;
185
186 for(i = 0; i < vbe->modes; i++) {
187
188 mi = vbe->mode + i;
189
190 mi->number = modelist[i];
191
192 ax = 0x4f01; bx = 0; cx = modelist[i];
193 l = CallInt10(&ax, &bx, &cx, tmp, sizeof tmp, cpuemu) & 0xffff;
194
195 if(l != 0x4f) {
196 ADD2LOG("0x%04x: no mode info\n", modelist[i]);
197 continue;
198 }
199
200 mi->attributes = tmp[0x00] + (tmp[0x01] << 8);
201
202 mi->width = tmp[0x12] + (tmp[0x13] << 8);
203 mi->height = tmp[0x14] + (tmp[0x15] << 8);
204 mi->bytes_p_line = tmp[0x10] + (tmp[0x11] << 8);
205
206 mi->win_A_start = (tmp[0x08] + (tmp[0x09] << 8)) << 4;
207 mi->win_B_start = (tmp[0x0a] + (tmp[0x0b] << 8)) << 4;
208
209 mi->win_A_attr = tmp[0x02];
210 mi->win_B_attr = tmp[0x03];
211
212 mi->win_gran = (tmp[0x04] + (tmp[0x05] << 8)) << 10;
213 mi->win_size = (tmp[0x06] + (tmp[0x07] << 8)) << 10;
214
215 bpp = res_bpp = 0;
216 switch(tmp[0x1b]) {
217 case 0:
218 bpp = -1;
219 break;
220
221 case 1:
222 bpp = 2;
223 break;
224
225 case 2:
226 bpp = 1;
227 break;
228
229 case 3:
230 bpp = 4;
231 break;
232
233 case 4:
234 bpp = 8;
235 break;
236
237 case 6:
238 bpp = tmp[0x19] - tmp[0x25];
239 res_bpp = tmp[0x25];
240 }
241
242 fb = 0;
243 if(vbe->version >= 0x0200) {
244 mi->fb_start = tmp[0x28] + (tmp[0x29] << 8) + (tmp[0x2a] << 16) + (tmp[0x2b] << 24);
245 }
246
247 clock = 0;
248 if(vbe->version >= 0x0300) {
249 mi->pixel_clock = tmp[0x3e] + (tmp[0x3f] << 8) + (tmp[0x40] << 16) + (tmp[0x41] << 24);
250 }
251
252 mi->pixel_size = bpp;
253
254 if(bpp == -1u) {
255 ADD2LOG(" 0x%04x[%02x]: %ux%u, text\n", mi->number, mi->attributes, mi->width, mi->height);
256 }
257 else {
258 if(
259 (mi->attributes & 1) && /* mode is supported */
260 mi->fb_start
261 ) {
262 if(!vbe->fb_start) vbe->fb_start = mi->fb_start;
263 }
264 *s = 0;
265 if(res_bpp) sprintf(s, "+%u", res_bpp);
266 ADD2LOG(
267 " 0x%04x[%02x]: %ux%u+%u, %u%s bpp",
268 mi->number, mi->attributes, mi->width, mi->height, mi->bytes_p_line, mi->pixel_size, s
269 );
270
271 if(mi->pixel_clock) ADD2LOG(", max. %u MHz", mi->pixel_clock/1000000);
272
273 if(mi->fb_start) ADD2LOG(", fb: 0x%08x", mi->fb_start);
274
275 ADD2LOG(", %04x.%x", mi->win_A_start, mi->win_A_attr);
276
277 if(mi->win_B_start || mi->win_B_attr) ADD2LOG("/%04x.%x", mi->win_B_start, mi->win_B_attr);
278
279 ADD2LOG(": %uk", mi->win_size >> 10);
280
281 if(mi->win_gran != mi->win_size) ADD2LOG("/%uk", mi->win_gran >> 10);
282
283 ADD2LOG("\n");
284 }
285 }
286
287 }
288
289 void log_err(char *format, ...)
290 {
291 va_list args;
292 char buf[1024];
293
294 va_start(args, format);
295 vsnprintf(buf, sizeof buf, format, args);
296 str_printf(&log_hd_data->log, -2, "%s", buf);
297 va_end(args);
298 }
299