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