1 /* 2 Copyright (c) 2002-05, Thomas Kurschel 3 4 5 Part of Radeon accelerant 6 7 Access to VIP 8 9 This code must be in kernel because we need for FIFO to become empty 10 during VIP access (which in turn requires locking the card, and locking 11 is a dangerous thing in user mode as the app can suddenly die, taking 12 the lock with it) 13 */ 14 15 #include "radeon_driver.h" 16 #include "mmio.h" 17 #include "vip_regs.h" 18 #include "bios_regs.h" 19 #include "theatre_regs.h" 20 21 22 // moved to bottom to avoid inlining 23 static bool Radeon_VIPWaitForIdle( device_info *di ); 24 static status_t RADEON_VIPFifoIdle(device_info *di, uint8 channel); 25 26 27 // read data from VIP 28 // CP lock must be hold 29 static bool do_VIPRead( 30 device_info *di, uint channel, uint address, uint32 *data ) 31 { 32 vuint8 *regs = di->regs; 33 34 Radeon_WaitForFifo( di, 2 ); 35 // the 0x2000 is the nameless "register-read" flag 36 OUTREG( regs, RADEON_VIPH_REG_ADDR, (channel << 14) | address | 0x2000 ); 37 38 if( !Radeon_VIPWaitForIdle( di )) 39 return false; 40 41 // enable VIP register cycle reads 42 Radeon_WaitForFifo( di, 2 ); 43 OUTREGP( regs, RADEON_VIPH_TIMEOUT_STAT, 0, 44 ~RADEON_VIPH_TIMEOUT_STAT_AK_MASK & ~RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS ); 45 //Radeon_WaitForIdle( di, false, false ); 46 47 // this read starts a register cycle; the returned value has no meaning 48 INREG( regs, RADEON_VIPH_REG_DATA ); 49 50 if( !Radeon_VIPWaitForIdle( di )) 51 return false; 52 53 //Radeon_WaitForIdle( di, false, false ); 54 55 // register cycle is done, so disable any further cycle 56 Radeon_WaitForFifo( di, 2 ); 57 OUTREGP( regs, RADEON_VIPH_TIMEOUT_STAT, RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS, 58 ~RADEON_VIPH_TIMEOUT_STAT_AK_MASK & ~RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS ); 59 //Radeon_WaitForIdle( di, false, false ); 60 61 // get the data 62 *data = INREG( regs, RADEON_VIPH_REG_DATA ); 63 64 //SHOW_FLOW( 4, "channel=%d, address=%x, data=%lx", channel, address, *data ); 65 66 if( !Radeon_VIPWaitForIdle( di )) 67 return false; 68 69 // disable register cycle again (according to sample code) 70 // IMHO, this is not necessary as it has been done before 71 Radeon_WaitForFifo( di, 2 ); 72 OUTREGP( regs, RADEON_VIPH_TIMEOUT_STAT, RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS, 73 ~RADEON_VIPH_TIMEOUT_STAT_AK_MASK & ~RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS ); 74 75 return true; 76 } 77 78 // public function: read data from VIP 79 bool Radeon_VIPRead( 80 device_info *di, uint channel, uint address, uint32 *data, bool lock ) 81 { 82 bool res; 83 84 if( lock ) 85 ACQUIRE_BEN( di->si->cp.lock ); 86 87 res = do_VIPRead( di, channel, address, data ); 88 89 if( lock ) 90 RELEASE_BEN( di->si->cp.lock ); 91 92 // SHOW_FLOW( 2, "address=%x, data=%lx, lock=%d", address, *data, lock ); 93 94 return res; 95 } 96 97 static bool do_VIPFifoRead(device_info *di, uint8 channel, uint32 address, uint32 count, uint8 *buffer) 98 { 99 vuint8 *regs = di->regs; 100 uint32 status, tmp; 101 102 if(count!=1) 103 { 104 SHOW_FLOW0( 2, "Attempt to access VIP bus with non-stadard transaction length\n"); 105 return false; 106 } 107 108 SHOW_FLOW( 2, "address=%lx, count=%ld ", address, count ); 109 110 Radeon_WaitForFifo( di, 2); 111 SHOW_FLOW0( 2, "1"); 112 OUTREG( regs, RADEON_VIPH_REG_ADDR, (channel << 14) | address | 0x3000); 113 SHOW_FLOW0( 2, "3"); 114 while(B_BUSY == (status = RADEON_VIPFifoIdle( di , 0xff))); 115 if(B_OK != status) return false; 116 117 // disable VIPH_REGR_DIS to enable VIP cycle. 118 // The LSB of VIPH_TIMEOUT_STAT are set to 0 119 // because 1 would have acknowledged various VIP 120 // interrupts unexpectedly 121 122 SHOW_FLOW0( 2, "4"); 123 Radeon_WaitForFifo( di, 2 ); // Radeon_WaitForIdle( di, false, false ); 124 SHOW_FLOW0( 2, "5"); 125 OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT, 126 INREG( regs, RADEON_VIPH_TIMEOUT_STAT) & 127 (0xffffff00 & ~RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS) ); 128 129 // the value returned here is garbage. The read merely initiates 130 // a register cycle 131 SHOW_FLOW0( 2, "6"); 132 Radeon_WaitForFifo( di, 2 ); // Radeon_WaitForIdle( di, false, false ); 133 INREG( regs, RADEON_VIPH_REG_DATA); 134 SHOW_FLOW0( 2, "7"); 135 while(B_BUSY == (status = RADEON_VIPFifoIdle( di , 0xff))); 136 if(B_OK != status) return false; 137 138 // set VIPH_REGR_DIS so that the read won't take too long. 139 SHOW_FLOW0( 2, "8"); 140 Radeon_WaitForFifo( di, 2 ); // Radeon_WaitForIdle( di, false, false ); 141 SHOW_FLOW0( 2, "9"); 142 tmp = INREG( regs, RADEON_VIPH_TIMEOUT_STAT); 143 OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT, (tmp & 0xffffff00) | RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS); 144 145 SHOW_FLOW0( 2, "10"); 146 Radeon_WaitForFifo( di, 2 ); // Radeon_WaitForIdle( di, false, false ); 147 switch(count){ 148 case 1: 149 *buffer=(uint8)(INREG( regs, RADEON_VIPH_REG_DATA) & 0xff); 150 break; 151 case 2: 152 *(uint16 *)buffer=(uint16) (INREG( regs, RADEON_VIPH_REG_DATA) & 0xffff); 153 break; 154 case 4: 155 *(uint32 *)buffer=(uint32) ( INREG( regs, RADEON_VIPH_REG_DATA) & 0xffffffff); 156 break; 157 } 158 SHOW_FLOW0( 2, "11"); 159 while(B_BUSY == (status = RADEON_VIPFifoIdle( di , 0xff))); 160 if(B_OK != status) return false; 161 162 // so that reading VIPH_REG_DATA would not trigger unnecessary vip cycles. 163 SHOW_FLOW0( 2, "12"); 164 OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT, 165 (INREG( regs, RADEON_VIPH_TIMEOUT_STAT) & 0xffffff00) | RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS); 166 return true; 167 168 } 169 170 bool Radeon_VIPFifoRead(device_info *di, uint8 channel, uint32 address, uint32 count, uint8 *buffer, bool lock) 171 { 172 bool res; 173 174 if( lock ) 175 ACQUIRE_BEN( di->si->cp.lock ); 176 177 res = do_VIPFifoRead( di, channel, address, count, buffer ); 178 179 if( lock ) 180 RELEASE_BEN( di->si->cp.lock ); 181 182 //SHOW_FLOW( 2, "address=%x, data=%lx, lock=%d", address, *data, lock ); 183 184 return res; 185 } 186 187 // write data to VIP 188 // CP must be hold 189 static bool do_VIPWrite( device_info *di, uint8 channel, uint address, uint32 data ) 190 { 191 vuint8 *regs = di->regs; 192 193 Radeon_WaitForFifo( di, 2 ); 194 OUTREG( regs, RADEON_VIPH_REG_ADDR, (channel << 14) | (address & ~0x2000) ); 195 196 if( !Radeon_VIPWaitForIdle( di )) return false; 197 198 //SHOW_FLOW( 4, "channel=%d, address=%x, data=%lx", channel, address, data ); 199 200 Radeon_WaitForFifo( di, 2 ); 201 OUTREG( regs, RADEON_VIPH_REG_DATA, data ); 202 203 return Radeon_VIPWaitForIdle( di ); 204 205 } 206 207 // public function: write data to VIP 208 bool Radeon_VIPWrite(device_info *di, uint8 channel, uint address, uint32 data, bool lock ) 209 { 210 bool res; 211 212 //SHOW_FLOW( 2, "address=%x, data=%lx, lock=%d", address, data, lock ); 213 214 if( lock ) 215 ACQUIRE_BEN( di->si->cp.lock ); 216 217 res = do_VIPWrite( di, channel, address, data ); 218 219 if( lock ) 220 RELEASE_BEN( di->si->cp.lock ); 221 222 return res; 223 } 224 225 226 static bool do_VIPFifoWrite(device_info *di, uint8 channel, uint32 address, uint32 count, uint8 *buffer) 227 { 228 vuint8 *regs = di->regs; 229 230 uint32 status; 231 uint32 i; 232 233 SHOW_FLOW( 2, "address=%lx, count=%ld, ", address, count ); 234 235 Radeon_WaitForFifo( di, 2 ); 236 OUTREG( regs, RADEON_VIPH_REG_ADDR, ((channel << 14) | address | 0x1000) & ~0x2000 ); 237 SHOW_FLOW0( 2, "1"); 238 while(B_BUSY == (status = RADEON_VIPFifoIdle( di, 0x0f))); 239 240 241 if(B_OK != status){ 242 SHOW_FLOW( 2 ,"cannot write %x to VIPH_REG_ADDR\n", (unsigned int)address); 243 return false; 244 } 245 246 SHOW_FLOW0( 2, "2"); 247 for (i = 0; i < count; i+=4) 248 { 249 Radeon_WaitForFifo( di, 2); 250 SHOW_FLOW( 2, "count %ld", count); 251 OUTREG( regs, RADEON_VIPH_REG_DATA, *(uint32*)(buffer + i)); 252 while(B_BUSY == (status = RADEON_VIPFifoIdle( di, 0x0f))); 253 if(B_OK != status) 254 { 255 SHOW_FLOW0( 2 , "cannot write to VIPH_REG_DATA\n"); 256 return false; 257 } 258 } 259 260 return true; 261 } 262 263 bool Radeon_VIPFifoWrite(device_info *di, uint8 channel, uint32 address, uint32 count, uint8 *buffer, bool lock) 264 { 265 bool res; 266 267 //SHOW_FLOW( 2, "address=%x, data=%lx, lock=%d", address, data, lock ); 268 269 if( lock ) 270 ACQUIRE_BEN( di->si->cp.lock ); 271 272 Radeon_VIPReset( di, false); 273 res = do_VIPFifoWrite( di, channel, address, count, buffer ); 274 275 if( lock ) 276 RELEASE_BEN( di->si->cp.lock ); 277 278 return res; 279 } 280 281 282 // reset VIP 283 void Radeon_VIPReset( 284 device_info *di, bool lock ) 285 { 286 vuint8 *regs = di->regs; 287 288 if( lock ) 289 ACQUIRE_BEN( di->si->cp.lock ); 290 291 Radeon_WaitForFifo( di, 5 ); // Radeon_WaitForIdle( di, false, false ); 292 switch(di->asic){ 293 case rt_r200: 294 case rt_rs200: 295 case rt_rv200: 296 case rt_rs100: 297 case rt_rv100: 298 case rt_r100: 299 OUTREG( regs, RADEON_VIPH_CONTROL, 4 | (15 << RADEON_VIPH_CONTROL_VIPH_MAX_WAIT_SHIFT) | 300 RADEON_VIPH_CONTROL_VIPH_DMA_MODE | RADEON_VIPH_CONTROL_VIPH_EN ); // slowest, timeout in 16 phases 301 OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT, (INREG( regs, RADEON_VIPH_TIMEOUT_STAT) & 0xFFFFFF00) | 302 RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS); 303 OUTREG( regs, RADEON_VIPH_DV_LAT, 304 0xff | 305 (4 << RADEON_VIPH_DV_LAT_VIPH_DV0_LAT_SHIFT) | 306 (4 << RADEON_VIPH_DV_LAT_VIPH_DV1_LAT_SHIFT) | 307 (4 << RADEON_VIPH_DV_LAT_VIPH_DV2_LAT_SHIFT) | 308 (4 << RADEON_VIPH_DV_LAT_VIPH_DV3_LAT_SHIFT)); // set timeslice 309 OUTREG( regs, RADEON_VIPH_DMA_CHUNK, 0x151); 310 OUTREG( regs, RADEON_TEST_DEBUG_CNTL, INREG( regs, RADEON_TEST_DEBUG_CNTL) & (~RADEON_TEST_DEBUG_CNTL_OUT_EN)); 311 default: 312 OUTREG( regs, RADEON_VIPH_CONTROL, 9 | (15 << RADEON_VIPH_CONTROL_VIPH_MAX_WAIT_SHIFT) | 313 RADEON_VIPH_CONTROL_VIPH_DMA_MODE | RADEON_VIPH_CONTROL_VIPH_EN ); // slowest, timeout in 16 phases 314 OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT, (INREG( regs, RADEON_VIPH_TIMEOUT_STAT) & 0xFFFFFF00) | 315 RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS); 316 OUTREG( regs, RADEON_VIPH_DV_LAT, 317 0xff | 318 (4 << RADEON_VIPH_DV_LAT_VIPH_DV0_LAT_SHIFT) | 319 (4 << RADEON_VIPH_DV_LAT_VIPH_DV1_LAT_SHIFT) | 320 (4 << RADEON_VIPH_DV_LAT_VIPH_DV2_LAT_SHIFT) | 321 (4 << RADEON_VIPH_DV_LAT_VIPH_DV3_LAT_SHIFT)); // set timeslice 322 OUTREG( regs, RADEON_VIPH_DMA_CHUNK, 0x0); 323 OUTREG( regs, RADEON_TEST_DEBUG_CNTL, INREG( regs, RADEON_TEST_DEBUG_CNTL) & (~RADEON_TEST_DEBUG_CNTL_OUT_EN)); 324 break; 325 326 } 327 328 if( lock ) 329 RELEASE_BEN( di->si->cp.lock ); 330 } 331 332 333 // check whether VIP host is idle 334 // lock must be hold 335 static status_t Radeon_VIPIdle( 336 device_info *di ) 337 { 338 vuint8 *regs = di->regs; 339 uint32 timeout; 340 341 //Radeon_WaitForIdle( di, false, false ); 342 343 // if there is a stuck transaction, acknowledge that 344 timeout = INREG( regs, RADEON_VIPH_TIMEOUT_STAT ); 345 if( (timeout & RADEON_VIPH_TIMEOUT_STAT_VIPH_REG_STAT) != 0 ) 346 { 347 OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT, 348 (timeout & 0xffffff00) | RADEON_VIPH_TIMEOUT_STAT_VIPH_REG_AK); 349 return (INREG( regs, RADEON_VIPH_CONTROL) & 0x2000) ? B_BUSY : B_ERROR; 350 } 351 return (INREG( regs, RADEON_VIPH_CONTROL) & 0x2000) ? B_BUSY : B_OK; 352 } 353 354 static status_t RADEON_VIPFifoIdle(device_info *di, uint8 channel) 355 { 356 vuint8 *regs = di->regs; 357 uint32 timeout; 358 359 timeout = INREG( regs, RADEON_VIPH_TIMEOUT_STAT); 360 if((timeout & 0x0000000f) & channel) /* lockup ?? */ 361 { 362 OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT, (timeout & 0xfffffff0) | channel); 363 return (INREG( regs, RADEON_VIPH_CONTROL) & 0x2000) ? B_BUSY : B_ERROR; 364 } 365 return (INREG( regs, RADEON_VIPH_CONTROL) & 0x2000) ? B_BUSY : B_OK ; 366 } 367 368 369 // wait until VIP host is idle 370 // lock must be hold 371 static bool Radeon_VIPWaitForIdle( 372 device_info *di ) 373 { 374 int i; 375 376 // wait 100x 1ms before giving up 377 for( i = 0; i < 100; ++i ) { 378 status_t res; 379 380 res = Radeon_VIPIdle( di ); 381 if( res != B_BUSY ) { 382 if( res == B_OK ) 383 return true; 384 else 385 return false; 386 } 387 388 snooze( 1000 ); 389 } 390 391 return false; 392 } 393 394 395 // find VIP channel of a device 396 // return: >= 0 channel of device 397 // < 0 no device found 398 int Radeon_FindVIPDevice( 399 device_info *di, uint32 device_id ) 400 { 401 uint channel; 402 uint32 cur_device_id; 403 404 // if card has no VIP port, let hardware detection fail; 405 // in this case, noone will bother us again 406 if( !di->has_vip ) { 407 SHOW_FLOW0( 3, "This Device has no VIP Bus."); 408 return -1; 409 } 410 411 ACQUIRE_BEN( di->si->cp.lock ); 412 413 Radeon_VIPReset( di, false ); 414 415 // there are up to 4 devices, connected to one of 4 channels 416 for( channel = 0; channel < 4; ++channel ) { 417 418 // read device id 419 if( !Radeon_VIPRead( di, channel, RADEON_VIP_VENDOR_DEVICE_ID, &cur_device_id, false )) { 420 SHOW_FLOW( 3, "No device found on channel %d", channel); 421 continue; 422 } 423 424 // compare device id directly 425 if( cur_device_id == device_id ) { 426 SHOW_FLOW( 3, "Device %08lx found on channel %d", device_id, channel); 427 RELEASE_BEN( di->si->cp.lock ); 428 return channel; 429 } 430 } 431 432 RELEASE_BEN( di->si->cp.lock ); 433 434 // couldn't find device 435 return -1; 436 } 437