Esempio n. 1
0
void viacore_signal(via_context_t *via_context, int line, int edge)
{
    switch (line) {
        case VIA_SIG_CA1:
            if ((edge ? 1 : 0) == (via_context->via[VIA_PCR] & 0x01)) {
                if (IS_CA2_TOGGLE_MODE() && !(via_context->ca2_state)) {
                    via_context->ca2_state = 1;
                    (via_context->set_ca2)(via_context, via_context->ca2_state);
                }
                via_context->ifr |= VIA_IM_CA1;
                update_myviairq(via_context);
#ifdef MYVIA_NEED_LATCHING
                if (IS_PA_INPUT_LATCH()) {
                    via_context->ila = (via_context->read_pra)(via_context, addr);
                }
#endif
            }
            break;
        case VIA_SIG_CA2:
            if (!(via_context->via[VIA_PCR] & 0x08)) {
                via_context->ifr |= (((edge << 2)
                                    ^ via_context->via[VIA_PCR]) & 0x04) ?
                                    0 : VIA_IM_CA2;
                update_myviairq(via_context);
            }
            break;
        case VIA_SIG_CB1:
            if ((edge ? 0x10 : 0) == (via_context->via[VIA_PCR] & 0x10)) {
                if (IS_CB2_TOGGLE_MODE() && !(via_context->cb2_state)) {
                    via_context->cb2_state = 1;
                    (via_context->set_cb2)(via_context, via_context->cb2_state);
                }
                via_context->ifr |= VIA_IM_CB1;
                update_myviairq(via_context);
#ifdef MYVIA_NEED_LATCHING
                if (IS_PB_INPUT_LATCH()) {
                    via_context->ilb = (via_context->read_prb)(via_context);
                }
#endif
            }
            break;
        case VIA_SIG_CB2:
            if (!(via_context->via[VIA_PCR] & 0x80)) {
                via_context->ifr |= (((edge << 6)
                                    ^ via_context->via[VIA_PCR]) & 0x40) ?
                                    0 : VIA_IM_CB2;
                update_myviairq(via_context);
            }
            break;
    }
}
Esempio n. 2
0
static void viacore_intt1(CLOCK offset, void *data)
{
    via_context_t *via_context = (via_context_t *)data;

#ifdef MYVIA_TIMER_DEBUG
    if (app_resources.debugFlag)
        log_message(via_context->log, "myvia timer A interrupt");
#endif

    if (!(via_context->via[VIA_ACR] & 0x40)) {     /* one-shot mode */
#ifdef MYVIA_TIMER_DEBUG
        log_message(via_context->log,
                    "MYVIA Timer A interrupt -- one-shot mode: next int won't happen");
#endif
        alarm_unset(via_context->t1_alarm);
        via_context->tai = 0;
    } else {                    /* continuous mode */
        /* load counter with latch value */
        via_context->tai += via_context->tal + 2;
        alarm_set(via_context->t1_alarm, via_context->tai);
    }
    via_context->ifr |= VIA_IM_T1;
    update_myviairq(via_context);

    /* TODO: toggle PB7? */
    /*(viaier & VIA_IM_T1) ? 1:0; */
}
Esempio n. 3
0
/*
 * according to Rockwell, all internal registers are cleared, except
 * for the Timer (1 and 2, counter and latches) and the shift register.
 */
