Statistics
| Branch: | Revision:

root / hw / cs4231.c @ ff90d503

History | View | Annotate | Download (4.5 kB)

1
/*
2
 * QEMU Crystal CS4231 audio chip emulation
3
 *
4
 * Copyright (c) 2006 Fabrice Bellard
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24

    
25
#include "sysbus.h"
26
#include "trace.h"
27

    
28
/*
29
 * In addition to Crystal CS4231 there is a DMA controller on Sparc.
30
 */
31
#define CS_SIZE 0x40
32
#define CS_REGS 16
33
#define CS_DREGS 32
34
#define CS_MAXDREG (CS_DREGS - 1)
35

    
36
typedef struct CSState {
37
    SysBusDevice busdev;
38
    qemu_irq irq;
39
    uint32_t regs[CS_REGS];
40
    uint8_t dregs[CS_DREGS];
41
} CSState;
42

    
43
#define CS_RAP(s) ((s)->regs[0] & CS_MAXDREG)
44
#define CS_VER 0xa0
45
#define CS_CDC_VER 0x8a
46

    
47
static void cs_reset(DeviceState *d)
48
{
49
    CSState *s = container_of(d, CSState, busdev.qdev);
50

    
51
    memset(s->regs, 0, CS_REGS * 4);
52
    memset(s->dregs, 0, CS_DREGS);
53
    s->dregs[12] = CS_CDC_VER;
54
    s->dregs[25] = CS_VER;
55
}
56

    
57
static uint32_t cs_mem_readl(void *opaque, target_phys_addr_t addr)
58
{
59
    CSState *s = opaque;
60
    uint32_t saddr, ret;
61

    
62
    saddr = addr >> 2;
63
    switch (saddr) {
64
    case 1:
65
        switch (CS_RAP(s)) {
66
        case 3: // Write only
67
            ret = 0;
68
            break;
69
        default:
70
            ret = s->dregs[CS_RAP(s)];
71
            break;
72
        }
73
        trace_cs4231_mem_readl_dreg(CS_RAP(s), ret);
74
        break;
75
    default:
76
        ret = s->regs[saddr];
77
        trace_cs4231_mem_readl_reg(saddr, ret);
78
        break;
79
    }
80
    return ret;
81
}
82

    
83
static void cs_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
84
{
85
    CSState *s = opaque;
86
    uint32_t saddr;
87

    
88
    saddr = addr >> 2;
89
    trace_cs4231_mem_writel_reg(saddr, s->regs[saddr], val);
90
    switch (saddr) {
91
    case 1:
92
        trace_cs4231_mem_writel_dreg(CS_RAP(s), s->dregs[CS_RAP(s)], val);
93
        switch(CS_RAP(s)) {
94
        case 11:
95
        case 25: // Read only
96
            break;
97
        case 12:
98
            val &= 0x40;
99
            val |= CS_CDC_VER; // Codec version
100
            s->dregs[CS_RAP(s)] = val;
101
            break;
102
        default:
103
            s->dregs[CS_RAP(s)] = val;
104
            break;
105
        }
106
        break;
107
    case 2: // Read only
108
        break;
109
    case 4:
110
        if (val & 1) {
111
            cs_reset(&s->busdev.qdev);
112
        }
113
        val &= 0x7f;
114
        s->regs[saddr] = val;
115
        break;
116
    default:
117
        s->regs[saddr] = val;
118
        break;
119
    }
120
}
121

    
122
static CPUReadMemoryFunc * const cs_mem_read[3] = {
123
    cs_mem_readl,
124
    cs_mem_readl,
125
    cs_mem_readl,
126
};
127

    
128
static CPUWriteMemoryFunc * const cs_mem_write[3] = {
129
    cs_mem_writel,
130
    cs_mem_writel,
131
    cs_mem_writel,
132
};
133

    
134
static const VMStateDescription vmstate_cs4231 = {
135
    .name ="cs4231",
136
    .version_id = 1,
137
    .minimum_version_id = 1,
138
    .minimum_version_id_old = 1,
139
    .fields      = (VMStateField []) {
140
        VMSTATE_UINT32_ARRAY(regs, CSState, CS_REGS),
141
        VMSTATE_UINT8_ARRAY(dregs, CSState, CS_DREGS),
142
        VMSTATE_END_OF_LIST()
143
    }
144
};
145

    
146
static int cs4231_init1(SysBusDevice *dev)
147
{
148
    int io;
149
    CSState *s = FROM_SYSBUS(CSState, dev);
150

    
151
    io = cpu_register_io_memory(cs_mem_read, cs_mem_write, s,
152
                                DEVICE_NATIVE_ENDIAN);
153
    sysbus_init_mmio(dev, CS_SIZE, io);
154
    sysbus_init_irq(dev, &s->irq);
155

    
156
    return 0;
157
}
158

    
159
static SysBusDeviceInfo cs4231_info = {
160
    .init = cs4231_init1,
161
    .qdev.name  = "SUNW,CS4231",
162
    .qdev.size  = sizeof(CSState),
163
    .qdev.vmsd  = &vmstate_cs4231,
164
    .qdev.reset = cs_reset,
165
    .qdev.props = (Property[]) {
166
        {.name = NULL}
167
    }
168
};
169

    
170
static void cs4231_register_devices(void)
171
{
172
    sysbus_register_withprop(&cs4231_info);
173
}
174

    
175
device_init(cs4231_register_devices)