* THE SOFTWARE.
*/
-#include "vl.h"
+#include "hw.h"
+#include "pc.h"
+#include "isa.h"
+#include "audio/audio.h"
+#include "qemu-timer.h"
+#include "i8254.h"
+#include "pcspk.h"
#define PCSPK_BUF_LEN 1792
#define PCSPK_SAMPLE_RATE 32000
#define PCSPK_MIN_COUNT ((PIT_FREQ + PCSPK_MAX_FREQ - 1) / PCSPK_MAX_FREQ)
typedef struct {
+ ISADevice dev;
+ MemoryRegion ioport;
+ uint32_t iobase;
uint8_t sample_buf[PCSPK_BUF_LEN];
QEMUSoundCard card;
SWVoiceOut *voice;
- PITState *pit;
+ void *pit;
unsigned int pit_count;
unsigned int samples;
unsigned int play_pos;
} PCSpkState;
static const char *s_spk = "pcspk";
-static PCSpkState pcspk_state;
+static PCSpkState *pcspk_state;
static inline void generate_samples(PCSpkState *s)
{
static void pcspk_callback(void *opaque, int free)
{
PCSpkState *s = opaque;
+ PITChannelInfo ch;
unsigned int n;
- if (pit_get_mode(s->pit, 2) != 3)
+ pit_get_channel_info(s->pit, 2, &ch);
+
+ if (ch.mode != 3) {
return;
+ }
- n = pit_get_initial_count(s->pit, 2);
+ n = ch.initial_count;
/* avoid frequencies that are not reproducible with sample rate */
if (n < PCSPK_MIN_COUNT)
n = 0;
}
}
-int pcspk_audio_init(AudioState *audio)
+int pcspk_audio_init(ISABus *bus)
{
- PCSpkState *s = &pcspk_state;
- audsettings_t as = {PCSPK_SAMPLE_RATE, 1, AUD_FMT_U8};
+ PCSpkState *s = pcspk_state;
+ struct audsettings as = {PCSPK_SAMPLE_RATE, 1, AUD_FMT_U8, 0};
- if (!audio) {
- AUD_log(s_spk, "No audio state\n");
- return -1;
- }
- AUD_register_card(audio, s_spk, &s->card);
+ AUD_register_card(s_spk, &s->card);
- s->voice = AUD_open_out(&s->card, s->voice, s_spk, s, pcspk_callback, &as, 0);
+ s->voice = AUD_open_out(&s->card, s->voice, s_spk, s, pcspk_callback, &as);
if (!s->voice) {
AUD_log(s_spk, "Could not open voice\n");
return -1;
return 0;
}
-static uint32_t pcspk_ioport_read(void *opaque, uint32_t addr)
+static uint64_t pcspk_io_read(void *opaque, hwaddr addr,
+ unsigned size)
{
PCSpkState *s = opaque;
- int out;
+ PITChannelInfo ch;
+
+ pit_get_channel_info(s->pit, 2, &ch);
s->dummy_refresh_clock ^= (1 << 4);
- out = pit_get_out(s->pit, 2, qemu_get_clock(vm_clock)) << 5;
- return pit_get_gate(s->pit, 2) | (s->data_on << 1) | s->dummy_refresh_clock | out;
+ return ch.gate | (s->data_on << 1) | s->dummy_refresh_clock |
+ (ch.out << 5);
}
-static void pcspk_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+static void pcspk_io_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
{
PCSpkState *s = opaque;
const int gate = val & 1;
}
}
-void pcspk_init(PITState *pit)
+static const MemoryRegionOps pcspk_io_ops = {
+ .read = pcspk_io_read,
+ .write = pcspk_io_write,
+ .impl = {
+ .min_access_size = 1,
+ .max_access_size = 1,
+ },
+};
+
+static int pcspk_initfn(ISADevice *dev)
+{
+ PCSpkState *s = DO_UPCAST(PCSpkState, dev, dev);
+
+ memory_region_init_io(&s->ioport, &pcspk_io_ops, s, "elcr", 1);
+ isa_register_ioport(dev, &s->ioport, s->iobase);
+
+ pcspk_state = s;
+
+ return 0;
+}
+
+static Property pcspk_properties[] = {
+ DEFINE_PROP_HEX32("iobase", PCSpkState, iobase, -1),
+ DEFINE_PROP_PTR("pit", PCSpkState, pit),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void pcspk_class_initfn(ObjectClass *klass, void *data)
{
- PCSpkState *s = &pcspk_state;
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
- s->pit = pit;
- register_ioport_read(0x61, 1, 1, pcspk_ioport_read, s);
- register_ioport_write(0x61, 1, 1, pcspk_ioport_write, s);
+ ic->init = pcspk_initfn;
+ dc->no_user = 1;
+ dc->props = pcspk_properties;
+}
+
+static TypeInfo pcspk_info = {
+ .name = "isa-pcspk",
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof(PCSpkState),
+ .class_init = pcspk_class_initfn,
+};
+
+static void pcspk_register(void)
+{
+ type_register_static(&pcspk_info);
}
+type_init(pcspk_register)