xref: /haiku/src/add-ons/kernel/drivers/graphics/radeon/bios.c (revision 93aeb8c3bc3f13cb1f282e3e749258a23790d947)
1 /*
2 	Copyright (c) 2002, Thomas Kurschel
3 
4 
5 	Part of Radeon kernel driver
6 
7 	BIOS detection and retrieval of vital data
8 
9 	Most of this data should be gathered directly,
10 	especially monitor detection should be done on
11 	demand so not all monitors need to be connected
12 	during boot
13 */
14 
15 #include "radeon_driver.h"
16 #include "mmio.h"
17 #include "bios_regs.h"
18 #include "config_regs.h"
19 #include "memcntrl_regs.h"
20 #include "fp_regs.h"
21 #include "crtc_regs.h"
22 #include "radeon_bios.h"
23 #include "utils.h"
24 
25 #include <stdio.h>
26 #include <string.h>
27 
28 static const char ati_rom_sig[] = "761295520";
29 static const char *radeon_sig[] = {
30 	"RADEON",		// r100
31 	"RV100",		// rv100
32 	"U1",			// rs100 (IGP320M)
33 	"M6",			// mobile version of r100
34 	// probably an M6P;
35 	// anyway - this is the card I wrote this driver for!
36 	// (perhaps ATI tries to make the card incompatible to standard drivers)
37 	"P6",
38 	"RV200",		// rv200
39 	"M7",			// m7
40 	"RG6",			// r200 (according to spec)
41 	"RS200",		// rs200
42 	"R200",			// r200 (8500 LE)
43 	"R200AGP",		// Fire GL E1
44 	"M9"			// guess: m9
45 	"RV250",		// rv250 R9100
46 	"V280",			// RV280 R9200
47 	"R300",			// R300 R9500 / R9700
48 	"R350",			// R350 R9800
49 	"R360",			// R360 R9800 XT
50 	"V350",			// RV350 R9600
51 	"V360",			// RV350 R9600 XT :guess
52 };
53 
54 
55 // find address of ROM;
56 // this code is really nasty as maintaining the radeon signatures
57 // is almost impossible (the signatures provided by ATI are always out-dated);
58 // further, if there is more then one card built into the computer, we
59 // may detect the wrong BIOS!
60 // we have two possible solutions:
61 // 1. use the PCI location as stored in BIOS
62 // 2. verify the IO-base address as stored in BIOS
63 // I have no clue how these values are _written_ into the BIOS, and
64 // unfortunately, every BIOS does the detection in a different way,
65 // so I'm not sure which is the _right_ way of doing it
66 static char *Radeon_FindRom( rom_info *ri )
67 {
68 	uint32 segstart;
69 	uint8 *rom_base;
70 	char *rom;
71 	int i,j;
72 
73 	for( segstart = 0x000c0000; segstart < 0x000f0000; segstart += 0x00001000 ) {
74 		bool found = false;
75 
76 		// find ROM
77 		rom_base = ri->bios_ptr + segstart - 0xc0000;
78 
79 		if( rom_base[0] != 0x55 || rom_base[1] != 0xaa )
80 			continue;
81 
82 		// find signature of ATI
83 		rom = rom_base;
84 
85 		found = false;
86 
87 		for( i = 0; i < 128 - strlen( ati_rom_sig ); i++ ) {
88 			if( ati_rom_sig[0] == rom_base[i] ) {
89 				if( strncmp(ati_rom_sig, rom_base + i, strlen( ati_rom_sig )) == 0 ) {
90 					found = true;
91 					break;
92 				}
93 			}
94 		}
95 
96 		if( !found )
97 			continue;
98 
99 		// find signature of card
100 		found = false;
101 
102 		for( i = 0; i < 512; i++ ) {
103 			for( j = 0; j < sizeof( radeon_sig ) / sizeof( radeon_sig[0] ); j++ ) {
104 				if( radeon_sig[j][0] == rom_base[i] ) {
105 					if( strncmp( radeon_sig[j], rom_base + i, strlen( radeon_sig[j] )) == 0 ) {
106 						SHOW_INFO( 2, "Signature: %s", radeon_sig[j] );
107 						found = true;
108 						break;
109 					}
110 				}
111 			}
112 		}
113 
114 		if( !found )
115 			continue;
116 
117 		SHOW_INFO( 2, "found ROM @0x%lx", segstart );
118 		return rom_base;
119 	}
120 
121 	SHOW_INFO0( 2, "no ROM found" );
122 	return NULL;
123 }
124 
125 
126 // PLL info is stored in ROM, probably it's too easy to replace it
127 // and thus they produce cards with different timings
128 static void Radeon_GetPLLInfo( device_info *di )
129 {
130 	uint8 *bios_header;
131 	PLL_BLOCK pll, *pll_info;
132 
133 	bios_header = di->rom.rom_ptr + *(uint16 *)(di->rom.rom_ptr + 0x48);
134 	pll_info = (PLL_BLOCK *)(di->rom.rom_ptr + *(uint16 *)(bios_header + 0x30));
135 
136 	memcpy( &pll, pll_info, sizeof( pll ));
137 
138 	di->pll.xclk = (uint32)pll.XCLK;
139 	di->pll.ref_freq = (uint32)pll.PCLK_ref_freq;
140 	di->pll.ref_div = (uint32)pll.PCLK_ref_divider;
141 	di->pll.min_pll_freq = pll.PCLK_min_freq;
142 	di->pll.max_pll_freq = pll.PCLK_max_freq;
143 
144 	SHOW_INFO( 2, "ref_clk=%ld, ref_div=%ld, xclk=%ld, min_freq=%ld, max_freq=%ld from BIOS",
145 		di->pll.ref_freq, di->pll.ref_div, di->pll.xclk,
146 		di->pll.min_pll_freq, di->pll.max_pll_freq );
147 }
148 
149 /*
150 const char *Mon2Str[] = {
151 	"N/C",
152 	"CRT",
153 	"CRT",
154 	"Laptop flatpanel",
155 	"DVI (flatpanel)",
156 	"secondary DVI (flatpanel) - unsupported",
157 	"Composite TV",
158 	"S-Video out"
159 };*/
160 
161 /*
162 // ask BIOS what kind of monitor is connected to each port
163 static void Radeon_GetMonType( device_info *di )
164 {
165 	unsigned int tmp;
166 
167 	SHOW_FLOW0( 3, "" );
168 
169 	di->disp_type[0] = di->disp_type[1] = dt_none;
170 
171 	if (di->has_crtc2) {
172 		tmp = INREG( di->regs, RADEON_BIOS_4_SCRATCH );
173 
174 		// ordering of "if"s is important as multiple
175 		// devices can be concurrently connected to one port
176 		// (like both a CRT and a TV)
177 
178 		// primary port
179 		// having flat-panel support is most important
180 		if (tmp & 0x08)
181 			di->disp_type[0] = dt_dvi;
182 		else if (tmp & 0x4)
183 			di->disp_type[0] = dt_lvds;
184 		else if (tmp & 0x200)
185 			di->disp_type[0] = dt_tv_crt;
186 		else if (tmp & 0x10)
187 			di->disp_type[0] = dt_ctv;
188 		else if (tmp & 0x20)
189 			di->disp_type[0] = dt_stv;
190 
191 		// secondary port
192 		// having TV-Out support is more important then CRT support
193 		// (CRT gets signal anyway)
194 		if (tmp & 0x1000)
195 			di->disp_type[1] = dt_ctv;
196 		else if (tmp & 0x2000)
197 			di->disp_type[1] = dt_stv;
198 		else if (tmp & 0x2)
199 			di->disp_type[1] = dt_crt;
200 		else if (tmp & 0x800)
201 			di->disp_type[1] = dt_dvi_ext;
202 		else if (tmp & 0x400)
203 			// this is unlikely - I only know about one LVDS unit
204 			di->disp_type[1] = dt_lvds;
205 	} else {
206 		// regular Radeon
207 		// TBD: no TV-Out detection
208 		di->disp_type[0] = dt_none;
209 
210 		tmp = INREG( di->regs, RADEON_FP_GEN_CNTL);
211 
212 		if( tmp & RADEON_FP_EN_TMDS )
213 			di->disp_type[0] = dt_dvi;
214 		else
215 			di->disp_type[0] = dt_crt;
216 	}
217 
218 	SHOW_INFO( 1, "BIOS reports %s on primary and %s on secondary port",
219 		Mon2Str[di->disp_type[0]], Mon2Str[di->disp_type[1]]);
220 
221 	// remove unsupported devices
222 	if( di->disp_type[0] >= dt_dvi_ext )
223 		di->disp_type[0] = dt_none;
224 	if( di->disp_type[1] >= dt_dvi_ext )
225 		di->disp_type[1] = dt_none;
226 
227 	// HACK: overlays can only be shown on first CRTC;
228 	// if there's nothing on first port, connect
229 	// second port to first CRTC (proper signal routing
230 	// is hopefully done by BIOS)
231 	if( di->has_crtc2 ) {
232 		if( di->disp_type[0] == dt_none && di->disp_type[1] == dt_crt ) {
233 			di->disp_type[0] = dt_crt;
234 			di->disp_type[1] = dt_none;
235 		}
236 	}
237 
238 	SHOW_INFO( 1, "Effective routing: %s on primary and %s on secondary port",
239 		Mon2Str[di->disp_type[0]], Mon2Str[di->disp_type[1]]);
240 }
241 */
242 
243 // get flat panel info (does only make sense for Laptops
244 // with integrated display, but looking for it doesn't hurt,
245 // who knows which strange kind of combination is out there?)
246 static bool Radeon_GetBIOSDFPInfo( device_info *di )
247 {
248 	uint8 *bios_header;
249 	uint16 fpi_offset;
250 	FPI_BLOCK fpi;
251 	char panel_name[30];
252 	int i;
253 
254 	bios_header = di->rom.rom_ptr + *(uint16 *)(di->rom.rom_ptr + 0x48);
255 
256 	fpi_offset = *(uint16 *)(bios_header + 0x40);
257 
258 	if( !fpi_offset ) {
259 		di->fp_info.panel_pwr_delay = 200;
260 		SHOW_ERROR0( 2, "No Panel Info Table found in BIOS" );
261 		return false;
262 	}
263 
264 	memcpy( &fpi, di->rom.rom_ptr + fpi_offset, sizeof( fpi ));
265 
266 	memcpy( panel_name, &fpi.name, sizeof( fpi.name ) );
267 	panel_name[sizeof( fpi.name )] = 0;
268 
269 	SHOW_INFO( 2, "Panel ID string: %s", panel_name );
270 
271 	di->fp_info.panel_xres = fpi.panel_xres;
272 	di->fp_info.panel_yres = fpi.panel_yres;
273 
274 	SHOW_INFO( 2, "Panel Size from BIOS: %dx%d",
275 		di->fp_info.panel_xres, di->fp_info.panel_yres);
276 
277 	di->fp_info.panel_pwr_delay = fpi.panel_pwr_delay;
278 	if( di->fp_info.panel_pwr_delay > 2000 || di->fp_info.panel_pwr_delay < 0 )
279 		di->fp_info.panel_pwr_delay = 2000;
280 
281 	// there might be multiple supported resolutions stored;
282 	// we are looking for native resolution
283 	for( i = 0; i < 20; ++i ) {
284 		uint16 fpi_timing_ofs;
285 		FPI_TIMING_BLOCK fpi_timing;
286 
287 		fpi_timing_ofs = fpi.fpi_timing_ofs[i];
288 
289 		if( fpi_timing_ofs == 0 )
290 			break;
291 
292 		memcpy( &fpi_timing, di->rom.rom_ptr + fpi_timing_ofs, sizeof( fpi_timing ));
293 
294 		if( fpi_timing.panel_xres != di->fp_info.panel_xres ||
295 			fpi_timing.panel_yres != di->fp_info.panel_yres )
296 			continue;
297 
298 		di->fp_info.h_blank = (fpi_timing.h_total - fpi_timing.h_display) * 8;
299 		// TBD: seems like upper four bits of hsync_start contain garbage
300 		di->fp_info.h_over_plus = ((fpi_timing.h_sync_start & 0xfff) - fpi_timing.h_display - 1) * 8;
301 		di->fp_info.h_sync_width = fpi_timing.h_sync_width * 8;
302 		di->fp_info.v_blank = fpi_timing.v_total - fpi_timing.v_display;
303 		di->fp_info.v_over_plus = (fpi_timing.v_sync & 0x7ff) - fpi_timing.v_display;
304 		di->fp_info.v_sync_width = (fpi_timing.v_sync & 0xf800) >> 11;
305 		di->fp_info.dot_clock = fpi_timing.dot_clock * 10;
306 		return true;
307 	}
308 
309 	SHOW_ERROR0( 2, "Radeon: couldn't get Panel Timing from BIOS" );
310 	return false;
311 }
312 
313 
314 // try to reverse engineer DFP specification from
315 // timing currently set up in graphics cards registers
316 // (effectively, we hope that BIOS has set it up correctly
317 //  and noone has messed registers up yet; let's pray)
318 static void Radeon_RevEnvDFPSize( device_info *di )
319 {
320 	vuint8 *regs = di->regs;
321 
322 	di->fp_info.panel_yres =
323 		((INREG( regs, RADEON_FP_VERT_STRETCH ) & RADEON_VERT_PANEL_SIZE)
324 		>> RADEON_VERT_PANEL_SIZE_SHIFT) + 1;
325 
326 	di->fp_info.panel_xres =
327 		(((INREG( regs, RADEON_FP_HORZ_STRETCH ) & RADEON_HORZ_PANEL_SIZE)
328 		>> RADEON_HORZ_PANEL_SIZE_SHIFT) + 1) * 8;
329 
330 	SHOW_INFO( 2, "detected panel size from registers: %dx%d",
331 		di->fp_info.panel_xres, di->fp_info.panel_yres);
332 }
333 
334 
335 // once more for getting precise timing
336 static void Radeon_RevEnvDFPTiming( device_info *di )
337 {
338 	vuint8 *regs = di->regs;
339 	uint32 r;
340 	uint16 a, b;
341 
342 
343 	r = INREG( regs, RADEON_FP_CRTC_H_TOTAL_DISP );
344 	// the magic "4" was found by trial and error and probably stems from fudge (see crtc.c)
345 	a = (r & RADEON_FP_CRTC_H_TOTAL_MASK)/* + 4*/;
346 	b = (r & RADEON_FP_CRTC_H_DISP_MASK) >> RADEON_FP_CRTC_H_DISP_SHIFT;
347 	di->fp_info.h_blank = (a - b) * 8;
348 
349 	SHOW_FLOW( 2, "h_total=%d, h_disp=%d", a * 8, b * 8 );
350 
351 	r = INREG( regs, RADEON_FP_H_SYNC_STRT_WID );
352 	di->fp_info.h_over_plus =
353 		((r & RADEON_FP_H_SYNC_STRT_CHAR_MASK)
354 			  	>> RADEON_FP_H_SYNC_STRT_CHAR_SHIFT) - b/* - 1*/;
355 	di->fp_info.h_over_plus *= 8;
356 	di->fp_info.h_sync_width =
357 		((r & RADEON_FP_H_SYNC_WID_MASK)
358 				>> RADEON_FP_H_SYNC_WID_SHIFT);
359 	// TBD: this seems to be wrong
360 	// (my BIOS tells 112, this calculation leads to 24!)
361 	di->fp_info.h_sync_width *= 8;
362 
363 	r = INREG( regs, RADEON_FP_CRTC_V_TOTAL_DISP );
364 	a = (r & RADEON_FP_CRTC_V_TOTAL_MASK)/* + 1*/;
365 	b = (r & RADEON_FP_CRTC_V_DISP_MASK) >> RADEON_FP_CRTC_V_DISP_SHIFT;
366 	di->fp_info.v_blank = a - b;
367 
368 	SHOW_FLOW( 2, "v_total=%d, v_disp=%d", a, b );
369 
370 	r = INREG( regs, RADEON_FP_V_SYNC_STRT_WID );
371 	di->fp_info.v_over_plus = (r & RADEON_FP_V_SYNC_STRT_MASK) - b;
372 	di->fp_info.v_sync_width = ((r & RADEON_FP_V_SYNC_WID_MASK)
373 		>> RADEON_FP_V_SYNC_WID_SHIFT)/* + 1*/;
374 
375 	// standard CRTC
376 	r = INREG( regs, RADEON_CRTC_H_TOTAL_DISP );
377 	a = (r & RADEON_CRTC_H_TOTAL);
378 	b = (r & RADEON_CRTC_H_DISP) >> RADEON_CRTC_H_DISP_SHIFT;
379 	di->fp_info.h_blank = (a - b) * 8;
380 
381 	SHOW_FLOW( 2, "h_total=%d, h_disp=%d", a * 8, b * 8 );
382 
383 	r = INREG( regs, RADEON_CRTC_H_SYNC_STRT_WID );
384 	di->fp_info.h_over_plus =
385 		((r & RADEON_CRTC_H_SYNC_STRT_CHAR)
386 			  	>> RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT) - b;
387 	di->fp_info.h_over_plus *= 8;
388 	di->fp_info.h_sync_width =
389 		((r & RADEON_CRTC_H_SYNC_WID)
390 				>> RADEON_CRTC_H_SYNC_WID_SHIFT);
391 	di->fp_info.h_sync_width *= 8;
392 
393 	r = INREG( regs, RADEON_CRTC_V_TOTAL_DISP );
394 	a = (r & RADEON_CRTC_V_TOTAL);
395 	b = (r & RADEON_CRTC_V_DISP) >> RADEON_CRTC_V_DISP_SHIFT;
396 	di->fp_info.v_blank = a - b;
397 
398 	SHOW_FLOW( 2, "v_total=%d, v_disp=%d", a, b );
399 
400 	r = INREG( regs, RADEON_CRTC_V_SYNC_STRT_WID );
401 	di->fp_info.v_over_plus = (r & RADEON_CRTC_V_SYNC_STRT) - b;
402 	di->fp_info.v_sync_width = ((r & RADEON_CRTC_V_SYNC_WID)
403 		>> RADEON_CRTC_V_SYNC_WID_SHIFT);
404 }
405 
406 
407 /*
408 // get everything in terms of monitors connected to the card
409 static void Radeon_GetBIOSMon( device_info *di )
410 {
411 	Radeon_GetMonType( di );
412 
413     // reset all Flat Panel Info;
414     // it gets filled out step by step, and this way we know what's still missing
415     memset( &di->fp_info, 0, sizeof( di->fp_info ));
416 
417     // we assume that the only fp port is combined with standard port 0
418 	di->fp_info.disp_type = di->disp_type[0];
419 
420 	if( di->is_mobility ) {
421 		// there is a flat panel - get info about it
422 		Radeon_GetBIOSDFPInfo( di );
423 
424 		// if BIOS doesn't know, ask the registers
425 		if( di->fp_info.panel_xres == 0 || di->fp_info.panel_yres == 0)
426 			Radeon_RevEnvDFPSize( di );
427 
428 		if( di->fp_info.h_blank == 0 || di->fp_info.v_blank == 0)
429 			Radeon_RevEnvDFPTiming( di );
430 
431 		SHOW_INFO( 2, "h_disp=%d, h_blank=%d, h_over_plus=%d, h_sync_width=%d",
432 			di->fp_info.panel_xres, di->fp_info.h_blank, di->fp_info.h_over_plus, di->fp_info.h_sync_width );
433 		SHOW_INFO( 2, "v_disp=%d, v_blank=%d, v_over_plus=%d, v_sync_width=%d",
434 			di->fp_info.panel_yres, di->fp_info.v_blank, di->fp_info.v_over_plus, di->fp_info.v_sync_width );
435 		SHOW_INFO( 2, "pixel_clock=%d", di->fp_info.dot_clock );
436 	}
437 }
438 */
439 
440 // get info about Laptop flat panel
441 static void Radeon_GetFPData( device_info *di )
442 {
443     // reset all Flat Panel Info;
444     // it gets filled out step by step, and this way we know what's still missing
445     memset( &di->fp_info, 0, sizeof( di->fp_info ));
446 
447 	// we only use BIOS for Laptop flat panels
448 	if( !di->is_mobility )
449 		return;
450 
451 	// ask BIOS about flat panel spec
452 	Radeon_GetBIOSDFPInfo( di );
453 
454 	// if BIOS doesn't know, ask the registers
455 	if( di->fp_info.panel_xres == 0 || di->fp_info.panel_yres == 0)
456 		Radeon_RevEnvDFPSize( di );
457 
458 	if( di->fp_info.h_blank == 0 || di->fp_info.v_blank == 0)
459 		Radeon_RevEnvDFPTiming( di );
460 
461 	SHOW_INFO( 2, "h_disp=%d, h_blank=%d, h_over_plus=%d, h_sync_width=%d",
462 		di->fp_info.panel_xres, di->fp_info.h_blank, di->fp_info.h_over_plus, di->fp_info.h_sync_width );
463 	SHOW_INFO( 2, "v_disp=%d, v_blank=%d, v_over_plus=%d, v_sync_width=%d",
464 		di->fp_info.panel_yres, di->fp_info.v_blank, di->fp_info.v_over_plus, di->fp_info.v_sync_width );
465 	SHOW_INFO( 2, "pixel_clock=%d", di->fp_info.dot_clock );
466 }
467 
468 // detect amount of graphics memory
469 static void Radeon_DetectRAM( device_info *di )
470 {
471 	vuint8 *regs = di->regs;
472 
473 	if( !di->is_igp	)
474 		di->local_mem_size = INREG( regs, RADEON_CONFIG_MEMSIZE ) & RADEON_CONFIG_MEMSIZE_MASK;
475 	else {
476 		uint32 tom;
477 
478 		tom = INREG( regs, RADEON_GC_NB_TOM );
479 		di->local_mem_size = ((tom >> 16) + 1 - (tom & 0xffff)) << 16;
480 	}
481 
482 	// some production boards of m6 will return 0 if it's 8 MB
483 	if( di->local_mem_size == 0 )
484 		di->local_mem_size = 8 * 1024 *1024;
485 
486 	switch( INREG( regs, RADEON_MEM_SDRAM_MODE_REG ) & RADEON_MEM_CFG_TYPE_MASK ) {
487 		case RADEON_MEM_CFG_SDR:
488 			// SDR SGRAM (2:1)
489 			strcpy(di->ram_type, "SDR SGRAM");
490 			di->ram.ml = 4;
491 			di->ram.MB = 4;
492 			di->ram.Trcd = 1;
493 			di->ram.Trp = 2;
494 			di->ram.Twr = 1;
495 			di->ram.CL = 2;
496 			di->ram.loop_latency = 16;
497 			di->ram.Rloop = 16;
498 			di->ram.Tr2w = 0;
499 			break;
500 
501 		case RADEON_MEM_CFG_DDR:
502 			// DDR SGRAM
503 			strcpy(di->ram_type, "DDR SGRAM");
504 			di->ram.ml = 4;
505 			di->ram.MB = 4;
506 			di->ram.Trcd = 3;
507 			di->ram.Trp = 3;
508 			di->ram.Twr = 2;
509 			di->ram.CL = 3;
510 			di->ram.Tr2w = 1;
511 			di->ram.loop_latency = 16;
512 			di->ram.Rloop = 16;
513 			break;
514 
515 		// only one bit, so there's no default
516 	}
517 
518 	SHOW_INFO( 1, "%ld MB %s found", di->local_mem_size / 1024 / 1024,
519 		di->ram_type );
520 
521 /*	if( di->local_mem_size > 64 * 1024 * 1024 ) {
522 		di->local_mem_size = 64 * 1024 * 1024;
523 
524 		SHOW_INFO0( 1, "restricted to 64 MB" );
525 	}*/
526 }
527 
528 
529 // map and verify card's BIOS to see whether this really is a Radeon
530 // (as we need BIOS for further info we have to make sure we use the right one)
531 status_t Radeon_MapBIOS( pci_info *pcii, rom_info *ri )
532 {
533 	char buffer[100];
534 
535 	sprintf(buffer, "%04X_%04X_%02X%02X%02X bios",
536 		pcii->vendor_id, pcii->device_id,
537 		pcii->bus, pcii->device, pcii->function);
538 
539 	// we only scan BIOS at legacy location in first MB;
540 	// using the PCI location would improve detection, especially
541 	// if multiple graphics cards are installed
542 	// BUT: BeOS uses the first graphics card it finds (sorted by
543 	// device name), thus you couldn't choose in BIOS which card
544 	// to use; checking the legacy location ensures that the card is
545 	// only detected if it's the primary card
546 	ri->phys_address = 0xc0000;
547 	ri->size = 0x40000;
548 
549 	ri->bios_area = map_physical_memory( buffer, (void *)ri->phys_address,
550 		ri->size, B_ANY_KERNEL_ADDRESS, B_READ_AREA, (void **)&ri->bios_ptr );
551 	if( ri->bios_area < 0 )
552 		return ri->bios_area;
553 
554 	ri->rom_ptr = Radeon_FindRom( ri );
555 
556 	// on success, adjust physical address to found ROM
557 	if( ri->rom_ptr != NULL )
558 		ri->phys_address += ri->rom_ptr - ri->bios_ptr;
559 
560 	return ri->rom_ptr != NULL ? B_OK : B_ERROR;
561 }
562 
563 
564 // unmap card's BIOS
565 void Radeon_UnmapBIOS( rom_info *ri )
566 {
567 	delete_area( ri->bios_area );
568 
569 	ri->bios_ptr = ri->rom_ptr = NULL;
570 }
571 
572 
573 // get everything valuable from BIOS (BIOS must be mapped)
574 status_t Radeon_ReadBIOSData( device_info *di )
575 {
576 	shared_info dummy_si;
577 	status_t result = B_OK;
578 
579 	// give Radeon_MapDevice something to play with
580 	di->si = &dummy_si;
581 
582 	// don't map frame buffer - we don't know its proper size yet!
583 	result = Radeon_MapDevice( di, true );
584 	if( result < 0 )
585 		goto err1;
586 
587 	Radeon_GetPLLInfo( di );
588 	Radeon_GetFPData( di );
589 	Radeon_DetectRAM( di );
590 
591 	Radeon_UnmapDevice( di );
592 
593 err1:
594 	di->si = NULL;
595 
596 	return result;
597 }
598