void viacore_reset(via_context_t *via_context)
{
    int i;

    /* clear registers */
    for (i = 0; i < 4; i++) {
        via_context->via[i] = 0;
    }
    for (i = 4; i < 10; i++) {
        via_context->via[i] = 0xff;
    }
    for (i = 11; i < 16; i++) {
        via_context->via[i] = 0;
    }

    via_context->tal = 0xffff;
    via_context->t2cl = 0xff;
    via_context->t2ch = 0xff;
    via_context->tau = *(via_context->clk_ptr);
    via_context->tbu = *(via_context->clk_ptr);

    via_context->read_clk = 0;

    via_context->ier = 0;
    via_context->ifr = 0;

    via_context->pb7 = 0;
    via_context->pb7x = 0;
    via_context->pb7o = 0;
    via_context->pb7xx = 0;
    via_context->pb7sx = 0;

    via_context->shift_state = 0;

    /* disable vice interrupts */
    via_context->tai = 0;
    via_context->tbi = 0;
    alarm_unset(via_context->t1_alarm);
    alarm_unset(via_context->t2_alarm);
    update_myviairq(via_context);

    via_context->oldpa = 0xff;
    via_context->oldpb = 0xff;

    via_context->ca2_state = 1;
    via_context->cb2_state = 1;
    (via_context->set_ca2)(via_context, via_context->ca2_state);      /* input = high */
    (via_context->set_cb2)(via_context, via_context->cb2_state);      /* input = high */

    if (via_context && via_context->reset) {
        (via_context->reset)(via_context);
    }

    via_context->enabled = 1;
}
Esempio n. 4
0
static void viacore_intt2(CLOCK offset, void *data)
{
    via_context_t *via_context = (via_context_t *)data;

#ifdef MYVIA_TIMER_DEBUG
    if (app_resources.debugFlag)
        log_message(via_context->log, "MYVIA timer B interrupt.");
#endif

    alarm_unset(via_context->t2_alarm);       /*int_clk[I_MYVIAT2] = 0; */
    via_context->tbi = 0;

    via_context->ifr |= VIA_IM_T2;
    update_myviairq(via_context);
}
Esempio n. 5
0
void viacore_store(via_context_t *via_context, WORD addr, BYTE byte)
{
    CLOCK rclk;

    if (*(via_context->rmw_flag)) {
        (*(via_context->clk_ptr))--;
        *(via_context->rmw_flag) = 0;
        viacore_store(via_context, addr, via_context->last_read);
        (*(via_context->clk_ptr))++;
    }

    /* stores have a one-cycle offset if CLK++ happens before store */
    rclk = *(via_context->clk_ptr) - via_context->write_offset;

    addr &= 0xf;

    switch (addr) {
        /* these are done with saving the value */
        case VIA_PRA:           /* port A */
            via_context->ifr &= ~VIA_IM_CA1;
            if (!IS_CA2_INDINPUT()) {
                via_context->ifr &= ~VIA_IM_CA2;
            }
            if (IS_CA2_HANDSHAKE()) {
                via_context->ca2_state = 0;
                (via_context->set_ca2)(via_context, via_context->ca2_state);
                if (IS_CA2_PULSE_MODE()) {
                    via_context->ca2_state = 1;
                    (via_context->set_ca2)(via_context, via_context->ca2_state);
                }
            }
            if (via_context->ier & (VIA_IM_CA1 | VIA_IM_CA2)) {
                update_myviairq(via_context);
            }

        case VIA_PRA_NHS: /* port A, no handshake */
            via_context->via[VIA_PRA_NHS] = byte;
            addr = VIA_PRA;
        case VIA_DDRA:
            via_context->via[addr] = byte;
            byte = via_context->via[VIA_PRA] | ~(via_context->via[VIA_DDRA]);
            (via_context->store_pra)(via_context, byte, via_context->oldpa, addr);
            via_context->oldpa = byte;
            break;

        case VIA_PRB:           /* port B */
            via_context->ifr &= ~VIA_IM_CB1;
            if ((via_context->via[VIA_PCR] & 0xa0) != 0x20) {
                via_context->ifr &= ~VIA_IM_CB2;
            }
            if (IS_CB2_HANDSHAKE()) {
                via_context->cb2_state = 0;
                (via_context->set_cb2)(via_context, via_context->cb2_state);
                if (IS_CB2_PULSE_MODE()) {
                    via_context->cb2_state = 1;
                    (via_context->set_cb2)(via_context, via_context->cb2_state);
                }
            }
            if (via_context->ier & (VIA_IM_CB1 | VIA_IM_CB2)) {
                update_myviairq(via_context);
            }

        case VIA_DDRB:
            via_context->via[addr] = byte;
            byte = via_context->via[VIA_PRB] | ~(via_context->via[VIA_DDRB]);
            (via_context->store_prb)(via_context, byte, via_context->oldpb, addr);
            via_context->oldpb = byte;
            break;

        case VIA_SR:            /* Serial Port output buffer */
            via_context->via[addr] = byte;

            /* shift state can only be reset once 8 bits are complete */
            if (via_context->ifr & VIA_IM_SR) {
                via_context->ifr &= ~VIA_IM_SR;
                update_myviairq(via_context);
                via_context->shift_state = 0;
            }
            (via_context->store_sr)(via_context, byte);
            break;

        /* Timers */

        case VIA_T1CL:
        case VIA_T1LL:
            via_context->via[VIA_T1LL] = byte;
            update_myviatal(via_context, rclk);
            break;

        case VIA_T1CH:  /* Write timer A high */
            via_context->via[VIA_T1LH] = byte;
            update_myviatal(via_context, rclk);
            /* load counter with latch value */
            via_context->tau = rclk + via_context->tal + 3 + TAUOFFSET;
            via_context->tai = rclk + via_context->tal + 2;
            alarm_set(via_context->t1_alarm, via_context->tai);

            /* set pb7 state */
            via_context->pb7 = 0;
            via_context->pb7o = 0;

            /* Clear T1 interrupt */
            via_context->ifr &= ~VIA_IM_T1;
            update_myviairq(via_context);
            break;

        case VIA_T1LH:          /* Write timer A high order latch */
            via_context->via[addr] = byte;
            update_myviatal(via_context, rclk);
            /* IF: Does not change T1 interrupt, see Synertek notes */
            break;

        case VIA_T2LL:          /* Write timer 2 low latch */
            via_context->via[VIA_T2LL] = byte;
            (via_context->store_t2l)(via_context, byte);
            break;

        case VIA_T2CH:            /* Write timer 2 high counter/latch */
            /* update counter and latch values */
            via_context->via[VIA_T2LH] = byte;
            via_context->t2cl = via_context->via[VIA_T2LL];
            via_context->t2ch = byte;

            /* start T2 only in timer mode, leave unchanged in pulse counting mode */
            if (!(via_context->via[VIA_ACR] & 0x20)) {
                /* set the next alarm to the low latch value as timer cascading mode change 
                matters at each underflow of the T2 low counter */
                via_context->tbu = rclk + via_context->t2cl + 3;
                via_context->tbi = rclk + via_context->t2cl + 2;
                alarm_set(via_context->t2_alarm, via_context->tbi);
            }

            /* Clear T2 interrupt */
            via_context->ifr &= ~VIA_IM_T2;
            update_myviairq(via_context);
            break;

        /* Interrupts */

        case VIA_IFR:           /* 6522 Interrupt Flag Register */
            via_context->ifr &= ~byte;
            update_myviairq(via_context);

            /* FIXME: clearing any timer interrupt should set the relevant timer alarm */
            break;

        case VIA_IER:           /* Interrupt Enable Register */
            if (byte & VIA_IM_IRQ) {
                /* set interrupts */
                via_context->ier |= byte & 0x7f;
            } else {
                /* clear interrupts */
                via_context->ier &= ~byte;
            }
            update_myviairq(via_context);
            break;

        /* Control */

        case VIA_ACR:
            /* bit 7 timer 1 output to PB7 */
            update_myviatal(via_context, rclk);
            if ((via_context->via[VIA_ACR] ^ byte) & 0x80) {
                if (byte & 0x80) {
                    via_context->pb7 = 1 ^ via_context->pb7x;
                }
            }
            if ((via_context->via[VIA_ACR] ^ byte) & 0x40) {
                via_context->pb7 ^= via_context->pb7sx;
                if ((byte & 0x40)) {
                    if (via_context->pb7x || via_context->pb7xx) {
                        if (via_context->tal) {
                            via_context->pb7o = 1;
                        } else {
                            via_context->pb7o = 0;
                            if ((via_context->via[VIA_ACR] & 0x80)
                                && via_context->pb7x
                                && (!(via_context->pb7xx))) {
                                via_context->pb7 ^= 1;
                            }
                        }
                    }
                }
            }
            via_context->pb7sx = via_context->pb7x;

            /* bit 1, 0  latch enable port B and A */
#ifdef MYVIA_NEED_LATCHING
            /* switch on port A latching - FIXME: is this ok? */
            if ((!(via_context->via[addr] & 1)) && (byte & 1)) {
                via_context->ila = (via_context->read_pra)(via_context, addr);
            }
            /* switch on port B latching - FIXME: is this ok? */
            if ((!(via_context->via[addr] & 2)) && (byte & 2)) {
                via_context->ilb = (via_context->read_prb)(via_context);
            }
#endif

            /* switch between timer and pulse counting mode if bit 5 changes */
            if ((via_context->via[VIA_ACR] ^ byte) & 0x20) {
                if (byte & 0x20) {
                    /* Pulse counting mode: set t2 to the current T2 value; 
                    PB6 should always update t2 and update irq on underflow */
                    CLOCK stop = myviatb(via_context);
                    via_context->t2cl = (BYTE)(stop & 0xff);
                    via_context->t2ch = (BYTE)((stop >> 8) & 0xff);

                    /* stop alarm to prevent t2 and T2 updates */
                    alarm_unset(via_context->t2_alarm);
                    via_context->tbi = 0;
                } else {
                    /* Timer mode; set the next alarm to the low latch value as timer cascading mode change 
                    matters at each underflow of the T2 low counter */
                    via_context->tbu = rclk + via_context->t2cl + 3;
                    via_context->tbi = rclk + via_context->t2cl + 2;
                    alarm_set(via_context->t2_alarm, via_context->tbi);
                }
            }
Esempio n. 6
0
BYTE viacore_read_(via_context_t *via_context, WORD addr)
{
#endif
    BYTE byte = 0xff;
    CLOCK rclk;

    addr &= 0xf;

    via_context->read_clk = *(via_context->clk_ptr);
    via_context->read_offset = 0;
    rclk = *(via_context->clk_ptr);

    if (addr >= VIA_T1CL && addr <= VIA_IER) {
        if (via_context->tai && (via_context->tai < *(via_context->clk_ptr)))
            viacore_intt1(*(via_context->clk_ptr) - via_context->tai,
                          (void *)via_context);
        if (via_context->tbi && (via_context->tbi < *(via_context->clk_ptr)))
            viacore_intt2(*(via_context->clk_ptr) - via_context->tbi,
                          (void *)via_context);
    }

    switch (addr) {

      case VIA_PRA:             /* port A */
        via_context->ifr &= ~VIA_IM_CA1;
        if ((via_context->via[VIA_PCR] & 0x0a) != 0x02) {
            via_context->ifr &= ~VIA_IM_CA2;
        }
        if (IS_CA2_HANDSHAKE()) {
            via_context->ca2_state = 0;
            (via_context->set_ca2)(via_context, via_context->ca2_state);
            if (IS_CA2_PULSE_MODE()) {
                via_context->ca2_state = 1;
                (via_context->set_ca2)(via_context, via_context->ca2_state);
            }
        }
        if (via_context->ier & (VIA_IM_CA1 | VIA_IM_CA2))
            update_myviairq(via_context);

      case VIA_PRA_NHS: /* port A, no handshake */
        /* WARNING: this pin reads the voltage of the output pins, not
           the ORA value as the other port. Value read might be different
           from what is expected due to excessive load. */
#ifdef MYVIA_NEED_LATCHING
        if (IS_PA_INPUT_LATCH()) {
            byte = via_context->ila;
        } else {
            byte = (via_context->read_pra)(via_context, addr);
        }
#else
        byte = (via_context->read_pra)(via_context, addr);
#endif
        via_context->ila = byte;
        via_context->last_read = byte;
        return byte;

      case VIA_PRB:             /* port B */
        via_context->ifr &= ~VIA_IM_CB1;
        if ((via_context->via[VIA_PCR] & 0xa0) != 0x20)
            via_context->ifr &= ~VIA_IM_CB2;
        if (via_context->ier & (VIA_IM_CB1 | VIA_IM_CB2))
            update_myviairq(via_context);

        /* WARNING: this pin reads the ORA for output pins, not
           the voltage on the pins as the other port. */
#ifdef MYVIA_NEED_LATCHING
        if (IS_PB_INPUT_LATCH()) {
            byte = via_context->ilb;
        } else {
            byte = (via_context->read_prb)(via_context);
        }
#else
        byte = (via_context->read_prb)(via_context);
#endif
        via_context->ilb = byte;
        byte = (byte & ~(via_context->via[VIA_DDRB]))
               | (via_context->via[VIA_PRB] & via_context->via[VIA_DDRB]);

        if (via_context->via[VIA_ACR] & 0x80) {
            update_myviatal(via_context, rclk);
            byte = (byte & 0x7f)
                   | (((via_context->pb7 ^ via_context->pb7x)
                   | via_context->pb7o) ? 0x80 : 0);
        }
        via_context->last_read = byte;
        return byte;

        /* Timers */

      case VIA_T1CL /*TIMER_AL */ :     /* timer A low */
        via_context->ifr &= ~VIA_IM_T1;
        update_myviairq(via_context);
        via_context->last_read = (BYTE)(myviata(via_context) & 0xff);
        return via_context->last_read;

      case VIA_T1CH /*TIMER_AH */ :     /* timer A high */
        via_context->last_read = (BYTE)((myviata(via_context) >> 8) & 0xff);
        return via_context->last_read;

      case VIA_T2CL /*TIMER_BL */ :     /* timer B low */
        via_context->ifr &= ~VIA_IM_T2;
        update_myviairq(via_context);
        via_context->last_read = (BYTE)(myviatb(via_context) & 0xff);
        return via_context->last_read;

      case VIA_T2CH /*TIMER_BH */ :     /* timer B high */
        via_context->last_read = (BYTE)((myviatb(via_context) >> 8) & 0xff);
        return via_context->last_read;

      case VIA_SR:              /* Serial Port Shift Register */
        via_context->last_read = via_context->via[addr];
        return via_context->last_read;

        /* Interrupts */

      case VIA_IFR:             /* Interrupt Flag Register */
        {
            BYTE t = via_context->ifr;
            if (via_context->ifr & via_context->ier /*[VIA_IER] */ )
                t |= 0x80;
            via_context->last_read = t;
            return (t);
        }

      case VIA_IER:             /* 6522 Interrupt Control Register */
        via_context->last_read = (via_context->ier /*[VIA_IER] */  | 0x80);
        return via_context->last_read;

    }                           /* switch */

    via_context->last_read = via_context->via[addr];

    return via_context->via[addr];
}
Esempio n. 7
0
void viacore_store(via_context_t *via_context, WORD addr, BYTE byte)
{
    CLOCK rclk;

    if (*(via_context->rmw_flag)) {
        (*(via_context->clk_ptr))--;
        *(via_context->rmw_flag) = 0;
        viacore_store(via_context, addr, via_context->last_read);
        (*(via_context->clk_ptr))++;
    }

    /* stores have a one-cycle offset if CLK++ happens before store */
    rclk = *(via_context->clk_ptr) - via_context->write_offset;

    addr &= 0xf;

    switch (addr) {

      /* these are done with saving the value */
      case VIA_PRA:             /* port A */
        via_context->ifr &= ~VIA_IM_CA1;
        if (!IS_CA2_INDINPUT()) {
            via_context->ifr &= ~VIA_IM_CA2;
        }
        if (IS_CA2_HANDSHAKE()) {
            via_context->ca2_state = 0;
            (via_context->set_ca2)(via_context, via_context->ca2_state);
            if (IS_CA2_PULSE_MODE()) {
                via_context->ca2_state = 1;
                (via_context->set_ca2)(via_context, via_context->ca2_state);
            }
        }
        if (via_context->ier & (VIA_IM_CA1 | VIA_IM_CA2))
            update_myviairq(via_context);

      case VIA_PRA_NHS: /* port A, no handshake */
        via_context->via[VIA_PRA_NHS] = byte;
        addr = VIA_PRA;
      case VIA_DDRA:
        via_context->via[addr] = byte;
        byte = via_context->via[VIA_PRA] | ~(via_context->via[VIA_DDRA]);
        (via_context->store_pra)(via_context, byte, via_context->oldpa, addr);
        via_context->oldpa = byte;
        break;

      case VIA_PRB:             /* port B */
        via_context->ifr &= ~VIA_IM_CB1;
        if ((via_context->via[VIA_PCR] & 0xa0) != 0x20) {
            via_context->ifr &= ~VIA_IM_CB2;
        }
        if (IS_CB2_HANDSHAKE()) {
            via_context->cb2_state = 0;
            (via_context->set_cb2)(via_context, via_context->cb2_state);
            if (IS_CB2_PULSE_MODE()) {
                via_context->cb2_state = 1;
                (via_context->set_cb2)(via_context, via_context->cb2_state);
            }
        }
        if (via_context->ier & (VIA_IM_CB1 | VIA_IM_CB2))
            update_myviairq(via_context);

      case VIA_DDRB:
        via_context->via[addr] = byte;
        byte = via_context->via[VIA_PRB] | ~(via_context->via[VIA_DDRB]);
        (via_context->store_prb)(via_context, byte, via_context->oldpb, addr);
        via_context->oldpb = byte;
        break;

      case VIA_SR:              /* Serial Port output buffer */
        via_context->via[addr] = byte;
        (via_context->store_sr)(via_context, byte);
        break;

        /* Timers */

      case VIA_T1CL:
      case VIA_T1LL:
        via_context->via[VIA_T1LL] = byte;
        update_myviatal(via_context, rclk);
        break;

      case VIA_T1CH:    /* Write timer A high */
        via_context->via[VIA_T1LH] = byte;
        update_myviatal(via_context, rclk);
        /* load counter with latch value */
        via_context->tau = rclk + via_context->tal + 3 + TAUOFFSET;
        via_context->tai = rclk + via_context->tal + 2;
        alarm_set(via_context->t1_alarm, via_context->tai);

        /* set pb7 state */
        via_context->pb7 = 0;
        via_context->pb7o = 0;

        /* Clear T1 interrupt */
        via_context->ifr &= ~VIA_IM_T1;
        update_myviairq(via_context);
        break;

      case VIA_T1LH:            /* Write timer A high order latch */
        via_context->via[addr] = byte;
        update_myviatal(via_context, rclk);

        /* Clear T1 interrupt */
        via_context->ifr &= ~VIA_IM_T1;
        update_myviairq(via_context);
        break;

      case VIA_T2LL:            /* Write timer 2 low latch */
        via_context->via[VIA_T2LL] = byte;
        update_myviatbl(via_context);
        (via_context->store_t2l)(via_context, byte);
        break;

      case VIA_T2CH:            /* Write timer 2 high */
        via_context->via[VIA_T2CH] = byte;
        update_myviatbl(via_context);
        via_context->tbu = rclk + via_context->tbl + 3;
        via_context->tbi = rclk + via_context->tbl + 2;
        alarm_set(via_context->t2_alarm, via_context->tbi);

        /* Clear T2 interrupt */
        via_context->ifr &= ~VIA_IM_T2;
        update_myviairq(via_context);
        break;

        /* Interrupts */

      case VIA_IFR:             /* 6522 Interrupt Flag Register */
        via_context->ifr &= ~byte;
        update_myviairq(via_context);
        break;

      case VIA_IER:             /* Interrupt Enable Register */
        if (byte & VIA_IM_IRQ) {
            /* set interrupts */
            via_context->ier |= byte & 0x7f;
        } else {
            /* clear interrupts */
            via_context->ier &= ~byte;
        }
        update_myviairq(via_context);
        break;

        /* Control */

      case VIA_ACR:
        /* bit 7 timer 1 output to PB7 */
        update_myviatal(via_context, rclk);
        if ((via_context->via[VIA_ACR] ^ byte) & 0x80) {
            if (byte & 0x80) {
                via_context->pb7 = 1 ^ via_context->pb7x;
            }
        }
        if ((via_context->via[VIA_ACR] ^ byte) & 0x40) {
            via_context->pb7 ^= via_context->pb7sx;
            if ((byte & 0x40)) {
                if (via_context->pb7x || via_context->pb7xx) {
                    if (via_context->tal) {
                        via_context->pb7o = 1;
                    } else {
                        via_context->pb7o = 0;
                        if ((via_context->via[VIA_ACR] & 0x80)
                            && via_context->pb7x
                            && (!(via_context->pb7xx)))
                            via_context->pb7 ^= 1;
                    }
                }
            }
        }
        via_context->pb7sx = via_context->pb7x;

        /* bit 1, 0  latch enable port B and A */
#ifdef MYVIA_NEED_LATCHING
        /* switch on port A latching - FIXME: is this ok? */
        if ( (!(via_context->via[addr] & 1)) && (byte & 1)) {
            via_context->ila = (via_context->read_pra)(via_context, addr);
        }
        /* switch on port B latching - FIXME: is this ok? */
        if ((!(via_context->via[addr] & 2)) && (byte & 2)) {
            via_context->ilb = (via_context->read_prb)(via_context);
        }
#endif

        via_context->via[addr] = byte;
        (via_context->store_acr)(via_context, byte);

        /* bit 5 timer 2 count mode */
        if (byte & 32) {
            /* TODO */
            /* update_myviatb(0); *//* stop timer if mode == 1 */
        }

        /* bit 4, 3, 2 shift register control */

        break;

      case VIA_PCR:

        /* bit 7, 6, 5  CB2 handshake/interrupt control */
        /* bit 4  CB1 interrupt control */

        /* bit 3, 2, 1  CA2 handshake/interrupt control */
        /* bit 0  CA1 interrupt control */

        if ((byte & 0x0e) == 0x0c) {  /* set output low */
            via_context->ca2_state = 0;
        } else
        if ((byte & 0x0e) == 0x0e) {  /* set output high */
            via_context->ca2_state = 1;
        } else {                        /* set to toggle/pulse/input */
            /* FIXME: is this correct if handshake is already active? */
            via_context->ca2_state = 1;
        }
        (via_context->set_ca2)(via_context, via_context->ca2_state);

        if ((byte & 0xe0) == 0xc0) {  /* set output low */
            via_context->cb2_state = 0;
        } else
        if ((byte & 0xe0) == 0xe0) {  /* set output high */
            via_context->cb2_state = 1;
        } else {                        /* set to toggle/pulse/input */
            /* FIXME: is this correct if handshake is already active? */
            via_context->cb2_state = 1;
        }
        (via_context->set_cb2)(via_context, via_context->cb2_state);

        (via_context->store_pcr)(via_context, byte, addr);

        via_context->via[addr] = byte;

        break;

      default:
        via_context->via[addr] = byte;

    }                           /* switch */
}