dev_vr41xx.cc Source File

Back to the index.

dev_vr41xx.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2004-2009 Anders Gavare. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * 3. The name of the author may not be used to endorse or promote products
13  * derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *
28  * COMMENT: VR41xx (VR4122 and VR4131) misc functions
29  *
30  * This is just a big hack.
31  *
32  * TODO: Implement more functionality some day.
33  */
34 
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 
39 #include "console.h"
40 #include "cpu.h"
41 #include "device.h"
42 #include "devices.h"
43 #include "interrupt.h"
44 #include "machine.h"
45 #include "memory.h"
46 #include "misc.h"
47 #include "timer.h"
48 
49 #include "thirdparty/bcureg.h"
50 #include "thirdparty/vripreg.h"
51 #include "thirdparty/vrkiureg.h"
52 #include "thirdparty/vr_rtcreg.h"
53 
54 
55 /* #define debug fatal */
56 
57 #define DEV_VR41XX_TICKSHIFT 14
58 
59 #define DEV_VR41XX_LENGTH 0x800 /* TODO? */
60 struct vr41xx_data {
61  struct interrupt cpu_irq; /* Connected to MIPS irq 2 */
62  int cpumodel; /* Model nr, e.g. 4121 */
63 
64  /* KIU: */
66  uint32_t kiu_offset;
70 
71  int d0, d1, d2, d3, d4, d5;
74 
75  /* Timer: */
78  struct timer *timer;
79 
80  /* See icureg.h in NetBSD for more info. */
81  uint16_t sysint1;
82  uint16_t msysint1;
83  uint16_t giuint;
84  uint16_t giumask;
85  uint16_t sysint2;
86  uint16_t msysint2;
88 };
89 
90 
91 /*
92  * vr41xx_vrip_interrupt_assert():
93  * vr41xx_vrip_interrupt_deassert():
94  */
96 {
97  struct vr41xx_data *d = (struct vr41xx_data *) interrupt->extra;
98  int line = interrupt->line;
99  if (line < 16)
100  d->sysint1 |= (1 << line);
101  else
102  d->sysint2 |= (1 << (line-16));
103  if ((d->sysint1 & d->msysint1) | (d->sysint2 & d->msysint2))
105 }
107 {
108  struct vr41xx_data *d = (struct vr41xx_data *) interrupt->extra;
109  int line = interrupt->line;
110  if (line < 16)
111  d->sysint1 &= ~(1 << line);
112  else
113  d->sysint2 &= ~(1 << (line-16));
114  if (!(d->sysint1 & d->msysint1) && !(d->sysint2 & d->msysint2))
116 }
117 
118 
119 /*
120  * vr41xx_giu_interrupt_assert():
121  * vr41xx_giu_interrupt_deassert():
122  */
124 {
125  struct vr41xx_data *d = (struct vr41xx_data *) interrupt->extra;
126  int line = interrupt->line;
127  d->giuint |= (1 << line);
128  if (d->giuint & d->giumask)
130 }
132 {
133  struct vr41xx_data *d = (struct vr41xx_data *) interrupt->extra;
134  int line = interrupt->line;
135  d->giuint &= ~(1 << line);
136  if (!(d->giuint & d->giumask))
138 }
139 
140 
141 static void recalc_kiu_int_assert(struct cpu *cpu, struct vr41xx_data *d)
142 {
143  if (d->kiu_int_assert != d->old_kiu_int_assert) {
145  if (d->kiu_int_assert != 0)
147  else
149  }
150 }
151 
152 
153 /*
154  * vr41xx_keytick():
155  */
156 static void vr41xx_keytick(struct cpu *cpu, struct vr41xx_data *d)
157 {
158  int keychange = 0;
159 
160  /*
161  * Keyboard input:
162  *
163  * Hardcoded for MobilePro. (See NetBSD's hpckbdkeymap.h for
164  * info on other keyboard layouts. mobilepro780_keytrans is the
165  * one used here.)
166  *
167  * TODO: Make this work with "any" keyboard layout.
168  *
169  * ofs 0:
170  * 8000='o' 4000='.' 2000=DOWN 1000=UP
171  * 800=';' 400=''' 200='[' 100=?
172  * 80='l' 40=CR 20=RIGHT 10=LEFT
173  * 8='/' 4='\' 2=']' 1=SPACE
174  * ofs 2:
175  * 8000='a' 4000='s' 2000='d' 1000='f'
176  * 800='`' 400='-' 200='=' 100=?
177  * 80='z' 40='x' 20='c' 10='v'
178  * 8=? 4=? 2=?
179  * ofs 4:
180  * 8000='9' 4000='0' 2000=? 1000=?
181  * 800='b' 400='n' 200='m' 100=','
182  * 80='q' 40='w' 20='e' 10='r'
183  * 8='5' 4='6' 2='7' 1='8'
184  * ofs 6:
185  * 8000=ESC 4000=DEL 2000=CAPS 1000=?
186  * 800='t' 400='y' 200='u' 100='i'
187  * 80='1' 40='2' 20='3' 10='4'
188  * 8='g' 4='h' 2='j' 1='k'
189  * ofs 8:
190  * 200=ALT_L
191  * 80= 40=TAB 20='p' 10=BS
192  * 8= 4= 2= 1=ALT_R
193  * ofs a:
194  * 800=SHIFT 4=CTRL
195  *
196  *
197  * The following are for the IBM WorkPad Z50:
198  * (Not yet implemented, TODO)
199  *
200  * 00 f1 f3 f5 f7 f9 - - f11
201  * 08 f2 f4 f6 f8 f10 - - f12
202  * 10 ' [ - 0 p ; up /
203  * 18 - - - 9 o l . -
204  * 20 left ] = 8 i k , -
205  * 28 h y 6 7 u j m n
206  * 30 - bs num del - \ ent sp
207  * 38 g t 5 4 r f v b
208  * 40 - - - 3 e d c right
209  * 48 - - - 2 w s x down
210  * 50 esc tab ~ 1 q a z -
211  * 58 menu Ls Lc Rc La Ra Rs -
212  */
213 
214  if (d->d0 != 0 || d->d1 != 0 || d->d2 != 0 ||
215  d->d3 != 0 || d->d4 != 0 || d->d5 != 0)
216  keychange = 1;
217 
218  /* Release all keys: */
219  if (!d->dont_clear_next) {
220  d->d0 = d->d1 = d->d2 = d->d3 = d->d4 = d->d5 = 0;
221  } else
222  d->dont_clear_next = 0;
223 
225  char ch = console_readchar(d->kiu_console_handle);
226 
227  if (d->escape_state > 0) {
228  switch (d->escape_state) {
229  case 1: /* expecting a [ */
230  d->escape_state = 0;
231  if (ch == '[')
232  d->escape_state = 2;
233  break;
234  case 2: /* cursor keys etc: */
235  /* Ugly hack for Mobilepro770: */
236  if (cpu->machine->machine_subtype ==
238  switch (ch) {
239  case 'A': d->d0 = 0x2000; break;
240  case 'B': d->d0 = 0x20; break;
241  case 'C': d->d0 = 0x1000; break;
242  case 'D': d->d0 = 0x10; break;
243  default: fatal("[ vr41xx kiu: unimpl"
244  "emented escape 0x%02 ]\n", ch);
245  }
246  } else {
247  switch (ch) {
248  case 'A': d->d0 = 0x1000; break;
249  case 'B': d->d0 = 0x2000; break;
250  case 'C': d->d0 = 0x20; break;
251  case 'D': d->d0 = 0x10; break;
252  default: fatal("[ vr41xx kiu: unimpl"
253  "emented escape 0x%02 ]\n", ch);
254  }
255  }
256  d->escape_state = 0;
257  }
258  } else switch (ch) {
259  case '+': console_makeavail(d->kiu_console_handle, '=');
260  d->d5 = 0x800; break;
261  case '_': console_makeavail(d->kiu_console_handle, '-');
262  d->d5 = 0x800; break;
263  case '<': console_makeavail(d->kiu_console_handle, ',');
264  d->d5 = 0x800; break;
265  case '>': console_makeavail(d->kiu_console_handle, '.');
266  d->d5 = 0x800; break;
267  case '{': console_makeavail(d->kiu_console_handle, '[');
268  d->d5 = 0x800; break;
269  case '}': console_makeavail(d->kiu_console_handle, ']');
270  d->d5 = 0x800; break;
271  case ':': console_makeavail(d->kiu_console_handle, ';');
272  d->d5 = 0x800; break;
273  case '"': console_makeavail(d->kiu_console_handle, '\'');
274  d->d5 = 0x800; break;
275  case '|': console_makeavail(d->kiu_console_handle, '\\');
276  d->d5 = 0x800; break;
277  case '?': console_makeavail(d->kiu_console_handle, '/');
278  d->d5 = 0x800; break;
279 
280  case '!': console_makeavail(d->kiu_console_handle, '1');
281  d->d5 = 0x800; break;
282  case '@': console_makeavail(d->kiu_console_handle, '2');
283  d->d5 = 0x800; break;
284  case '#': console_makeavail(d->kiu_console_handle, '3');
285  d->d5 = 0x800; break;
286  case '$': console_makeavail(d->kiu_console_handle, '4');
287  d->d5 = 0x800; break;
288  case '%': console_makeavail(d->kiu_console_handle, '5');
289  d->d5 = 0x800; break;
290  case '^': console_makeavail(d->kiu_console_handle, '6');
291  d->d5 = 0x800; break;
292  case '&': console_makeavail(d->kiu_console_handle, '7');
293  d->d5 = 0x800; break;
294  case '*': console_makeavail(d->kiu_console_handle, '8');
295  d->d5 = 0x800; break;
296  case '(': console_makeavail(d->kiu_console_handle, '9');
297  d->d5 = 0x800; break;
298  case ')': console_makeavail(d->kiu_console_handle, '0');
299  d->d5 = 0x800; break;
300 
301  case '1': d->d3 = 0x80; break;
302  case '2': d->d3 = 0x40; break;
303  case '3': d->d3 = 0x20; break;
304  case '4': d->d3 = 0x10; break;
305  case '5': d->d2 = 0x08; break;
306  case '6': d->d2 = 0x04; break;
307  case '7': d->d2 = 0x02; break;
308  case '8': d->d2 = 0x01; break;
309  case '9': d->d2 = 0x8000; break;
310  case '0': d->d2 = 0x4000; break;
311 
312  case ';': d->d0 = 0x800; break;
313  case '\'': d->d0 = 0x400; break;
314  case '[': d->d0 = 0x200; break;
315  case '/': d->d0 = 0x8; break;
316  case '\\': d->d0 = 0x4; break;
317  case ']': d->d0 = 0x2; break;
318 
319  case 'a': d->d1 = 0x8000; break;
320  case 'b': d->d2 = 0x800; break;
321  case 'c': d->d1 = 0x20; break;
322  case 'd': d->d1 = 0x2000; break;
323  case 'e': d->d2 = 0x20; break;
324  case 'f': d->d1 = 0x1000; break;
325  case 'g': d->d3 = 0x8; break;
326  case 'h': d->d3 = 0x4; break;
327  case 'i': d->d3 = 0x100; break;
328  case 'j': d->d3 = 0x2; break;
329  case 'k': d->d3 = 0x1; break;
330  case 'l': d->d0 = 0x80; break;
331  case 'm': d->d2 = 0x200; break;
332  case 'n': d->d2 = 0x400; break;
333  case 'o': d->d0 = 0x8000; break;
334  case 'p': d->d4 = 0x20; break;
335  case 'q': d->d2 = 0x80; break;
336  case 'r': d->d2 = 0x10; break;
337  case 's': d->d1 = 0x4000; break;
338  case 't': d->d3 = 0x800; break;
339  case 'u': d->d3 = 0x200; break;
340  case 'v': d->d1 = 0x10; break;
341  case 'w': d->d2 = 0x40; break;
342  case 'x': d->d1 = 0x40; break;
343  case 'y': d->d3 = 0x400; break;
344  case 'z': d->d1 = 0x80; break;
345 
346  case ',': d->d2 = 0x100; break;
347  case '.': d->d0 = 0x4000; break;
348  case '-': d->d1 = 0x400; break;
349  case '=': d->d1 = 0x200; break;
350 
351  case '\r':
352  case '\n': d->d0 = 0x40; break;
353  case ' ': d->d0 = 0x01; break;
354  case '\b': d->d4 = 0x10; break;
355 
356  case 27: d->escape_state = 1; break;
357 
358  default:
359  /* Shifted: */
360  if (ch >= 'A' && ch <= 'Z') {
362  ch + 32);
363  d->d5 = 0x800;
364  d->dont_clear_next = 1;
365  break;
366  }
367 
368  /* CTRLed: */
369  if (ch >= 1 && ch <= 26) {
371  ch + 96);
372  d->d5 = 0x4;
373  d->dont_clear_next = 1;
374  break;
375  }
376  }
377 
378  if (d->escape_state == 0)
379  keychange = 1;
380  }
381 
382  if (keychange) {
383  /* 4=lost data, 2=data complete, 1=key input detected */
384  d->kiu_int_assert |= 3;
385  recalc_kiu_int_assert(cpu, d);
386  }
387 }
388 
389 
390 /*
391  * timer_tick():
392  */
393 static void timer_tick(struct timer *timer, void *extra)
394 {
395  struct vr41xx_data *d = (struct vr41xx_data *) extra;
397 }
398 
399 
400 DEVICE_TICK(vr41xx)
401 {
402  struct vr41xx_data *d = (struct vr41xx_data *) extra;
403 
404  if (d->pending_timer_interrupts > 0)
406 
407  if (cpu->machine->x11_md.in_use)
408  vr41xx_keytick(cpu, d);
409 }
410 
411 
412 /*
413  * vr41xx_kiu():
414  *
415  * Keyboard Interface Unit. Return value is "odata".
416  * (See NetBSD's vrkiu.c for more info.)
417  */
418 static uint64_t vr41xx_kiu(struct cpu *cpu, int ofs, uint64_t idata,
419  int writeflag, struct vr41xx_data *d)
420 {
421  uint64_t odata = 0;
422 
423  switch (ofs) {
424  case KIUDAT0:
425  odata = d->d0; break;
426  case KIUDAT1:
427  odata = d->d1; break;
428  case KIUDAT2:
429  odata = d->d2; break;
430  case KIUDAT3:
431  odata = d->d3; break;
432  case KIUDAT4:
433  odata = d->d4; break;
434  case KIUDAT5:
435  odata = d->d5; break;
436  case KIUSCANREP:
437  if (writeflag == MEM_WRITE) {
438  debug("[ vr41xx KIU: setting KIUSCANREP to 0x%04x ]\n",
439  (int)idata);
440  /* TODO */
441  } else
442  fatal("[ vr41xx KIU: unimplemented read from "
443  "KIUSCANREP ]\n");
444  break;
445  case KIUSCANS:
446  if (writeflag == MEM_WRITE) {
447  debug("[ vr41xx KIU: write to KIUSCANS: 0x%04x: TODO"
448  " ]\n", (int)idata);
449  /* TODO */
450  } else
451  debug("[ vr41xx KIU: unimplemented read from "
452  "KIUSCANS ]\n");
453  break;
454  case KIUINT:
455  /* Interrupt. A wild guess: zero-on-write */
456  if (writeflag == MEM_WRITE) {
457  d->kiu_int_assert &= ~idata;
458  } else {
459  odata = d->kiu_int_assert;
460  }
461  recalc_kiu_int_assert(cpu, d);
462  break;
463  case KIURST:
464  /* Reset. */
465  break;
466  default:
467  if (writeflag == MEM_WRITE)
468  debug("[ vr41xx KIU: unimplemented write to offset "
469  "0x%x, data=0x%016" PRIx64" ]\n", ofs,
470  (uint64_t) idata);
471  else
472  debug("[ vr41xx KIU: unimplemented read from offset "
473  "0x%x ]\n", ofs);
474  }
475 
476  return odata;
477 }
478 
479 
481 {
482  struct vr41xx_data *d = (struct vr41xx_data *) extra;
483  uint64_t idata = 0, odata = 0;
484  int regnr;
485  int revision = 0;
486 
487  if (writeflag == MEM_WRITE)
488  idata = memory_readmax64(cpu, data, len);
489 
490  regnr = relative_addr / sizeof(uint64_t);
491 
492  /* KIU ("Keyboard Interface Unit") is handled separately. */
493  if (relative_addr >= d->kiu_offset &&
494  relative_addr < d->kiu_offset + 0x20) {
495  odata = vr41xx_kiu(cpu, relative_addr - d->kiu_offset,
496  idata, writeflag, d);
497  goto ret;
498  }
499 
500  /* TODO: Maybe these should be handled separately as well? */
501 
502  switch (relative_addr) {
503 
504  /* BCU: 0x00 .. 0x1c */
505  case BCUREVID_REG_W: /* 0x010 */
506  case BCU81REVID_REG_W: /* 0x014 */
507  /*
508  * TODO? Linux seems to read 0x14. The lowest bits are
509  * a divisor for PClock, bits 8 and up seem to be a
510  * divisor for VTClock (relative to PClock?)...
511  */
512  switch (d->cpumodel) {
513  case 4131: revision = BCUREVID_RID_4131; break;
514  case 4122: revision = BCUREVID_RID_4122; break;
515  case 4121: revision = BCUREVID_RID_4121; break;
516  case 4111: revision = BCUREVID_RID_4111; break;
517  case 4102: revision = BCUREVID_RID_4102; break;
518  case 4101: revision = BCUREVID_RID_4101; break;
519  case 4181: revision = BCUREVID_RID_4181; break;
520  }
521  odata = (revision << BCUREVID_RIDSHFT) | 0x020c;
522  break;
523  case BCU81CLKSPEED_REG_W: /* 0x018 */
524  /*
525  * TODO: Implement this for ALL cpu types:
526  */
528  break;
529 
530  /* DMAAU: 0x20 .. 0x3c */
531 
532  /* DCU: 0x40 .. 0x5c */
533 
534  /* CMU: 0x60 .. 0x7c */
535 
536  /* ICU: 0x80 .. 0xbc */
537  case 0x80: /* Level 1 system interrupt reg 1... */
538  if (writeflag == MEM_READ)
539  odata = d->sysint1;
540  else {
541  /* TODO: clear-on-write-one? */
542  d->sysint1 &= ~idata;
543  d->sysint1 &= 0xffff;
544  }
545  break;
546  case 0x88:
547  if (writeflag == MEM_READ)
548  odata = d->giuint;
549  else
550  d->giuint &= ~idata;
551  break;
552  case 0x8c:
553  if (writeflag == MEM_READ)
554  odata = d->msysint1;
555  else
556  d->msysint1 = idata;
557  break;
558  case 0x94:
559  if (writeflag == MEM_READ)
560  odata = d->giumask;
561  else
562  d->giumask = idata;
563  break;
564  case 0xa0: /* Level 1 system interrupt reg 2... */
565  if (writeflag == MEM_READ)
566  odata = d->sysint2;
567  else {
568  /* TODO: clear-on-write-one? */
569  d->sysint2 &= ~idata;
570  d->sysint2 &= 0xffff;
571  }
572  break;
573  case 0xa6:
574  if (writeflag == MEM_READ)
575  odata = d->msysint2;
576  else
577  d->msysint2 = idata;
578  break;
579 
580  /* RTC: */
581  case 0xc0:
582  case 0xc2:
583  case 0xc4:
584  {
585  struct timeval tv;
586  gettimeofday(&tv, NULL);
587  /* Adjust time by 120 years and 29 days. */
588  tv.tv_sec += (int64_t) (120*365 + 29) * 24*60*60;
589 
590  switch (relative_addr) {
591  case 0xc0:
592  odata = (tv.tv_sec & 1) << 15;
593  odata += (uint64_t)tv.tv_usec * 32768 / 1000000;
594  break;
595  case 0xc2:
596  odata = (tv.tv_sec >> 1) & 0xffff;
597  break;
598  case 0xc4:
599  odata = (tv.tv_sec >> 17) & 0xffff;
600  break;
601  }
602  }
603  break;
604 
605  case 0xd0: /* RTCL1_L_REG_W */
606  if (writeflag == MEM_WRITE && idata != 0) {
607  int hz = RTCL1_L_HZ / idata;
608  debug("[ vr41xx: rtc interrupts at %i Hz ]\n", hz);
609  if (d->timer == NULL)
610  d->timer = timer_add(hz, timer_tick, d);
611  else
613  }
614  break;
615  case 0xd2: /* RTCL1_H_REG_W */
616  break;
617 
618  case 0x108:
619  if (writeflag == MEM_READ)
620  odata = d->giuint;
621  else
622  d->giuint &= ~idata;
623  break;
624  /* case 0x10a:
625  "High" part of GIU?
626  break;
627  */
628 
629  case 0x13e: /* on 4181? */
630  case 0x1de: /* on 4121? */
631  /* RTC interrupt register... */
632  /* Ack. timer interrupts? */
634  if (d->pending_timer_interrupts > 0)
636  break;
637 
638  default:
639  if (writeflag == MEM_WRITE)
640  debug("[ vr41xx: unimplemented write to address "
641  "0x%" PRIx64", data=0x%016" PRIx64" ]\n",
642  (uint64_t) relative_addr, (uint64_t) idata);
643  else
644  debug("[ vr41xx: unimplemented read from address "
645  "0x%" PRIx64" ]\n", (uint64_t) relative_addr);
646  }
647 
648 ret:
649  /*
650  * Recalculate interrupt assertions:
651  */
652  if (d->giuint & d->giumask)
654  else
656  if ((d->sysint1 & d->msysint1) | (d->sysint2 & d->msysint2))
658  else
660 
661  if (writeflag == MEM_READ)
662  memory_writemax64(cpu, data, len, odata);
663 
664  return 1;
665 }
666 
667 
668 /*
669  * dev_vr41xx_init():
670  *
671  * machine->path is something like "machine[0]".
672  */
674  struct memory *mem, int cpumodel)
675 {
676  struct vr41xx_data *d;
677  uint64_t baseaddr = 0;
678  char tmps[300];
679  int i;
680 
681  CHECK_ALLOCATION(d = (struct vr41xx_data *) malloc(sizeof(struct vr41xx_data)));
682  memset(d, 0, sizeof(struct vr41xx_data));
683 
684  /* Connect to MIPS irq 2: */
685  snprintf(tmps, sizeof(tmps), "%s.cpu[%i].2",
686  machine->path, machine->bootstrap_cpu);
687  INTERRUPT_CONNECT(tmps, d->cpu_irq);
688 
689  /*
690  * Register VRIP interrupt lines 0..25:
691  */
692  for (i=0; i<=25; i++) {
693  struct interrupt templ;
694  snprintf(tmps, sizeof(tmps), "%s.cpu[%i].vrip.%i",
695  machine->path, machine->bootstrap_cpu, i);
696  memset(&templ, 0, sizeof(templ));
697  templ.line = i;
698  templ.name = tmps;
699  templ.extra = d;
703  }
704 
705  /*
706  * Register GIU interrupt lines 0..31:
707  */
708  for (i=0; i<32; i++) {
709  struct interrupt templ;
710  snprintf(tmps, sizeof(tmps), "%s.cpu[%i].vrip.%i.giu.%i",
711  machine->path, machine->bootstrap_cpu, VRIP_INTR_GIU, i);
712  memset(&templ, 0, sizeof(templ));
713  templ.line = i;
714  templ.name = tmps;
715  templ.extra = d;
719  }
720 
721  d->cpumodel = cpumodel;
722 
723  /* TODO: VRC4173 has the KIU at offset 0x100? */
724  d->kiu_offset = 0x180;
725  d->kiu_console_handle = -1;
726  if (machine->x11_md.in_use)
728  machine, "kiu", 1);
729 
730  /* Connect to the KIU and GIU interrupts: */
731  snprintf(tmps, sizeof(tmps), "%s.cpu[%i].vrip.%i",
732  machine->path, machine->bootstrap_cpu, VRIP_INTR_GIU);
733  INTERRUPT_CONNECT(tmps, d->giu_irq);
734  snprintf(tmps, sizeof(tmps), "%s.cpu[%i].vrip.%i",
735  machine->path, machine->bootstrap_cpu, VRIP_INTR_KIU);
736  INTERRUPT_CONNECT(tmps, d->kiu_irq);
737 
738  if (machine->x11_md.in_use)
740 
741  switch (cpumodel) {
742  case 4101:
743  case 4102:
744  case 4111:
745  case 4121:
746  baseaddr = 0xb000000;
747  break;
748  case 4181:
749  baseaddr = 0xa000000;
750  dev_ram_init(machine, 0xb000000, 0x1000000, DEV_RAM_MIRROR,
751  0xa000000);
752  break;
753  case 4122:
754  case 4131:
755  baseaddr = 0xf000000;
756  break;
757  default:
758  printf("Unimplemented VR cpu model\n");
759  exit(1);
760  }
761 
762  if (d->cpumodel == 4121 || d->cpumodel == 4181)
763  snprintf(tmps, sizeof(tmps), "%s.cpu[%i].3",
764  machine->path, machine->bootstrap_cpu);
765  else
766  snprintf(tmps, sizeof(tmps), "%s.cpu[%i].vrip.%i",
767  machine->path, machine->bootstrap_cpu, VRIP_INTR_ETIMER);
768  INTERRUPT_CONNECT(tmps, d->timer_irq);
769 
770  memory_device_register(mem, "vr41xx", baseaddr, DEV_VR41XX_LENGTH,
771  dev_vr41xx_access, (void *)d, DM_DEFAULT, NULL);
772 
773  /*
774  * TODO: Find out which controllers are at which addresses on
775  * which chips.
776  */
777  if (cpumodel == 4131) {
778  snprintf(tmps, sizeof(tmps), "ns16550 irq=%s.cpu[%i].vrip.%i "
779  "addr=0x%" PRIx64" name2=siu", machine->path,
780  machine->bootstrap_cpu, VRIP_INTR_SIU,
781  (uint64_t) (baseaddr+0x800));
782  device_add(machine, tmps);
783  } else {
784  /* This is used by Linux and NetBSD: */
785  snprintf(tmps, sizeof(tmps), "ns16550 irq=%s.cpu[%i]."
786  "vrip.%i addr=0x%x name2=serial", machine->path,
787  machine->bootstrap_cpu, VRIP_INTR_SIU, 0xc000000);
788  device_add(machine, tmps);
789  }
790 
791  /* Hm... maybe this should not be here. TODO */
792  snprintf(tmps, sizeof(tmps), "pcic irq=%s.cpu[%i].vrip.%i addr="
793  "0x140003e0", machine->path, machine->bootstrap_cpu,
794  VRIP_INTR_GIU);
795  device_add(machine, tmps);
796 
797  machine_add_tickfunction(machine, dev_vr41xx_tick, d,
799 
800  /* Some machines (?) use ISA space at 0x15000000 instead of
801  0x14000000, eg IBM WorkPad Z50. */
802  dev_ram_init(machine, 0x15000000, 0x1000000, DEV_RAM_MIRROR,
803  0x14000000);
804 
805  return d;
806 }
807 
uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
Definition: memory.cc:55
uint16_t msysint1
Definition: dev_vr41xx.cc:82
void fatal(const char *fmt,...)
Definition: main.cc:152
#define VRIP_INTR_SIU
Definition: vripreg.h:284
int console_start_slave_inputonly(struct machine *machine, const char *consolename, int use_for_input)
Definition: console.cc:714
void(* interrupt_assert)(struct interrupt *)
Definition: interrupt.h:38
#define KIUDAT5
Definition: vrkiureg.h:48
#define DM_DEFAULT
Definition: memory.h:130
struct timer * timer
Definition: dev_vr41xx.cc:78
int main_console_handle
Definition: machine.h:128
#define BCUREVID_RIDSHFT
Definition: bcureg.h:414
struct interrupt timer_irq
Definition: dev_vr41xx.cc:77
#define BCUREVID_REG_W
Definition: bcureg.h:410
uint16_t giuint
Definition: dev_vr41xx.cc:83
void vr41xx_vrip_interrupt_assert(struct interrupt *interrupt)
Definition: dev_vr41xx.cc:95
#define VRIP_INTR_ETIMER
Definition: vripreg.h:290
struct machine * machine
Definition: cpu.h:328
void interrupt_handler_register(struct interrupt *templ)
Definition: interrupt.cc:81
#define MEM_READ
Definition: memory.h:116
#define KIUDAT2
Definition: vrkiureg.h:45
void(* interrupt_deassert)(struct interrupt *)
Definition: interrupt.h:39
void console_makeavail(int handle, char ch)
Definition: console.cc:296
int console_readchar(int handle)
Definition: console.cc:385
int kiu_int_assert
Definition: dev_vr41xx.cc:68
uint16_t sysint1
Definition: dev_vr41xx.cc:81
#define RTCL1_L_HZ
Definition: vr_rtcreg.h:90
int dont_clear_next
Definition: dev_vr41xx.cc:72
#define BCU81CLKSPEED_REG_W
Definition: bcureg.h:438
void * device_add(struct machine *machine, const char *name_and_params)
Definition: device.cc:252
#define BCUREVID_RID_4102
Definition: bcureg.h:419
Definition: timer.cc:45
#define BCUREVID_RID_4131
Definition: bcureg.h:415
#define DEV_RAM_MIRROR
Definition: devices.h:365
#define DEV_VR41XX_LENGTH
Definition: dev_vr41xx.cc:59
struct vr41xx_data * dev_vr41xx_init(struct machine *machine, struct memory *mem, int cpumodel)
Definition: dev_vr41xx.cc:673
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239
uint16_t msysint2
Definition: dev_vr41xx.cc:86
void timer_update_frequency(struct timer *t, double new_freq)
Definition: timer.cc:132
char * path
Definition: machine.h:108
void vr41xx_giu_interrupt_deassert(struct interrupt *interrupt)
Definition: dev_vr41xx.cc:131
#define KIUDAT0
Definition: vrkiureg.h:43
#define KIUSCANREP
Definition: vrkiureg.h:49
int console_charavail(int handle)
Definition: console.cc:336
#define KIUDAT1
Definition: vrkiureg.h:44
int bootstrap_cpu
Definition: machine.h:136
#define BCUREVID_RID_4122
Definition: bcureg.h:416
u_short data
Definition: siireg.h:79
int old_kiu_int_assert
Definition: dev_vr41xx.cc:69
struct interrupt kiu_irq
Definition: dev_vr41xx.cc:67
#define DEV_VR41XX_TICKSHIFT
Definition: dev_vr41xx.cc:57
struct timer * timer_add(double freq, void(*timer_tick)(struct timer *timer, void *extra), void *extra)
Definition: timer.cc:75
void dev_ram_init(struct machine *machine, uint64_t baseaddr, uint64_t length, int mode, uint64_t otheraddress, const char *name)
Definition: dev_ram.cc:134
#define INTERRUPT_ASSERT(istruct)
Definition: interrupt.h:74
#define MEM_WRITE
Definition: memory.h:117
void vr41xx_vrip_interrupt_deassert(struct interrupt *interrupt)
Definition: dev_vr41xx.cc:106
int escape_state
Definition: dev_vr41xx.cc:73
struct x11_md x11_md
Definition: machine.h:179
void vr41xx_giu_interrupt_assert(struct interrupt *interrupt)
Definition: dev_vr41xx.cc:123
#define debug
Definition: dev_adb.cc:57
#define BCUCLKSPEED_DIVTSHFT
Definition: bcureg.h:449
#define BCUCLKSPEED_DIVT4
Definition: bcureg.h:446
#define KIUSCANS
Definition: vrkiureg.h:50
uint32_t line
Definition: interrupt.h:51
#define INTERRUPT_CONNECT(name, istruct)
Definition: interrupt.h:77
Definition: cpu.h:326
char * name
Definition: interrupt.h:66
int pending_timer_interrupts
Definition: dev_vr41xx.cc:76
uint16_t giumask
Definition: dev_vr41xx.cc:84
void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len, uint64_t data)
Definition: memory.cc:89
DEVICE_TICK(vr41xx)
Definition: dev_vr41xx.cc:400
#define BCU81REVID_REG_W
Definition: bcureg.h:411
void memory_device_register(struct memory *mem, const char *, uint64_t baseaddr, uint64_t len, int(*f)(struct cpu *, struct memory *, uint64_t, unsigned char *, size_t, int, void *), void *extra, int flags, unsigned char *dyntrans_data)
Definition: memory.cc:339
int in_use
Definition: machine.h:82
uint32_t kiu_offset
Definition: dev_vr41xx.cc:66
#define KIURST
Definition: vrkiureg.h:59
#define VRIP_INTR_KIU
Definition: vripreg.h:286
#define KIUDAT3
Definition: vrkiureg.h:46
Definition: memory.h:75
addr & if(addr >=0x24 &&page !=NULL)
#define BCUREVID_RID_4121
Definition: bcureg.h:417
struct interrupt cpu_irq
Definition: dev_vr41xx.cc:61
void machine_add_tickfunction(struct machine *machine, void(*func)(struct cpu *, void *), void *extra, int clockshift)
Definition: machine.cc:280
int kiu_console_handle
Definition: dev_vr41xx.cc:65
void * extra
Definition: interrupt.h:59
int machine_subtype
Definition: machine.h:112
#define BCUREVID_RID_4111
Definition: bcureg.h:418
#define KIUINT
Definition: vrkiureg.h:58
#define VRIP_INTR_GIU
Definition: vripreg.h:285
struct interrupt giu_irq
Definition: dev_vr41xx.cc:87
#define BCUREVID_RID_4101
Definition: bcureg.h:420
DEVICE_ACCESS(vr41xx)
Definition: dev_vr41xx.cc:480
uint16_t sysint2
Definition: dev_vr41xx.cc:85
#define BCUREVID_RID_4181
Definition: bcureg.h:421
#define MACHINE_HPCMIPS_NEC_MOBILEPRO_770
Definition: machine.h:285
#define INTERRUPT_DEASSERT(istruct)
Definition: interrupt.h:75
#define KIUDAT4
Definition: vrkiureg.h:47

Generated on Fri Dec 7 2018 19:52:23 for GXemul by doxygen 1.8.13