25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: dev_vr41xx.c,v 1.38 2006/07/23 19:36:04 debug Exp $ |
* $Id: dev_vr41xx.c,v 1.41 2006/10/02 09:26:53 debug Exp $ |
29 |
* |
* |
30 |
* VR41xx (actually, VR4122 and VR4131) misc functions. |
* VR41xx (actually, VR4122 and VR4131) misc functions. |
31 |
* |
* |
43 |
#include "machine.h" |
#include "machine.h" |
44 |
#include "memory.h" |
#include "memory.h" |
45 |
#include "misc.h" |
#include "misc.h" |
46 |
|
#include "timer.h" |
47 |
|
|
48 |
#include "bcureg.h" |
#include "bcureg.h" |
49 |
#include "vripreg.h" |
#include "vripreg.h" |
50 |
#include "vrkiureg.h" |
#include "vrkiureg.h" |
51 |
|
#include "vr_rtcreg.h" |
52 |
|
|
53 |
|
|
54 |
#define DEV_VR41XX_TICKSHIFT 15 |
#define DEV_VR41XX_TICKSHIFT 14 |
55 |
|
|
56 |
/* #define debug fatal */ |
/* #define debug fatal */ |
57 |
|
|
75 |
/* |
/* |
76 |
* Keyboard input: |
* Keyboard input: |
77 |
* |
* |
78 |
* Hardcoded for MobilePro 780. (See NetBSD's hpckbdkeymap.h for |
* Hardcoded for MobilePro. (See NetBSD's hpckbdkeymap.h for |
79 |
* info on other keyboard layouts. mobilepro780_keytrans is the |
* info on other keyboard layouts. mobilepro780_keytrans is the |
80 |
* one used here.) |
* one used here.) |
81 |
* |
* |
82 |
* TODO: Make this work with "any" keyboard layout. |
* TODO: Make this work with "any" keyboard layout. |
83 |
* |
* |
|
* (Even MobilePro 770 seems to be different? Hm. TODO) |
|
|
* |
|
84 |
* ofs 0: |
* ofs 0: |
85 |
* 8000='o' 4000='.' 2000=DOWN 1000=UP |
* 8000='o' 4000='.' 2000=DOWN 1000=UP |
86 |
* 800=';' 400=''' 200='[' 100=? |
* 800=';' 400=''' 200='[' 100=? |
147 |
d->escape_state = 2; |
d->escape_state = 2; |
148 |
break; |
break; |
149 |
case 2: /* cursor keys etc: */ |
case 2: /* cursor keys etc: */ |
150 |
switch (ch) { |
/* Ugly hack for Mobilepro770: */ |
151 |
case 'A': d->d0 = 0x1000; break; |
if (cpu->machine->machine_subtype == |
152 |
case 'B': d->d0 = 0x2000; break; |
MACHINE_HPCMIPS_NEC_MOBILEPRO_770) { |
153 |
case 'C': d->d0 = 0x20; break; |
switch (ch) { |
154 |
case 'D': d->d0 = 0x10; break; |
case 'A': d->d0 = 0x2000; break; |
155 |
default: fatal("[ vr41xx kiu: " |
case 'B': d->d0 = 0x20; break; |
156 |
"unimplemented escape 0x%02 ]\n", ch); |
case 'C': d->d0 = 0x1000; break; |
157 |
|
case 'D': d->d0 = 0x10; break; |
158 |
|
default: fatal("[ vr41xx kiu: unimpl" |
159 |
|
"emented escape 0x%02 ]\n", ch); |
160 |
|
} |
161 |
|
} else { |
162 |
|
switch (ch) { |
163 |
|
case 'A': d->d0 = 0x1000; break; |
164 |
|
case 'B': d->d0 = 0x2000; break; |
165 |
|
case 'C': d->d0 = 0x20; break; |
166 |
|
case 'D': d->d0 = 0x10; break; |
167 |
|
default: fatal("[ vr41xx kiu: unimpl" |
168 |
|
"emented escape 0x%02 ]\n", ch); |
169 |
|
} |
170 |
} |
} |
171 |
d->escape_state = 0; |
d->escape_state = 0; |
172 |
} |
} |
302 |
} |
} |
303 |
|
|
304 |
|
|
305 |
|
/* |
306 |
|
* timer_tick(): |
307 |
|
*/ |
308 |
|
static void timer_tick(struct timer *timer, void *extra) |
309 |
|
{ |
310 |
|
struct vr41xx_data *d = (struct vr41xx_data *) extra; |
311 |
|
d->pending_timer_interrupts ++; |
312 |
|
} |
313 |
|
|
314 |
|
|
315 |
DEVICE_TICK(vr41xx) |
DEVICE_TICK(vr41xx) |
316 |
{ |
{ |
317 |
struct vr41xx_data *d = extra; |
struct vr41xx_data *d = extra; |
318 |
|
|
319 |
/* |
if (d->pending_timer_interrupts > 0) { |
320 |
* UGLY! TODO: fix this. |
if (d->cpumodel == 4121 || d->cpumodel == 4181) |
321 |
* |
cpu_interrupt(cpu, 3); |
322 |
* Interrupts should be triggered if the corresponding unit (for |
else |
323 |
* example the RTC unit) is activated. |
cpu_interrupt(cpu, 8 + VRIP_INTR_ETIMER); |
|
*/ |
|
|
{ |
|
|
static unsigned int x = 0; |
|
|
x++; |
|
|
|
|
|
if (x > 100 && (x&3)==0) { |
|
|
if (d->cpumodel == 4121 || d->cpumodel == 4181) |
|
|
cpu_interrupt(cpu, 3); |
|
|
else |
|
|
cpu_interrupt(cpu, 8 + VRIP_INTR_ETIMER); |
|
|
} |
|
324 |
} |
} |
325 |
|
|
326 |
if (cpu->machine->use_x11) |
if (cpu->machine->use_x11) |
419 |
/* TODO: Maybe these should be handled separately as well? */ |
/* TODO: Maybe these should be handled separately as well? */ |
420 |
|
|
421 |
switch (relative_addr) { |
switch (relative_addr) { |
422 |
|
|
423 |
/* BCU: 0x00 .. 0x1c */ |
/* BCU: 0x00 .. 0x1c */ |
424 |
case BCUREVID_REG_W: /* 0x010 */ |
case BCUREVID_REG_W: /* 0x010 */ |
425 |
case BCU81REVID_REG_W: /* 0x014 */ |
case BCU81REVID_REG_W: /* 0x014 */ |
496 |
d->msysint2 = idata; |
d->msysint2 = idata; |
497 |
break; |
break; |
498 |
|
|
499 |
/* PMU: 0xc0 .. 0xfc */ |
/* RTC: */ |
500 |
/* RTC: 0x100 .. ? */ |
case 0xc0: |
501 |
|
case 0xc2: |
502 |
|
case 0xc4: |
503 |
|
{ |
504 |
|
struct timeval tv; |
505 |
|
gettimeofday(&tv, NULL); |
506 |
|
/* Adjust time by 120 years and 29 days. */ |
507 |
|
tv.tv_sec += (int64_t) (120*365 + 29) * 24*60*60; |
508 |
|
|
509 |
|
switch (relative_addr) { |
510 |
|
case 0xc0: |
511 |
|
odata = (tv.tv_sec & 1) << 15; |
512 |
|
break; |
513 |
|
case 0xc2: |
514 |
|
odata = (tv.tv_sec >> 1) & 0xffff; |
515 |
|
break; |
516 |
|
case 0xc4: |
517 |
|
odata = (tv.tv_sec >> 17) & 0xffff; |
518 |
|
break; |
519 |
|
} |
520 |
|
} |
521 |
|
break; |
522 |
|
|
523 |
|
case 0xd0: /* RTCL1_L_REG_W */ |
524 |
|
if (writeflag == MEM_WRITE && idata != 0) { |
525 |
|
int hz = RTCL1_L_HZ / idata; |
526 |
|
debug("[ vr41xx: rtc interrupts at %i Hz ]\n", hz); |
527 |
|
if (d->timer == NULL) |
528 |
|
d->timer = timer_add(hz, timer_tick, d); |
529 |
|
else |
530 |
|
timer_update_frequency(d->timer, hz); |
531 |
|
} |
532 |
|
break; |
533 |
|
case 0xd2: /* RTCL1_H_REG_W */ |
534 |
|
break; |
535 |
|
|
536 |
case 0x108: |
case 0x108: |
537 |
if (writeflag == MEM_READ) |
if (writeflag == MEM_READ) |
548 |
/* RTC interrupt register... */ |
/* RTC interrupt register... */ |
549 |
/* Ack. timer interrupts? */ |
/* Ack. timer interrupts? */ |
550 |
cpu_interrupt_ack(cpu, 8 + VRIP_INTR_ETIMER); |
cpu_interrupt_ack(cpu, 8 + VRIP_INTR_ETIMER); |
551 |
|
if (d->pending_timer_interrupts > 0) |
552 |
|
d->pending_timer_interrupts --; |
553 |
break; |
break; |
554 |
|
|
555 |
case 0x1de: /* on 4121? */ |
case 0x1de: /* on 4121? */ |
556 |
/* RTC interrupt register... */ |
/* RTC interrupt register... */ |
557 |
/* Ack. timer interrupts? */ |
/* Ack. timer interrupts? */ |
558 |
cpu_interrupt_ack(cpu, 3); |
cpu_interrupt_ack(cpu, 3); |
559 |
|
if (d->pending_timer_interrupts > 0) |
560 |
|
d->pending_timer_interrupts --; |
561 |
break; |
break; |
562 |
|
|
563 |
default: |
default: |