1 /*
2 * Copyright (c) 2002-2004, Thomas Kurschel
3 * Copyright (c) 2006-2007, Euan Kirkhope
4 *
5 * Distributed under the terms of the MIT license.
6 */
7
8 /*
9 Init and clean-up of devices
10
11 TODO: support for multiple virtual card per device is
12 not implemented yet - there is only one per device;
13 apart from additional device names, we need proper
14 management of graphics mem to not interfere.
15 */
16
17 #include "dac_regs.h"
18 #include "tv_out_regs.h"
19 #include "fp_regs.h"
20 #include "mmio.h"
21 #include "radeon_driver.h"
22
23 #include <PCI.h>
24
25 #include <stdio.h>
26 #include <string.h>
27
28 // helper macros for easier PCI access
29 #define get_pci(o, s) (*pci_bus->read_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s))
30 #define set_pci(o, s, v) (*pci_bus->write_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s), (v))
31
32 extern radeon_settings current_settings;
33
34 // map frame buffer and registers
35 // mmio_only - true = map registers only (used during detection)
Radeon_MapDevice(device_info * di,bool mmio_only)36 status_t Radeon_MapDevice( device_info *di, bool mmio_only )
37 {
38 // framebuffer is stored in PCI range 0,
39 // register map in PCI range 2
40 int regs = 2;
41 int fb = 0;
42 char buffer[100];
43 shared_info *si = di->si;
44 uint32 tmp;
45 pci_info *pcii = &(di->pcii);
46 status_t result;
47
48 SHOW_FLOW( 3, "device: %02X%02X%02X",
49 di->pcii.bus, di->pcii.device, di->pcii.function );
50
51 si->ROM_area = si->regs_area = si->memory[mt_local].area = 0;
52
53 // enable memory mapped IO and frame buffer
54 // also, enable bus mastering (some BIOSes seem to
55 // disable that, like mine)
56 tmp = get_pci( PCI_command, 2 );
57 SHOW_FLOW( 3, "old PCI command state: 0x%08" B_PRIx32, tmp );
58 tmp |= PCI_command_io | PCI_command_memory | PCI_command_master;
59 set_pci( PCI_command, 2, tmp );
60
61 // registers cannot be accessed directly by user apps,
62 // they need to clone area for safety reasons
63 SHOW_INFO( 1,
64 "physical address of memory-mapped I/O: 0x%8" B_PRIx32 "-0x%8" B_PRIx32,
65 di->pcii.u.h0.base_registers[regs],
66 di->pcii.u.h0.base_registers[regs] + di->pcii.u.h0.base_register_sizes[regs] - 1 );
67
68 sprintf( buffer, "%04X_%04X_%02X%02X%02X regs",
69 di->pcii.vendor_id, di->pcii.device_id,
70 di->pcii.bus, di->pcii.device, di->pcii.function );
71
72 si->regs_area = map_physical_memory(
73 buffer,
74 di->pcii.u.h0.base_registers[regs],
75 di->pcii.u.h0.base_register_sizes[regs],
76 B_ANY_KERNEL_ADDRESS,
77 /*// for "poke" debugging
78 B_READ_AREA + B_WRITE_AREA*/
79 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_CLONEABLE_AREA,
80 (void **)&(di->regs));
81 if( si->regs_area < 0 )
82 return si->regs_area;
83
84 // that's all during detection as we have no clue about ROM or
85 // frame buffer at this point
86 if( mmio_only )
87 return B_OK;
88
89 // ROM must be explicetely mapped by applications too
90 sprintf( buffer, "%04X_%04X_%02X%02X%02X ROM",
91 di->pcii.vendor_id, di->pcii.device_id,
92 di->pcii.bus, di->pcii.device, di->pcii.function );
93
94 si->ROM_area = map_physical_memory(
95 buffer,
96 di->rom.phys_address,
97 di->rom.size,
98 B_ANY_KERNEL_ADDRESS,
99 0,
100 (void **)&(di->rom.rom_ptr));
101 if( si->ROM_area < 0 ) {
102 result = si->ROM_area;
103 goto err2;
104 }
105
106 if( di->pcii.u.h0.base_register_sizes[fb] > di->local_mem_size ) {
107 // Radeons allocate more address range then really needed ->
108 // only map the area that contains physical memory
109 SHOW_INFO( 1,
110 "restrict frame buffer from 0x%8" B_PRIx32
111 " to 0x%8" B_PRIx32 " bytes",
112 di->pcii.u.h0.base_register_sizes[fb],
113 di->local_mem_size
114 );
115 di->pcii.u.h0.base_register_sizes[fb] = di->local_mem_size;
116 }
117
118 // framebuffer can be accessed by everyone
119 // this is not a perfect solution; preferably, only
120 // those areas owned by an application are mapped into
121 // its address space
122 // (this hack is needed by BeOS to write something onto screen in KDL)
123 SHOW_INFO( 1,
124 "physical address of framebuffer: 0x%8" B_PRIx32 "-0x%8" B_PRIx32,
125 di->pcii.u.h0.base_registers[fb],
126 di->pcii.u.h0.base_registers[fb] + di->pcii.u.h0.base_register_sizes[fb] - 1 );
127
128 sprintf(buffer, "%04X_%04X_%02X%02X%02X framebuffer",
129 di->pcii.vendor_id, di->pcii.device_id,
130 di->pcii.bus, di->pcii.device, di->pcii.function);
131
132 si->memory[mt_local].area = map_physical_memory(
133 buffer,
134 di->pcii.u.h0.base_registers[fb],
135 di->pcii.u.h0.base_register_sizes[fb],
136 B_ANY_KERNEL_BLOCK_ADDRESS | B_WRITE_COMBINING_MEMORY,
137 B_READ_AREA | B_WRITE_AREA | B_CLONEABLE_AREA,
138 (void **)&(si->local_mem));
139
140 if( si->memory[mt_local].area < 0 ) {
141 SHOW_FLOW0( 3, "couldn't enable WC for frame buffer" );
142 si->memory[mt_local].area = map_physical_memory(
143 buffer,
144 di->pcii.u.h0.base_registers[fb],
145 di->pcii.u.h0.base_register_sizes[fb],
146 B_ANY_KERNEL_BLOCK_ADDRESS,
147 B_READ_AREA | B_WRITE_AREA | B_CLONEABLE_AREA,
148 (void **)&(si->local_mem));
149 }
150
151 SHOW_FLOW( 3, "mapped frame buffer @%p", si->local_mem );
152
153 if( si->memory[mt_local].area < 0 ) {
154 result = si->memory[mt_local].area;
155 goto err;
156 }
157
158 // save physical address though noone can probably make
159 // any use of it
160 si->framebuffer_pci = (void *) di->pcii.u.h0.base_registers_pci[fb];
161
162 return B_OK;
163
164 err:
165 delete_area( si->ROM_area );
166 err2:
167 delete_area( si->regs_area );
168 return result;
169 }
170
171
172 // unmap PCI ranges
Radeon_UnmapDevice(device_info * di)173 void Radeon_UnmapDevice(device_info *di)
174 {
175 shared_info *si = di->si;
176 pci_info *pcii = &(di->pcii);
177 uint32 tmp;
178
179 SHOW_FLOW0( 3, "" );
180
181 // disable PCI ranges (though it probably won't
182 // hurt leaving them enabled)
183 tmp = get_pci( PCI_command, 2 );
184 tmp &= ~PCI_command_io | PCI_command_memory | PCI_command_master;
185 set_pci( PCI_command, 2, tmp );
186
187 if( si->regs_area > 0 )
188 delete_area( si->regs_area );
189
190 if( si->ROM_area > 0 )
191 delete_area( si->ROM_area );
192
193 if( si->memory[mt_local].area > 0 )
194 delete_area( si->memory[mt_local].area );
195
196 si->regs_area = si->ROM_area = si->memory[mt_local].area = 0;
197 }
198
199
200 // initialize shared infos on first open
Radeon_FirstOpen(device_info * di)201 status_t Radeon_FirstOpen( device_info *di )
202 {
203 status_t result;
204 char buffer[100]; // B_OS_NAME_LENGTH is too short
205 shared_info *si;
206 //uint32 /*dma_block, */dma_offset;
207
208 // create shared info; don't allow access by apps -
209 // they'll clone it
210 sprintf( buffer, "%04X_%04X_%02X%02X%02X shared",
211 di->pcii.vendor_id, di->pcii.device_id,
212 di->pcii.bus, di->pcii.device, di->pcii.function );
213
214 di->shared_area = create_area(
215 buffer,
216 (void **)&(di->si),
217 B_ANY_KERNEL_ADDRESS,
218 (sizeof(shared_info) + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1),
219 B_FULL_LOCK,
220 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_CLONEABLE_AREA);
221 if (di->shared_area < 0) {
222 result = di->shared_area;
223 goto err8;
224 }
225
226 memset( di->si, 0, sizeof( *di->si ));
227
228 si = di->si;
229
230 si->settings = di->settings = current_settings;
231
232 if (di->settings.force_acc_dma)
233 di->acc_dma = true;
234 if (di->settings.force_acc_mmio) // force mmio will override dma... a tristate fuzzylogic, grey bool would be nice...
235 di->acc_dma = false;
236
237 #ifdef ENABLE_LOGGING
238 #ifdef LOG_INCLUDE_STARTUP
239 si->log = log_init( 1000000 );
240 #endif
241 #endif
242
243 // copy all info into shared info
244 si->vendor_id = di->pcii.vendor_id;
245 si->device_id = di->pcii.device_id;
246 si->revision = di->pcii.revision;
247
248 si->asic = di->asic;
249 si->is_mobility = di->is_mobility;
250 si->tv_chip = di->tv_chip;
251 si->new_pll = di->new_pll;
252 si->is_igp = di->is_igp;
253 si->has_no_i2c = di->has_no_i2c;
254 si->is_atombios = di->is_atombios;
255 si->is_mobility = di->is_mobility;
256 si->panel_pwr_delay = di->si->panel_pwr_delay;
257 si->acc_dma = di->acc_dma;
258
259 memcpy(&si->routing, &di->routing, sizeof(disp_entity));
260
261 // detecting theatre channel in kernel would lead to code duplication,
262 // so we let the first accelerant take care of it
263 si->theatre_channel = -1;
264
265 si->crtc[0].crtc_idx = 0;
266 si->crtc[0].flatpanel_port = 0;
267 si->crtc[1].crtc_idx = 1;
268 si->crtc[1].flatpanel_port = 1;
269 si->num_crtc = di->num_crtc;
270
271 if (di->is_mobility)
272 si->flatpanels[0] = di->fp_info;
273
274 si->pll = di->pll;
275
276 // create virtual card info; don't allow access by apps -
277 // they'll clone it
278 sprintf( buffer, "%04X_%04X_%02X%02X%02X virtual card 0",
279 di->pcii.vendor_id, di->pcii.device_id,
280 di->pcii.bus, di->pcii.device, di->pcii.function );
281 di->virtual_card_area = create_area(
282 buffer,
283 (void **)&(di->vc),
284 B_ANY_KERNEL_ADDRESS,
285 (sizeof(virtual_card) + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1),
286 B_FULL_LOCK,
287 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_CLONEABLE_AREA);
288 if (di->virtual_card_area < 0) {
289 result = di->virtual_card_area;
290 goto err7;
291 }
292
293 // currently, we assign fixed ports to this virtual card
294 di->vc->assigned_crtc[0] = true;
295 di->vc->assigned_crtc[1] = si->num_crtc > 1;
296 di->vc->controlled_displays =
297 dd_tv_crt | dd_crt | dd_lvds | dd_dvi | dd_dvi_ext | dd_ctv | dd_stv;
298
299 di->vc->fb_mem_handle = 0;
300 di->vc->cursor.mem_handle = 0;
301
302 // create unique id
303 di->vc->id = di->virtual_card_area;
304
305 result = Radeon_MapDevice( di, false );
306 if (result < 0)
307 goto err6;
308
309 // save dac2_cntl register
310 // on M6, we need to restore that during uninit, else you only get
311 // garbage on screen on reboot if both CRTCs are used
312 if( di->asic == rt_rv100 && di->is_mobility)
313 di->dac2_cntl = INREG( di->regs, RADEON_DAC_CNTL2 );
314
315 memcpy(&si->tmds_pll, &di->tmds_pll, sizeof(di->tmds_pll));
316 si->tmds_pll_cntl = INREG( di->regs, RADEON_TMDS_PLL_CNTL);
317 si->tmds_transmitter_cntl = INREG( di->regs, RADEON_TMDS_TRANSMITTER_CNTL);
318
319 // print these out to capture bios status...
320 // if ( di->is_mobility ) {
321 SHOW_INFO0( 2, "Copy of Laptop Display Regs for Reference:");
322 SHOW_INFO( 2, "LVDS GEN = %8" B_PRIx32,
323 INREG( di->regs, RADEON_LVDS_GEN_CNTL ));
324 SHOW_INFO( 2, "LVDS PLL = %8" B_PRIx32,
325 INREG( di->regs, RADEON_LVDS_PLL_CNTL ));
326 SHOW_INFO( 2, "TMDS PLL = %8" B_PRIx32,
327 INREG( di->regs, RADEON_TMDS_PLL_CNTL ));
328 SHOW_INFO( 2, "TMDS TRANS = %8" B_PRIx32,
329 INREG( di->regs, RADEON_TMDS_TRANSMITTER_CNTL ));
330 SHOW_INFO( 2, "FP1 GEN = %8" B_PRIx32,
331 INREG( di->regs, RADEON_FP_GEN_CNTL ));
332 SHOW_INFO( 2, "FP2 GEN = %8" B_PRIx32 ,
333 INREG( di->regs, RADEON_FP2_GEN_CNTL ));
334 SHOW_INFO( 2, "TV DAC = %8" B_PRIx32 ,
335 INREG( di->regs, RADEON_TV_DAC_CNTL )); //not setup right when ext dvi
336 // }
337
338 result = Radeon_InitPCIGART( di );
339 if( result < 0 )
340 goto err5;
341
342 si->memory[mt_local].size = di->local_mem_size;
343
344 si->memory[mt_PCI].area = di->pci_gart.buffer.area;
345 si->memory[mt_PCI].size = di->pci_gart.buffer.size;
346
347 // currently, defaultnon-local memory is PCI memory
348 si->nonlocal_type = mt_PCI;
349
350 Radeon_InitMemController( di );
351
352 // currently, we don't support VBI - something is broken there
353 // (it doesn't change a thing apart from crashing)
354 result = Radeon_SetupIRQ( di, buffer );
355 if( result < 0 )
356 goto err4;
357
358 // resolution of 2D register is 1K, resolution of CRTC etc. is higher,
359 // so 1K is the minimum block size;
360 // (CP cannot use local mem)
361 di->memmgr[mt_local] = mem_init("radeon local memory", 0, di->local_mem_size, 1024,
362 di->local_mem_size / 1024);
363 if (di->memmgr[mt_local] == NULL) {
364 result = B_NO_MEMORY;
365 goto err3;
366 }
367
368 // CP requires 4K alignment, which is the most restrictive I found
369 di->memmgr[mt_PCI] = mem_init("radeon PCI GART memory", 0, di->pci_gart.buffer.size, 4096,
370 di->pci_gart.buffer.size / 4096);
371 if (di->memmgr[mt_PCI] == NULL) {
372 result = B_NO_MEMORY;
373 goto err2;
374 }
375
376 // no AGP support
377 di->memmgr[mt_AGP] = NULL;
378
379 // fix AGP settings for IGP chipset
380 Radeon_Set_AGP( di, !di->settings.force_pci ); // disable AGP
381
382
383 // time to init Command Processor
384 result = Radeon_InitCP( di );
385 if( result != B_OK )
386 goto err;
387
388 if ( di->acc_dma )
389 {
390 result = Radeon_InitDMA( di );
391 if( result != B_OK )
392 goto err0;
393 }
394 else
395 {
396 SHOW_INFO0( 0, "DMA is diabled using PIO mode");
397 }
398
399 // mem_alloc( di->local_memmgr, 0x100000, (void *)-1, &dma_block, &dma_offset );
400 /* dma_offset = 15 * 1024 * 1024;
401
402 si->nonlocal_mem = (uint32 *)((uint32)si->framebuffer + dma_offset);
403 si->nonlocal_vm_start = (uint32)si->framebuffer_pci + dma_offset;*/
404
405 // set dynamic clocks for Mobilty chips
406 if (di->is_mobility && di->settings.dynamic_clocks)
407 Radeon_SetDynamicClock( di, 1);
408
409 return B_OK;
410
411 err0:
412 Radeon_UninitCP( di );
413 err:
414 mem_destroy( di->memmgr[mt_PCI] );
415 err2:
416 mem_destroy( di->memmgr[mt_local] );
417 err3:
418 Radeon_CleanupIRQ( di );
419 err4:
420 Radeon_CleanupPCIGART( di );
421 err5:
422 Radeon_UnmapDevice( di );
423 err6:
424 delete_area( di->virtual_card_area );
425 err7:
426 delete_area( di->shared_area );
427 err8:
428 return result;
429 }
430
431 // clean up shared info on last close
432 // (we could for device destruction, but this makes
433 // testing easier as everythings gets cleaned up
434 // during tests)
Radeon_LastClose(device_info * di)435 void Radeon_LastClose( device_info *di )
436 {
437 if ( di->acc_dma )
438 Radeon_UninitCP( di );
439
440 // M6 fix - unfortunately, the device is never closed by app_server,
441 // not even before reboot
442 if( di->asic == rt_rv100 && di->is_mobility)
443 OUTREG( di->regs, RADEON_DAC_CNTL2, di->dac2_cntl );
444
445
446 mem_destroy( di->memmgr[mt_local] );
447
448 if( di->memmgr[mt_PCI] )
449 mem_destroy( di->memmgr[mt_PCI] );
450
451 if( di->memmgr[mt_AGP] )
452 mem_destroy( di->memmgr[mt_AGP] );
453
454 Radeon_CleanupIRQ( di );
455 Radeon_CleanupPCIGART( di );
456 Radeon_UnmapDevice(di);
457
458 #ifdef ENABLE_LOGGING
459 #ifdef LOG_INCLUDE_STARTUP
460 log_exit( di->si->log );
461 #endif
462 #endif
463
464 delete_area( di->virtual_card_area );
465 delete_area( di->shared_area );
466 }
467