summaryrefslogtreecommitdiff
path: root/include/hw/misc/mos6522.h
blob: 97384c6e02cd261963826dd50eed07798c3b8ef9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*
 * QEMU MOS6522 VIA emulation
 *
 * Copyright (c) 2004-2007 Fabrice Bellard
 * Copyright (c) 2007 Jocelyn Mayer
 * Copyright (c) 2018 Mark Cave-Ayland
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#ifndef MOS6522_H
#define MOS6522_H

#include "exec/memory.h"
#include "hw/sysbus.h"
#include "hw/input/adb.h"

/* Bits in ACR */
#define SR_CTRL            0x1c    /* Shift register control bits */
#define SR_EXT             0x0c    /* Shift on external clock */
#define SR_OUT             0x10    /* Shift out if 1 */

/* Bits in IFR and IER */
#define IER_SET            0x80    /* set bits in IER */
#define IER_CLR            0       /* clear bits in IER */

#define CA2_INT            0x01
#define CA1_INT            0x02
#define SR_INT             0x04    /* Shift register full/empty */
#define CB2_INT            0x08
#define CB1_INT            0x10
#define T2_INT             0x20    /* Timer 2 interrupt */
#define T1_INT             0x40    /* Timer 1 interrupt */

/* Bits in ACR */
#define T1MODE             0xc0    /* Timer 1 mode */
#define T1MODE_CONT        0x40    /*  continuous interrupts */

/* VIA registers */
#define VIA_REG_B       0x00
#define VIA_REG_A       0x01
#define VIA_REG_DIRB    0x02
#define VIA_REG_DIRA    0x03
#define VIA_REG_T1CL    0x04
#define VIA_REG_T1CH    0x05
#define VIA_REG_T1LL    0x06
#define VIA_REG_T1LH    0x07
#define VIA_REG_T2CL    0x08
#define VIA_REG_T2CH    0x09
#define VIA_REG_SR      0x0a
#define VIA_REG_ACR     0x0b
#define VIA_REG_PCR     0x0c
#define VIA_REG_IFR     0x0d
#define VIA_REG_IER     0x0e
#define VIA_REG_ANH     0x0f

/**
 * MOS6522Timer:
 * @counter_value: counter value at load time
 */
typedef struct MOS6522Timer {
    int index;
    uint16_t latch;
    uint16_t counter_value;
    int64_t load_time;
    int64_t next_irq_time;
    uint64_t frequency;
    QEMUTimer *timer;
} MOS6522Timer;

/**
 * MOS6522State:
 * @b: B-side data
 * @a: A-side data
 * @dirb: B-side direction (1=output)
 * @dira: A-side direction (1=output)
 * @sr: Shift register
 * @acr: Auxiliary control register
 * @pcr: Peripheral control register
 * @ifr: Interrupt flag register
 * @ier: Interrupt enable register
 * @anh: A-side data, no handshake
 * @last_b: last value of B register
 * @last_acr: last value of ACR register
 */
typedef struct MOS6522State {
    /*< private >*/
    SysBusDevice parent_obj;
    /*< public >*/

    MemoryRegion mem;
    /* VIA registers */
    uint8_t b;
    uint8_t a;
    uint8_t dirb;
    uint8_t dira;
    uint8_t sr;
    uint8_t acr;
    uint8_t pcr;
    uint8_t ifr;
    uint8_t ier;

    MOS6522Timer timers[2];
    uint64_t frequency;

    qemu_irq irq;
} MOS6522State;

#define TYPE_MOS6522 "mos6522"
#define MOS6522(obj) OBJECT_CHECK(MOS6522State, (obj), TYPE_MOS6522)

typedef struct MOS6522DeviceClass {
    DeviceClass parent_class;

    DeviceReset parent_reset;
    void (*set_sr_int)(MOS6522State *dev);
    void (*portB_write)(MOS6522State *dev);
    void (*portA_write)(MOS6522State *dev);
    void (*update_irq)(MOS6522State *dev);
    /* These are used to influence the CUDA MacOS timebase calibration */
    uint64_t (*get_timer1_counter_value)(MOS6522State *dev, MOS6522Timer *ti);
    uint64_t (*get_timer2_counter_value)(MOS6522State *dev, MOS6522Timer *ti);
    uint64_t (*get_timer1_load_time)(MOS6522State *dev, MOS6522Timer *ti);
    uint64_t (*get_timer2_load_time)(MOS6522State *dev, MOS6522Timer *ti);
} MOS6522DeviceClass;

#define MOS6522_DEVICE_CLASS(cls) \
    OBJECT_CLASS_CHECK(MOS6522DeviceClass, (cls), TYPE_MOS6522)
#define MOS6522_DEVICE_GET_CLASS(obj) \
    OBJECT_GET_CLASS(MOS6522DeviceClass, (obj), TYPE_MOS6522)

extern const VMStateDescription vmstate_mos6522;

uint64_t mos6522_read(void *opaque, hwaddr addr, unsigned size);
void mos6522_write(void *opaque, hwaddr addr, uint64_t val, unsigned size);

#endif /* MOS6522_H */