1/* 2 * 3 */ 4 5#ifdef HAVE_CONFIG_H 6#include "config.h" 7#endif 8 9/* 10 * includes 11 */ 12 13#include "rendition.h" 14#include "v1krisc.h" 15#include "vos.h" 16 17 18 19/* 20 * defines 21 */ 22 23/* RISC registers */ 24#define RISC_FLAG 37 /* RISC flags register */ 25#define RISC_SP 252 /* RISC stack pointer/scratch register */ 26#define RISC_IRA 253 /* RISC register */ 27#define RISC_RA 254 /* RISC program link/scratch register */ 28#define RISC_FP 255 /* RISC frame pointer/scratch register */ 29 30/* RISC opcodes used */ 31#define NOP_INSTR 0x00000000 /* really add immed with D=zero */ 32#define ADDI_OP 0x00 33#define SPRI_OP 0x4f 34#define ADD_OP 0x10 35#define ANDN_OP 0x12 36#define OR_OP 0x15 37#define ADDIFI_OP 0x40 38#define ADDSL8_OP 0x4b 39#define LB_OP 0x70 40#define LH_OP 0x71 41#define LW_OP 0x72 42#define LI_OP 0x76 43#define LUI_OP 0x77 44#define SB_OP 0x78 45#define SH_OP 0x79 46#define SW_OP 0x7a 47#define JMP_OP 0x6c 48 49/* defines for instruction composition */ 50#define INT_INSTR(op, d, s2, s1) \ 51 (((vu32)(op)<<24) | ((vu32)(d)<<16) | ((vu32)(s2)<<8) | ((vu32)(s1)&0xff)) 52#define STR_INSTR(op, off8, s2, s1) \ 53 (((vu32)(op)<<24) | (((vu32)(off8)&0xff)<<16) | ((vu32)(s2)<<8) | ((vu32)(s1))) 54#define LD_INSTR(op, d, off8, s1) \ 55 (((vu32)(op)<<24) | ((vu32)(d)<<16) | (((vu32)(off8)&0xff)<<8) | ((vu32)(s1))) 56#define LI_INSTR(op, d, immed16) \ 57 (((vu32)(op)<<24) | ((vu32)(d)<<16) | ((vu32)(immed16)&0xffff)) 58#define BR_INSTR(op, off16, s1) \ 59 (((vu32)(op)<<24) | (((vu32)(off16)&0xffff)<<8) | ((vu32)(s1))) 60#define JMP_INSTR(op, addr24) \ 61 (((vu32)(op)<<24) | ((vu32)(addr24))) 62 63/* some masks */ 64#define TYPEINSTR 0xf0000000 65#define TYPEBRANCH 0x60000000 66#define HALTBIT 0x00000008 67 68#define VBIOS_DTNR 0x2000 69 70#define READ_BYTE 0 71#define READ_SHORT 1 72#define READ_WORD 2 73 74#define WRITE_BYTE 0 75#define WRITE_SHORT 1 76#define WRITE_WORD 2 77 78#define VERITE_MAX_POLLS 100 79 80 81 82/* 83 * local function prototypes 84 */ 85 86static void verite_iopoll(unsigned long port, vu32 data, vu32 mask); 87static void verite_iopoll8(unsigned long port, vu8 data, vu8 mask); 88 89static vu32 readRF(unsigned long io_base, vu8 index); 90static void writeRF(unsigned long io_base, vu8 index, vu32 data); 91 92static vu32 risc_readmem(unsigned long io_base, vu32 addr, vu8 read_type); 93static void risc_writemem(unsigned long io_base, vu32 addr, vu32 data, vu8 write_type); 94 95#if 0 96static void risc_step(unsigned long io_base, vu32 count); 97#endif 98static void risc_forcestep(unsigned long io_base, vu32 instruction); 99static void risc_continue(unsigned long io_base); 100 101 102 103/* 104 * functions 105 */ 106 107/* 108 * void v1k_start(ScrnInfoPtr pScreenInfo, vu32 pc) 109 * 110 * Start the RISC with its PC set to |pc|. 111 */ 112void 113v1k_start(ScrnInfoPtr pScreenInfo, vu32 pc) 114{ 115 renditionPtr pRendition = RENDITIONPTR(pScreenInfo); 116 unsigned long io_base=pRendition->board.io_base; 117 118 v1k_stop(pScreenInfo); 119 risc_forcestep(io_base, NOP_INSTR); 120 risc_forcestep(io_base, NOP_INSTR); 121 risc_forcestep(io_base, NOP_INSTR); 122 risc_forcestep(io_base, JMP_INSTR(JMP_OP, pc>>2)); 123 risc_forcestep(io_base, NOP_INSTR); 124 125 v1k_continue(pScreenInfo); 126} 127 128 129 130/* 131 * void v1k_continue(ScrnInfoPtr pScreenInfo) 132 * 133 * Let the RISC do its work. 134 */ 135void 136v1k_continue(ScrnInfoPtr pScreenInfo) 137{ 138 renditionPtr pRendition = RENDITIONPTR(pScreenInfo); 139 140 risc_continue(pRendition->board.io_base); 141} 142 143 144 145/* 146 * void v1k_stop(ScrnInfoPtr pScreenInfo) 147 * 148 * Stop the RISC. 149 */ 150void 151v1k_stop(ScrnInfoPtr pScreenInfo) 152{ 153 renditionPtr pRendition = RENDITIONPTR(pScreenInfo); 154 vu8 debugreg, statusreg; 155 unsigned long io_base=pRendition->board.io_base; 156 vu16 STATUS = 0x4A; /* v2x00 io register offset */ 157 int c; 158 159 debugreg=verite_in8(io_base+DEBUGREG); 160 161 if (pRendition->board.chip == V2000_DEVICE){ 162 c=0; 163 do { 164/* if(!(c%10000))ErrorF("#S1# !0x%x! -- ",verite_in8(io_base+STATUS)); */ 165 statusreg = verite_in8(io_base+STATUS); 166 if ((statusreg & 0x8C) == 0x8C) 167 break; 168 } while (c++<0xfffff); 169 if (c >= 0xfffff) 170 xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 171 ("Status timeout (1)\n")); 172 173 verite_out8(io_base+DEBUGREG, debugreg|HOLDRISC); 174 175 if (pRendition->board.chip == V2000_DEVICE){ 176 c=0; 177 do { 178/* if(!(c%10000))ErrorF("#S2# !0x%x! -- ",verite_in8(io_base+STATUS)); */ 179 statusreg = verite_in8(io_base+STATUS); 180 if (statusreg & HOLDRISC) break; 181 } while (c++<0xfffff); 182 if (c >= 0xfffff) 183 xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 184 ("Status timeout (2)\n")); 185 } 186 } 187 else { 188 /* V1000 stop */ 189 verite_out8(io_base+DEBUGREG, debugreg|HOLDRISC); 190 191 verite_iopoll(io_base+STATEDATA, 0, 0); /* short pause */ 192 verite_iopoll(io_base+STATEDATA, 0, 0); /* short pause */ 193 verite_iopoll(io_base+STATEDATA, 0, 0); /* short pause */ 194 } 195} 196 197 198 199/* 200 * void v1k_flushicache(ScrnInfoPtr pScreenInfo) 201 * 202 * Returns with Icache on, also flushes Pixel engine line buffers 203 * in the Dcache. 204 */ 205void 206v1k_flushicache(ScrnInfoPtr pScreenInfo) 207{ 208 renditionPtr pRendition = RENDITIONPTR(pScreenInfo); 209 vu32 c, p1, p2; 210 unsigned long io_base=pRendition->board.io_base; 211 212 /* first flush store accumulation buffers so data is all in memory */ 213 p1=risc_readmem(io_base, 0, READ_WORD); 214 p2=risc_readmem(io_base, 8, READ_WORD); 215 risc_writemem(io_base, 0, p1, WRITE_WORD); 216 risc_writemem(io_base, 8, p2, WRITE_WORD); 217 (void)risc_readmem(io_base, 0, READ_WORD); 218 (void)risc_readmem(io_base, 8, READ_WORD); 219 220 /* now force a spr Sync,zero to cause the pixel engine line buffers 221 * to be flushed. */ 222 risc_forcestep(io_base, INT_INSTR(SPRI_OP, 0, 0, 31)); /* spri Sync,zero */ 223 risc_forcestep(io_base, NOP_INSTR); 224 risc_forcestep(io_base, NOP_INSTR); 225 risc_forcestep(io_base, NOP_INSTR); 226 227 228 writeRF(io_base, RISC_RA, ICACHE_ONOFF_MASK); /* load mask */ 229 /* set bits */ 230 risc_forcestep(io_base, INT_INSTR(OR_OP, RISC_FLAG, RISC_FLAG, RISC_RA)); 231 risc_forcestep(io_base, NOP_INSTR); /* clear hazard */ 232 risc_forcestep(io_base, NOP_INSTR); 233 risc_forcestep(io_base, NOP_INSTR); 234 235 /* flush ICache */ 236 for (c=0; c<ICACHESIZE*2; c+=ICACHELINESIZE) 237 risc_forcestep(io_base, JMP_INSTR(JMP_OP, c>>2)); /* jmp NextCacheLine. */ 238 239 writeRF(io_base, RISC_RA, ICACHE_ONOFF_MASK); /* load mask */ 240 /* clear bits */ 241 risc_forcestep(io_base, INT_INSTR(ANDN_OP, RISC_FLAG, RISC_FLAG, RISC_RA)); 242 risc_forcestep(io_base, NOP_INSTR); /* jump back to PC=0 */ 243 risc_forcestep(io_base, JMP_INSTR(JMP_OP, 0)); 244 risc_forcestep(io_base, NOP_INSTR); 245} 246 247 248 249/* 250 * void v1k_softreset(ScrnInfoPtr pScreenInfo) 251 * 252 * Soft Reset RISC. 253 */ 254void 255v1k_softreset(ScrnInfoPtr pScreenInfo) 256{ 257 renditionPtr pRendition = RENDITIONPTR(pScreenInfo); 258 unsigned long io_base=pRendition->board.io_base; 259 260 verite_out8(io_base+DEBUGREG, SOFTRESET|HOLDRISC); 261 verite_out8(io_base+STATEINDEX, STATEINDEX_PC); 262 verite_iopoll(io_base+STATEDATA, 0, 0xffffffff); 263 verite_iopoll(io_base+STATEDATA, 0, 0xffffffff); 264 verite_iopoll(io_base+STATEDATA, 0, 0xffffffff); 265 266 verite_out8(io_base+DEBUGREG, HOLDRISC); 267 verite_iopoll(io_base+STATEDATA, 0, 0); 268 verite_iopoll(io_base+STATEDATA, 0, 0); 269 verite_iopoll(io_base+STATEDATA, 0, 0); 270 271 /* turn icache on */ 272 risc_forcestep(io_base, LI_INSTR(LI_OP, RISC_RA, ICACHE_ONOFF_MASK&0xffff)); 273 risc_forcestep(io_base, INT_INSTR(ADDIFI_OP, RISC_FLAG, RISC_RA, 274 ICACHE_ONOFF_MASK>>16)); 275 /* clear any interrupts */ 276 verite_out8(io_base+INTR, 0xff); 277 /* byte swap mode=word */ 278 verite_out8(io_base+MEMENDIAN, MEMENDIAN_NO); 279} 280 281 282 283/* 284void 285v1k_getriscprocs(verite_board_desc *boardDesc) 286{ 287 boardDesc->risc_procs.risc_softreset = v1krisc_softreset; 288 boardDesc->risc_procs.risc_flushicache = v1krisc_flushicache; 289 boardDesc->risc_procs.risc_start = v1krisc_start; 290 boardDesc->risc_procs.risc_stop = v1krisc_stop; 291 boardDesc->risc_procs.risc_continue = v1krisc_continue; 292 return; 293} 294*/ 295 296 297 298/* 299 * local functions 300 */ 301 302/* 303 * static void verite_iopoll(unsigned long port, vu32 data, vu32 mask) 304 * 305 * Loop on IO read until expected data is read or VERITE_MAX_POLLS is reached. 306 */ 307static void 308verite_iopoll(unsigned long port, vu32 data, vu32 mask) 309{ 310 vu32 c; 311 312 c=0; 313 do { 314 c++; 315 if ((verite_in32(port)&mask) == (data&mask)) 316 break; 317 } while (c <= VERITE_MAX_POLLS); 318} 319 320 321 322/* 323 * static void verite_iopoll8(unsigned long port, vu8 data, vu8 mask) 324 * 325 * Loop on IO read until expected data is read or VERITE_MAX_POLLS is reached. 326 */ 327static void 328verite_iopoll8(unsigned long port, vu8 data, vu8 mask) 329{ 330 vu32 c; 331 332 c=0; 333 do { 334 c++; 335 if ((verite_in8(port)&mask) == (data&mask)) 336 break; 337 } while (c <= VERITE_MAX_POLLS); 338} 339 340 341 342/* 343 * static vu32 readRF(unsigned long io_base, vu8 index) 344 * 345 * Reads data from register file. 346 */ 347static vu32 348readRF(unsigned long io_base, vu8 index) 349{ 350 vu32 data, instr; 351 vu8 debug, stateindex; 352 353 debug=verite_in8(io_base+DEBUGREG); 354 stateindex=verite_in8(io_base+STATEINDEX); 355 356 /* force RISC instruction: add zero,zero,index 357 * S1 reg address = reg index to read 358 * write to the DEC_IR, but no need to step it! */ 359 verite_out8(io_base+DEBUGREG, debug|HOLDRISC); 360 361 instr=INT_INSTR(ADD_OP, 0, 0, index); 362 verite_out32(io_base+STATEDATA, instr); 363 364 /* wait for instruction to get to RISC IR. */ 365 verite_out8(io_base+STATEINDEX, STATEINDEX_IR); /* point at DEC_IR */ 366 verite_iopoll(io_base+STATEDATA, instr, 0xffffffff); 367 368 verite_out8(io_base+STATEINDEX, STATEINDEX_S1); /* point at RISCS1 */ 369 verite_iopoll(io_base+STATEINDEX, 0, 0); /* short pause */ 370 data=verite_in32(io_base+STATEDATA); /* read RF */ 371 372 verite_out8(io_base+STATEINDEX, stateindex); /* restore state_index */ 373 verite_out8(io_base+DEBUGREG, debug); /* restore debug */ 374 375 return data; 376} 377 378 379 380/* 381 * static void writeRF(unsigned long io_base, vu8 index, vu32 data) 382 * 383 * Set RF register, being careful on how to set regs below 64. 384 */ 385static void 386writeRF(unsigned long io_base, vu8 index, vu32 data) 387{ 388 vu8 special=0; 389 390 if (index < 64) { /* constants or HW regs */ 391 special=index; /* keep track of special register */ 392 index=RISC_SP; /* use |sp| as tmp, since it gets restored */ 393 } 394 395 if (!(data & 0xff000000)) { /* only 16 or 24 LSBs */ 396 /* Set 16 LS bits. */ 397 risc_forcestep(io_base, LI_INSTR(LI_OP,index,data&0xffff)); 398 if (data & 0x00ff0000) /* need all 24 LS bits? */ 399 risc_forcestep(io_base, INT_INSTR(ADDIFI_OP,index,index,data>>16) ); 400 } 401 else { /* else, do all 32 bits */ 402 risc_forcestep(io_base, LI_INSTR(LUI_OP, index, data>>16)); 403 risc_forcestep(io_base, INT_INSTR(ADDSL8_OP, index, index, (data>>8)&0xff)); 404 risc_forcestep(io_base, INT_INSTR(ADDI_OP, index, index, data&0xff)); 405 } 406 407 if (special) { 408 /* move data to special register */ 409 risc_forcestep(io_base, INT_INSTR(ADD_OP, special, 0, RISC_SP)); 410 /* clear hazard */ 411 risc_forcestep(io_base, NOP_INSTR); 412 risc_forcestep(io_base, NOP_INSTR); 413 risc_forcestep(io_base, NOP_INSTR); 414 } 415} 416 417 418 419/* 420 * static vu32 risc_readmem(unsigned long io_base, vu32 addr, vu8 read_type) 421 * 422 * NOTE: Assumes RISC is in hold mode. 423 */ 424static vu32 425risc_readmem(unsigned long io_base, vu32 addr, vu8 read_type) 426{ 427 vu32 data; 428 429 writeRF(io_base, RISC_RA, addr); /* point to memory */ 430 if (READ_BYTE == read_type) /* read memory */ 431 risc_forcestep(io_base, LD_INSTR(LB_OP, RISC_SP, 0, RISC_RA)); 432 else 433 if (READ_SHORT == read_type) 434 risc_forcestep(io_base, LD_INSTR(LH_OP, RISC_SP, 0, RISC_RA)); 435 else 436 risc_forcestep(io_base, LD_INSTR(LW_OP, RISC_SP, 0, RISC_RA)); 437 438 risc_forcestep(io_base, NOP_INSTR); /* need nop's */ 439 risc_forcestep(io_base, NOP_INSTR); /* need nop's */ 440 data=readRF(io_base, RISC_SP); /* get data */ 441 442 return data; 443} 444 445 446 447/* 448 * static vu32 risc_writemem(unsigned long io_base, vu32 addr, vu32 data, vu8 write_type) 449 * 450 * NOTE: Assumes RISC is in hold mode. 451 */ 452static void 453risc_writemem(unsigned long io_base, vu32 addr, vu32 data, vu8 write_type) 454{ 455 writeRF(io_base, RISC_RA, addr); /* point to memory */ 456 writeRF(io_base, RISC_FP, data); /* set data */ 457 if (WRITE_BYTE == write_type) /* write memory */ 458 risc_forcestep(io_base, STR_INSTR(SB_OP, 0, RISC_FP, RISC_RA)); 459 else 460 if (WRITE_SHORT == write_type) 461 risc_forcestep(io_base, STR_INSTR(SH_OP, 0, RISC_FP, RISC_RA)); 462 else 463 risc_forcestep(io_base, STR_INSTR(SW_OP, 0, RISC_FP, RISC_RA)); 464} 465 466 467#if 0 468/* 469 * static void risc_step(unsigned long io_base, vu32 count) 470 * 471 * Single step the RISC. NOTE: Do not force instruction into RISCIR! 472 */ 473static void 474risc_step(unsigned long io_base, vu32 count) 475{ 476 vu32 c, d; 477 vu8 debugreg; 478 479 /* RISC is already held; just single step it */ 480 481 for (c=0; c<count; c++) { 482 debugreg=verite_in8(io_base+DEBUGREG); 483 verite_out8(io_base+DEBUGREG, debugreg|STEPRISC); 484 485 for (d=0; d<1000; d++) 486 if(0 == (verite_in8(io_base+DEBUGREG)&STEPRISC)) 487 break; 488 489 if (1000 == d) 490 return; /* stall occurred, we're done */ 491 } 492} 493#endif 494 495 496/* 497 * static void risc_forcestep(unsigned long io_base, vu32 instruction) 498 * 499 * Single step RISC; force instruction; assumes RISC held. 500 */ 501static void 502risc_forcestep(unsigned long io_base, vu32 instruction) 503{ 504 vu32 c; 505 vu8 debugreg, stateindex; 506 507 508 debugreg=verite_in8(io_base+DEBUGREG); 509 stateindex=verite_in8(io_base+STATEINDEX); 510 verite_out8(io_base+STATEINDEX, STATEINDEX_IR); 511 verite_iopoll8(io_base+STATEINDEX, STATEINDEX_IR, 0xff); /* wait */ 512 verite_out32(io_base+STATEDATA, instruction); /* load instruction */ 513 verite_iopoll(io_base+STATEDATA, instruction, 0xffffffff); /* wait */ 514 verite_out8(io_base+DEBUGREG, debugreg|HOLDRISC|STEPRISC); /* step */ 515 verite_iopoll(io_base+STATEDATA, 0, 0); /* short pause */ 516 517 for (c=0; c<VERITE_MAX_POLLS; c++) 518 if (HOLDRISC == (verite_in8(io_base+DEBUGREG) & (HOLDRISC|STEPRISC))) 519 break; 520 521 /* restore */ 522 verite_out8(io_base+STATEINDEX, stateindex); 523} 524 525 526 527/* 528 * static void risc_continue(unsigned long io_base) 529 * 530 * Turn off hold bit. 531 */ 532static void 533risc_continue(unsigned long io_base) 534{ 535 vu8 debugreg; 536 537 debugreg=verite_in8(io_base+DEBUGREG); 538 verite_out8(io_base+DEBUGREG, debugreg&(~HOLDRISC)); 539 verite_iopoll(io_base+STATEDATA, 0, 0); /* short pause */ 540} 541 542 543 544/* 545 * end of file v1krisc.c 546 */ 547