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