]> Git Repo - qemu.git/blob - hw/cs4231.c
Merge remote-tracking branch 'kraxel/usb.29' into staging
[qemu.git] / hw / cs4231.c
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)
This page took 0.031256 seconds and 4 git commands to generate.