qemu
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 "qemu/osdep.h"26#include "hw/sysbus.h"27#include "migration/vmstate.h"28#include "qemu/module.h"29#include "trace.h"30#include "qom/object.h"31
32/*
33* In addition to Crystal CS4231 there is a DMA controller on Sparc.
34*/
35#define CS_SIZE 0x4036#define CS_REGS 1637#define CS_DREGS 3238#define CS_MAXDREG (CS_DREGS - 1)39
40#define TYPE_CS4231 "sun-CS4231"41typedef struct CSState CSState;42DECLARE_INSTANCE_CHECKER(CSState, CS4231,43TYPE_CS4231)44
45struct CSState {46SysBusDevice parent_obj;47
48MemoryRegion iomem;49qemu_irq irq;50uint32_t regs[CS_REGS];51uint8_t dregs[CS_DREGS];52};53
54#define CS_RAP(s) ((s)->regs[0] & CS_MAXDREG)55#define CS_VER 0xa056#define CS_CDC_VER 0x8a57
58static void cs_reset(DeviceState *d)59{
60CSState *s = CS4231(d);61
62memset(s->regs, 0, CS_REGS * 4);63memset(s->dregs, 0, CS_DREGS);64s->dregs[12] = CS_CDC_VER;65s->dregs[25] = CS_VER;66}
67
68static uint64_t cs_mem_read(void *opaque, hwaddr addr,69unsigned size)70{
71CSState *s = opaque;72uint32_t saddr, ret;73
74saddr = addr >> 2;75switch (saddr) {76case 1:77switch (CS_RAP(s)) {78case 3: // Write only79ret = 0;80break;81default:82ret = s->dregs[CS_RAP(s)];83break;84}85trace_cs4231_mem_readl_dreg(CS_RAP(s), ret);86break;87default:88ret = s->regs[saddr];89trace_cs4231_mem_readl_reg(saddr, ret);90break;91}92return ret;93}
94
95static void cs_mem_write(void *opaque, hwaddr addr,96uint64_t val, unsigned size)97{
98CSState *s = opaque;99uint32_t saddr;100
101saddr = addr >> 2;102trace_cs4231_mem_writel_reg(saddr, s->regs[saddr], val);103switch (saddr) {104case 1:105trace_cs4231_mem_writel_dreg(CS_RAP(s), s->dregs[CS_RAP(s)], val);106switch(CS_RAP(s)) {107case 11:108case 25: // Read only109break;110case 12:111val &= 0x40;112val |= CS_CDC_VER; // Codec version113s->dregs[CS_RAP(s)] = val;114break;115default:116s->dregs[CS_RAP(s)] = val;117break;118}119break;120case 2: // Read only121break;122case 4:123if (val & 1) {124cs_reset(DEVICE(s));125}126val &= 0x7f;127s->regs[saddr] = val;128break;129default:130s->regs[saddr] = val;131break;132}133}
134
135static const MemoryRegionOps cs_mem_ops = {136.read = cs_mem_read,137.write = cs_mem_write,138.endianness = DEVICE_NATIVE_ENDIAN,139};140
141static const VMStateDescription vmstate_cs4231 = {142.name ="cs4231",143.version_id = 1,144.minimum_version_id = 1,145.fields = (const VMStateField[]) {146VMSTATE_UINT32_ARRAY(regs, CSState, CS_REGS),147VMSTATE_UINT8_ARRAY(dregs, CSState, CS_DREGS),148VMSTATE_END_OF_LIST()149}150};151
152static void cs4231_init(Object *obj)153{
154CSState *s = CS4231(obj);155SysBusDevice *dev = SYS_BUS_DEVICE(obj);156
157memory_region_init_io(&s->iomem, obj, &cs_mem_ops, s, "cs4321",158CS_SIZE);159sysbus_init_mmio(dev, &s->iomem);160sysbus_init_irq(dev, &s->irq);161}
162
163static void cs4231_class_init(ObjectClass *klass, void *data)164{
165DeviceClass *dc = DEVICE_CLASS(klass);166
167dc->reset = cs_reset;168dc->vmsd = &vmstate_cs4231;169}
170
171static const TypeInfo cs4231_info = {172.name = TYPE_CS4231,173.parent = TYPE_SYS_BUS_DEVICE,174.instance_size = sizeof(CSState),175.instance_init = cs4231_init,176.class_init = cs4231_class_init,177};178
179static void cs4231_register_types(void)180{
181type_register_static(&cs4231_info);182}
183
184type_init(cs4231_register_types)185