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