1 /* 2 Copyright (c) 2002, Thomas Kurschel 3 4 5 Part of Radeon kernel driver 6 7 Init and clean-up of devices 8 9 TBD: support for multiple virtual card per device is 10 not implemented yet - there is only one per device; 11 apart from additional device names, we need proper 12 management of graphics mem to not interfere. 13 */ 14 15 #include "radeon_driver.h" 16 17 #include <PCI.h> 18 #include <stdio.h> 19 #include <dac_regs.h> 20 #include <mmio.h> 21 22 // helper macros for easier PCI access 23 #define get_pci(o, s) (*pci_bus->read_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s)) 24 #define set_pci(o, s, v) (*pci_bus->write_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s), (v)) 25 26 27 // map frame buffer and registers 28 // mmio_only - true = map registers only (used during detection) 29 status_t Radeon_MapDevice( device_info *di, bool mmio_only ) 30 { 31 // framebuffer is stored in PCI range 0, 32 // register map in PCI range 2 33 int regs = 2; 34 int fb = 0; 35 char buffer[B_OS_NAME_LENGTH]; 36 shared_info *si = di->si; 37 uint32 tmp; 38 pci_info *pcii = &(di->pcii); 39 status_t result; 40 41 SHOW_FLOW( 3, "device: %02X%02X%02X", 42 di->pcii.bus, di->pcii.device, di->pcii.function ); 43 44 si->regs_area = si->fb_area = 0; 45 46 // enable memory mapped IO and frame buffer 47 // also, enable bus mastering (some BIOSes seem to 48 // disable that, like mine) 49 tmp = get_pci( PCI_command, 2 ); 50 SHOW_FLOW( 3, "old PCI command state: 0x%08lx", tmp ); 51 tmp |= PCI_command_io | PCI_command_memory | PCI_command_master; 52 set_pci( PCI_command, 2, tmp ); 53 54 // registers cannot be accessed directly by user apps, 55 // they need to clone area for safety reasons 56 SHOW_INFO( 1, "physical address of memory-mapped I/O: 0x%8lx-0x%8lx", 57 di->pcii.u.h0.base_registers[regs], 58 di->pcii.u.h0.base_registers[regs] + di->pcii.u.h0.base_register_sizes[regs] - 1 ); 59 60 sprintf( buffer, "%04X_%04X_%02X%02X%02X regs", 61 di->pcii.vendor_id, di->pcii.device_id, 62 di->pcii.bus, di->pcii.device, di->pcii.function ); 63 64 si->regs_area = map_physical_memory( 65 buffer, 66 (void *) di->pcii.u.h0.base_registers[regs], 67 di->pcii.u.h0.base_register_sizes[regs], 68 B_ANY_KERNEL_ADDRESS, 69 0, 70 (void **)&(di->regs)); 71 if( si->regs_area < 0 ) 72 return si->regs_area; 73 74 if( mmio_only ) 75 return B_OK; 76 77 if( di->pcii.u.h0.base_register_sizes[fb] > di->local_mem_size ) { 78 // Radeons allocate more address range then really needed -> 79 // only map the area that contains physical memory 80 SHOW_INFO( 1, "restrict frame buffer from 0x%8lx to 0x%8lx bytes", 81 di->pcii.u.h0.base_register_sizes[fb], 82 di->local_mem_size 83 ); 84 di->pcii.u.h0.base_register_sizes[fb] = di->local_mem_size; 85 } 86 87 // framebuffer can be accessed by everyone 88 // this is not a perfect solution; preferably, only 89 // those areas owned by an application are mapped into 90 // its address space 91 SHOW_INFO( 1, "physical address of framebuffer: 0x%8lx-0x%8lx", 92 di->pcii.u.h0.base_registers[fb], 93 di->pcii.u.h0.base_registers[fb] + di->pcii.u.h0.base_register_sizes[fb] - 1 ); 94 95 sprintf(buffer, "%04X_%04X_%02X%02X%02X framebuffer", 96 di->pcii.vendor_id, di->pcii.device_id, 97 di->pcii.bus, di->pcii.device, di->pcii.function); 98 99 si->fb_area = map_physical_memory( 100 buffer, 101 (void *) di->pcii.u.h0.base_registers[fb], 102 di->pcii.u.h0.base_register_sizes[fb], 103 B_ANY_KERNEL_BLOCK_ADDRESS | B_MTR_WC, 104 B_READ_AREA + B_WRITE_AREA, 105 (void **)&(si->framebuffer)); 106 107 if (si->fb_area < 0) { 108 SHOW_FLOW0( 3, "couldn't enable WC for frame buffer" ); 109 si->fb_area = map_physical_memory( 110 buffer, 111 (void *) di->pcii.u.h0.base_registers[fb], 112 di->pcii.u.h0.base_register_sizes[fb], 113 B_ANY_KERNEL_BLOCK_ADDRESS, 114 B_READ_AREA + B_WRITE_AREA, 115 (void **)&(si->framebuffer)); 116 } 117 118 SHOW_FLOW( 3, "mapped frame buffer @%p", si->framebuffer ); 119 120 if (si->fb_area < 0) { 121 result = si->fb_area; 122 goto err; 123 } 124 125 // save physical address though noone can probably make 126 // any use of it 127 si->framebuffer_pci = (void *) di->pcii.u.h0.base_registers_pci[fb]; 128 129 return B_OK; 130 131 err: 132 delete_area(si->regs_area); 133 return result; 134 } 135 136 137 // unmap PCI ranges 138 void Radeon_UnmapDevice(device_info *di) 139 { 140 shared_info *si = di->si; 141 pci_info *pcii = &(di->pcii); 142 uint32 tmp; 143 144 SHOW_FLOW0( 3, "" ); 145 146 // disable PCI ranges (though it probably won't 147 // hurt leaving them enabled) 148 tmp = get_pci( PCI_command, 2 ); 149 tmp &= ~PCI_command_io | PCI_command_memory | PCI_command_master; 150 set_pci( PCI_command, 2, tmp ); 151 152 if( si->regs_area > 0 ) 153 delete_area( si->regs_area ); 154 155 if( si->fb_area > 0 ) 156 delete_area( si->fb_area ); 157 158 si->regs_area = si->fb_area = 0; 159 } 160 161 162 // initialize shared infos on first open 163 status_t Radeon_FirstOpen( device_info *di ) 164 { 165 status_t result; 166 char buffer[B_OS_NAME_LENGTH]; 167 shared_info *si; 168 //uint32 /*dma_block, */dma_offset; 169 170 // create shared info; don't allow access by apps - 171 // they'll clone it 172 sprintf( buffer, "%04X_%04X_%02X%02X%02X shared", 173 di->pcii.vendor_id, di->pcii.device_id, 174 di->pcii.bus, di->pcii.device, di->pcii.function ); 175 176 di->shared_area = create_area( 177 buffer, 178 (void **)&(di->si), 179 B_ANY_KERNEL_ADDRESS, 180 (sizeof(shared_info) + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1), 181 B_FULL_LOCK, 0); 182 if (di->shared_area < 0) { 183 result = di->shared_area; 184 goto err8; 185 } 186 187 memset( di->si, 0, sizeof( *di->si )); 188 189 si = di->si; 190 191 #ifdef ENABLE_LOGGING 192 si->log = log_init( 1000000 ); 193 #endif 194 195 // copy all info into shared info 196 si->vendor_id = di->pcii.vendor_id; 197 si->device_id = di->pcii.device_id; 198 si->revision = di->pcii.revision; 199 200 si->has_crtc2 = di->has_crtc2; 201 si->asic = di->asic; 202 203 si->ports[0].disp_type = di->disp_type[0]; 204 si->ports[1].disp_type = di->disp_type[1]; 205 si->fp_port = di->fp_info; 206 si->pll = di->pll; 207 /* si->ram = di->ram; 208 strcpy( si->ram_type, di->ram_type );*/ 209 si->local_mem_size = di->local_mem_size; 210 211 // create virtual card info; don't allow access by apps - 212 // they'll clone it 213 sprintf( buffer, "%04X_%04X_%02X%02X%02X virtual card 0", 214 di->pcii.vendor_id, di->pcii.device_id, 215 di->pcii.bus, di->pcii.device, di->pcii.function ); 216 di->virtual_card_area = create_area( 217 buffer, 218 (void **)&(di->vc), 219 B_ANY_KERNEL_ADDRESS, 220 (sizeof(virtual_card) + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1), 221 B_FULL_LOCK, 0); 222 if (di->virtual_card_area < 0) { 223 result = di->virtual_card_area; 224 goto err5; 225 } 226 227 // currently, we assign fixed ports to this virtual card 228 di->vc->num_ports = si->has_crtc2 ? 2 : 1; 229 di->vc->ports[0].is_crtc2 = false; 230 di->vc->ports[0].physical_port = 0; 231 di->vc->ports[1].is_crtc2 = true; 232 di->vc->ports[1].physical_port = 1; 233 234 di->vc->fb_mem_handle = 0; 235 di->vc->cursor.mem_handle = 0; 236 237 // create unique id 238 di->vc->id = di->virtual_card_area; 239 240 result = Radeon_MapDevice( di, false ); 241 if (result < 0) 242 goto err4; 243 244 // save dac2_cntl register 245 // we need to restore that during uninit, else you only get 246 // garbage on screen on reboot 247 if( di->has_crtc2 ) 248 di->dac2_cntl = INREG( di->regs, RADEON_DAC_CNTL2 ); 249 250 result = Radeon_InitDMA( di ); 251 if( result < 0 ) 252 goto err3; 253 254 // currently, we don't support VLI - something is broken there 255 // (it doesn't change a thing apart from crashing) 256 /* result = Radeon_SetupIRQ( di, buffer ); 257 if( result < 0 ) 258 goto err2;*/ 259 260 di->local_memmgr = mem_init( 0, di->local_mem_size, 1024, 261 di->local_mem_size / 1024 ); 262 if( di->local_memmgr == NULL ) { 263 result = B_NO_MEMORY; 264 goto err1; 265 } 266 267 //Radeon_Fix_AGP(); 268 269 // mem_alloc( di->local_memmgr, 0x100000, (void *)-1, &dma_block, &dma_offset ); 270 /* dma_offset = 15 * 1024 * 1024; 271 272 si->nonlocal_mem = (uint32 *)((uint32)si->framebuffer + dma_offset); 273 si->nonlocal_vm_start = (uint32)si->framebuffer_pci + dma_offset;*/ 274 275 return B_OK; 276 277 err1: 278 /*Radeon_CleanupIRQ( di ); 279 err2:*/ 280 Radeon_CleanupDMA( di ); 281 err3: 282 Radeon_UnmapDevice( di ); 283 err4: 284 delete_area( di->virtual_card_area ); 285 err5: 286 delete_area( di->shared_area ); 287 err8: 288 return result; 289 } 290 291 // clean up shared info on last close 292 // (we could for device destruction, but this makes 293 // testing easier as everythings gets cleaned up 294 // during tests) 295 void Radeon_LastClose( device_info *di ) 296 { 297 if( di->has_crtc2 ) 298 OUTREG( di->regs, RADEON_DAC_CNTL2, di->dac2_cntl ); 299 300 mem_destroy( di->local_memmgr ); 301 302 // Radeon_CleanupIRQ( di ); 303 Radeon_CleanupDMA( di ); 304 Radeon_UnmapDevice(di); 305 306 #ifdef ENABLE_LOGGING 307 log_exit( di->si->log ); 308 #endif 309 310 delete_area( di->virtual_card_area ); 311 delete_area( di->shared_area ); 312 } 313