--- trunk/src/devices/dev_vr41xx.c 2007/10/08 16:20:40 30 +++ trunk/src/devices/dev_vr41xx.c 2007/10/08 16:20:58 32 @@ -25,7 +25,7 @@ * SUCH DAMAGE. * * - * $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 $ * * VR41xx (actually, VR4122 and VR4131) misc functions. * @@ -43,13 +43,15 @@ #include "machine.h" #include "memory.h" #include "misc.h" +#include "timer.h" #include "bcureg.h" #include "vripreg.h" #include "vrkiureg.h" +#include "vr_rtcreg.h" -#define DEV_VR41XX_TICKSHIFT 15 +#define DEV_VR41XX_TICKSHIFT 14 /* #define debug fatal */ @@ -73,14 +75,12 @@ /* * Keyboard input: * - * Hardcoded for MobilePro 780. (See NetBSD's hpckbdkeymap.h for + * Hardcoded for MobilePro. (See NetBSD's hpckbdkeymap.h for * info on other keyboard layouts. mobilepro780_keytrans is the * one used here.) * * TODO: Make this work with "any" keyboard layout. * - * (Even MobilePro 770 seems to be different? Hm. TODO) - * * ofs 0: * 8000='o' 4000='.' 2000=DOWN 1000=UP * 800=';' 400=''' 200='[' 100=? @@ -147,13 +147,26 @@ d->escape_state = 2; break; case 2: /* cursor keys etc: */ - switch (ch) { - case 'A': d->d0 = 0x1000; break; - case 'B': d->d0 = 0x2000; break; - case 'C': d->d0 = 0x20; break; - case 'D': d->d0 = 0x10; break; - default: fatal("[ vr41xx kiu: " - "unimplemented escape 0x%02 ]\n", ch); + /* Ugly hack for Mobilepro770: */ + if (cpu->machine->machine_subtype == + MACHINE_HPCMIPS_NEC_MOBILEPRO_770) { + switch (ch) { + case 'A': d->d0 = 0x2000; break; + case 'B': d->d0 = 0x20; break; + case 'C': d->d0 = 0x1000; break; + case 'D': d->d0 = 0x10; break; + default: fatal("[ vr41xx kiu: unimpl" + "emented escape 0x%02 ]\n", ch); + } + } else { + switch (ch) { + case 'A': d->d0 = 0x1000; break; + case 'B': d->d0 = 0x2000; break; + case 'C': d->d0 = 0x20; break; + case 'D': d->d0 = 0x10; break; + default: fatal("[ vr41xx kiu: unimpl" + "emented escape 0x%02 ]\n", ch); + } } d->escape_state = 0; } @@ -289,26 +302,25 @@ } +/* + * timer_tick(): + */ +static void timer_tick(struct timer *timer, void *extra) +{ + struct vr41xx_data *d = (struct vr41xx_data *) extra; + d->pending_timer_interrupts ++; +} + + DEVICE_TICK(vr41xx) { struct vr41xx_data *d = extra; - /* - * UGLY! TODO: fix this. - * - * Interrupts should be triggered if the corresponding unit (for - * example the RTC unit) is activated. - */ - { - 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); - } + if (d->pending_timer_interrupts > 0) { + if (d->cpumodel == 4121 || d->cpumodel == 4181) + cpu_interrupt(cpu, 3); + else + cpu_interrupt(cpu, 8 + VRIP_INTR_ETIMER); } if (cpu->machine->use_x11) @@ -407,6 +419,7 @@ /* TODO: Maybe these should be handled separately as well? */ switch (relative_addr) { + /* BCU: 0x00 .. 0x1c */ case BCUREVID_REG_W: /* 0x010 */ case BCU81REVID_REG_W: /* 0x014 */ @@ -483,8 +496,42 @@ d->msysint2 = idata; break; - /* PMU: 0xc0 .. 0xfc */ - /* RTC: 0x100 .. ? */ + /* RTC: */ + case 0xc0: + case 0xc2: + case 0xc4: + { + struct timeval tv; + gettimeofday(&tv, NULL); + /* Adjust time by 120 years and 29 days. */ + tv.tv_sec += (int64_t) (120*365 + 29) * 24*60*60; + + switch (relative_addr) { + case 0xc0: + odata = (tv.tv_sec & 1) << 15; + break; + case 0xc2: + odata = (tv.tv_sec >> 1) & 0xffff; + break; + case 0xc4: + odata = (tv.tv_sec >> 17) & 0xffff; + break; + } + } + break; + + case 0xd0: /* RTCL1_L_REG_W */ + if (writeflag == MEM_WRITE && idata != 0) { + int hz = RTCL1_L_HZ / idata; + debug("[ vr41xx: rtc interrupts at %i Hz ]\n", hz); + if (d->timer == NULL) + d->timer = timer_add(hz, timer_tick, d); + else + timer_update_frequency(d->timer, hz); + } + break; + case 0xd2: /* RTCL1_H_REG_W */ + break; case 0x108: if (writeflag == MEM_READ) @@ -501,12 +548,16 @@ /* RTC interrupt register... */ /* Ack. timer interrupts? */ cpu_interrupt_ack(cpu, 8 + VRIP_INTR_ETIMER); + if (d->pending_timer_interrupts > 0) + d->pending_timer_interrupts --; break; case 0x1de: /* on 4121? */ /* RTC interrupt register... */ /* Ack. timer interrupts? */ cpu_interrupt_ack(cpu, 3); + if (d->pending_timer_interrupts > 0) + d->pending_timer_interrupts --; break; default: