qemu

Форк
0
/
ac97.c 
1368 строк · 36.3 Кб
1
/*
2
 * Copyright (C) 2006 InnoTek Systemberatung GmbH
3
 *
4
 * This file is part of VirtualBox Open Source Edition (OSE), as
5
 * available from http://www.virtualbox.org. This file is free software;
6
 * you can redistribute it and/or modify it under the terms of the GNU
7
 * General Public License as published by the Free Software Foundation,
8
 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
9
 * distribution. VirtualBox OSE is distributed in the hope that it will
10
 * be useful, but WITHOUT ANY WARRANTY of any kind.
11
 *
12
 * If you received this file as part of a commercial VirtualBox
13
 * distribution, then only the terms of your commercial VirtualBox
14
 * license agreement apply instead of the previous paragraph.
15
 *
16
 * Contributions after 2012-01-13 are licensed under the terms of the
17
 * GNU GPL, version 2 or (at your option) any later version.
18
 */
19

20
#include "qemu/osdep.h"
21
#include "hw/audio/soundhw.h"
22
#include "audio/audio.h"
23
#include "hw/pci/pci_device.h"
24
#include "hw/qdev-properties.h"
25
#include "migration/vmstate.h"
26
#include "qemu/module.h"
27
#include "sysemu/dma.h"
28
#include "qom/object.h"
29
#include "ac97.h"
30

31
#define SOFT_VOLUME
32
#define SR_FIFOE 16             /* rwc */
33
#define SR_BCIS  8              /* rwc */
34
#define SR_LVBCI 4              /* rwc */
35
#define SR_CELV  2              /* ro */
36
#define SR_DCH   1              /* ro */
37
#define SR_VALID_MASK ((1 << 5) - 1)
38
#define SR_WCLEAR_MASK (SR_FIFOE | SR_BCIS | SR_LVBCI)
39
#define SR_RO_MASK (SR_DCH | SR_CELV)
40
#define SR_INT_MASK (SR_FIFOE | SR_BCIS | SR_LVBCI)
41

42
#define CR_IOCE  16             /* rw */
43
#define CR_FEIE  8              /* rw */
44
#define CR_LVBIE 4              /* rw */
45
#define CR_RR    2              /* rw */
46
#define CR_RPBM  1              /* rw */
47
#define CR_VALID_MASK ((1 << 5) - 1)
48
#define CR_DONT_CLEAR_MASK (CR_IOCE | CR_FEIE | CR_LVBIE)
49

50
#define GC_WR    4              /* rw */
51
#define GC_CR    2              /* rw */
52
#define GC_VALID_MASK ((1 << 6) - 1)
53

54
#define GS_MD3   (1 << 17)      /* rw */
55
#define GS_AD3   (1 << 16)      /* rw */
56
#define GS_RCS   (1 << 15)      /* rwc */
57
#define GS_B3S12 (1 << 14)      /* ro */
58
#define GS_B2S12 (1 << 13)      /* ro */
59
#define GS_B1S12 (1 << 12)      /* ro */
60
#define GS_S1R1  (1 << 11)      /* rwc */
61
#define GS_S0R1  (1 << 10)      /* rwc */
62
#define GS_S1CR  (1 << 9)       /* ro */
63
#define GS_S0CR  (1 << 8)       /* ro */
64
#define GS_MINT  (1 << 7)       /* ro */
65
#define GS_POINT (1 << 6)       /* ro */
66
#define GS_PIINT (1 << 5)       /* ro */
67
#define GS_RSRVD ((1 << 4) | (1 << 3))
68
#define GS_MOINT (1 << 2)       /* ro */
69
#define GS_MIINT (1 << 1)       /* ro */
70
#define GS_GSCI  1              /* rwc */
71
#define GS_RO_MASK (GS_B3S12 | \
72
                    GS_B2S12 | \
73
                    GS_B1S12 | \
74
                    GS_S1CR  | \
75
                    GS_S0CR  | \
76
                    GS_MINT  | \
77
                    GS_POINT | \
78
                    GS_PIINT | \
79
                    GS_RSRVD | \
80
                    GS_MOINT | \
81
                    GS_MIINT)
82
#define GS_VALID_MASK ((1 << 18) - 1)
83
#define GS_WCLEAR_MASK (GS_RCS | GS_S1R1 | GS_S0R1 | GS_GSCI)
84

85
#define BD_IOC (1 << 31)
86
#define BD_BUP (1 << 30)
87

88
#define TYPE_AC97 "AC97"
89
OBJECT_DECLARE_SIMPLE_TYPE(AC97LinkState, AC97)
90

91
#define REC_MASK 7
92
enum {
93
    REC_MIC = 0,
94
    REC_CD,
95
    REC_VIDEO,
96
    REC_AUX,
97
    REC_LINE_IN,
98
    REC_STEREO_MIX,
99
    REC_MONO_MIX,
100
    REC_PHONE
101
};
102

103
typedef struct BD {
104
    uint32_t addr;
105
    uint32_t ctl_len;
106
} BD;
107

108
typedef struct AC97BusMasterRegs {
109
    uint32_t bdbar;             /* rw 0 */
110
    uint8_t civ;                /* ro 0 */
111
    uint8_t lvi;                /* rw 0 */
112
    uint16_t sr;                /* rw 1 */
113
    uint16_t picb;              /* ro 0 */
114
    uint8_t piv;                /* ro 0 */
115
    uint8_t cr;                 /* rw 0 */
116
    unsigned int bd_valid;
117
    BD bd;
118
} AC97BusMasterRegs;
119

120
struct AC97LinkState {
121
    PCIDevice dev;
122
    QEMUSoundCard card;
123
    uint32_t glob_cnt;
124
    uint32_t glob_sta;
125
    uint32_t cas;
126
    uint32_t last_samp;
127
    AC97BusMasterRegs bm_regs[3];
128
    uint8_t mixer_data[256];
129
    SWVoiceIn *voice_pi;
130
    SWVoiceOut *voice_po;
131
    SWVoiceIn *voice_mc;
132
    int invalid_freq[3];
133
    uint8_t silence[128];
134
    int bup_flag;
135
    MemoryRegion io_nam;
136
    MemoryRegion io_nabm;
137
};
138

139
enum {
140
    BUP_SET = 1,
141
    BUP_LAST = 2
142
};
143

144
#ifdef DEBUG_AC97
145
#define dolog(...) AUD_log("ac97", __VA_ARGS__)
146
#else
147
#define dolog(...)
148
#endif
149

150
#define MKREGS(prefix, start)                   \
151
enum {                                          \
152
    prefix ## _BDBAR = start,                   \
153
    prefix ## _CIV = start + 4,                 \
154
    prefix ## _LVI = start + 5,                 \
155
    prefix ## _SR = start + 6,                  \
156
    prefix ## _PICB = start + 8,                \
157
    prefix ## _PIV = start + 10,                \
158
    prefix ## _CR = start + 11                  \
159
}
160

161
enum {
162
    PI_INDEX = 0,
163
    PO_INDEX,
164
    MC_INDEX,
165
    LAST_INDEX
166
};
167

168
MKREGS(PI, PI_INDEX * 16);
169
MKREGS(PO, PO_INDEX * 16);
170
MKREGS(MC, MC_INDEX * 16);
171

172
enum {
173
    GLOB_CNT = 0x2c,
174
    GLOB_STA = 0x30,
175
    CAS      = 0x34
176
};
177

178
#define GET_BM(index) (((index) >> 4) & 3)
179

180
static void po_callback(void *opaque, int free);
181
static void pi_callback(void *opaque, int avail);
182
static void mc_callback(void *opaque, int avail);
183

184
static void fetch_bd(AC97LinkState *s, AC97BusMasterRegs *r)
185
{
186
    uint8_t b[8];
187

188
    pci_dma_read(&s->dev, r->bdbar + r->civ * 8, b, 8);
189
    r->bd_valid = 1;
190
    r->bd.addr = le32_to_cpu(*(uint32_t *) &b[0]) & ~3;
191
    r->bd.ctl_len = le32_to_cpu(*(uint32_t *) &b[4]);
192
    r->picb = r->bd.ctl_len & 0xffff;
193
    dolog("bd %2d addr=0x%x ctl=0x%06x len=0x%x(%d bytes)\n",
194
          r->civ, r->bd.addr, r->bd.ctl_len >> 16,
195
          r->bd.ctl_len & 0xffff, (r->bd.ctl_len & 0xffff) << 1);
196
}
197

198
static void update_sr(AC97LinkState *s, AC97BusMasterRegs *r, uint32_t new_sr)
199
{
200
    int event = 0;
201
    int level = 0;
202
    uint32_t new_mask = new_sr & SR_INT_MASK;
203
    uint32_t old_mask = r->sr & SR_INT_MASK;
204
    uint32_t masks[] = {GS_PIINT, GS_POINT, GS_MINT};
205

206
    if (new_mask ^ old_mask) {
207
        /** @todo is IRQ deasserted when only one of status bits is cleared? */
208
        if (!new_mask) {
209
            event = 1;
210
            level = 0;
211
        } else {
212
            if ((new_mask & SR_LVBCI) && (r->cr & CR_LVBIE)) {
213
                event = 1;
214
                level = 1;
215
            }
216
            if ((new_mask & SR_BCIS) && (r->cr & CR_IOCE)) {
217
                event = 1;
218
                level = 1;
219
            }
220
        }
221
    }
222

223
    r->sr = new_sr;
224

225
    dolog("IOC%d LVB%d sr=0x%x event=%d level=%d\n",
226
          r->sr & SR_BCIS, r->sr & SR_LVBCI, r->sr, event, level);
227

228
    if (!event) {
229
        return;
230
    }
231

232
    if (level) {
233
        s->glob_sta |= masks[r - s->bm_regs];
234
        dolog("set irq level=1\n");
235
        pci_irq_assert(&s->dev);
236
    } else {
237
        s->glob_sta &= ~masks[r - s->bm_regs];
238
        dolog("set irq level=0\n");
239
        pci_irq_deassert(&s->dev);
240
    }
241
}
242

243
static void voice_set_active(AC97LinkState *s, int bm_index, int on)
244
{
245
    switch (bm_index) {
246
    case PI_INDEX:
247
        AUD_set_active_in(s->voice_pi, on);
248
        break;
249

250
    case PO_INDEX:
251
        AUD_set_active_out(s->voice_po, on);
252
        break;
253

254
    case MC_INDEX:
255
        AUD_set_active_in(s->voice_mc, on);
256
        break;
257

258
    default:
259
        AUD_log("ac97", "invalid bm_index(%d) in voice_set_active", bm_index);
260
        break;
261
    }
262
}
263

264
static void reset_bm_regs(AC97LinkState *s, AC97BusMasterRegs *r)
265
{
266
    dolog("reset_bm_regs\n");
267
    r->bdbar = 0;
268
    r->civ = 0;
269
    r->lvi = 0;
270
    /** todo do we need to do that? */
271
    update_sr(s, r, SR_DCH);
272
    r->picb = 0;
273
    r->piv = 0;
274
    r->cr = r->cr & CR_DONT_CLEAR_MASK;
275
    r->bd_valid = 0;
276

277
    voice_set_active(s, r - s->bm_regs, 0);
278
    memset(s->silence, 0, sizeof(s->silence));
279
}
280

281
static void mixer_store(AC97LinkState *s, uint32_t i, uint16_t v)
282
{
283
    if (i + 2 > sizeof(s->mixer_data)) {
284
        dolog("mixer_store: index %d out of bounds %zd\n",
285
              i, sizeof(s->mixer_data));
286
        return;
287
    }
288

289
    s->mixer_data[i + 0] = v & 0xff;
290
    s->mixer_data[i + 1] = v >> 8;
291
}
292

293
static uint16_t mixer_load(AC97LinkState *s, uint32_t i)
294
{
295
    uint16_t val = 0xffff;
296

297
    if (i + 2 > sizeof(s->mixer_data)) {
298
        dolog("mixer_load: index %d out of bounds %zd\n",
299
              i, sizeof(s->mixer_data));
300
    } else {
301
        val = s->mixer_data[i + 0] | (s->mixer_data[i + 1] << 8);
302
    }
303

304
    return val;
305
}
306

307
static void open_voice(AC97LinkState *s, int index, int freq)
308
{
309
    struct audsettings as;
310

311
    as.freq = freq;
312
    as.nchannels = 2;
313
    as.fmt = AUDIO_FORMAT_S16;
314
    as.endianness = 0;
315

316
    if (freq > 0) {
317
        s->invalid_freq[index] = 0;
318
        switch (index) {
319
        case PI_INDEX:
320
            s->voice_pi = AUD_open_in(
321
                &s->card,
322
                s->voice_pi,
323
                "ac97.pi",
324
                s,
325
                pi_callback,
326
                &as
327
                );
328
            break;
329

330
        case PO_INDEX:
331
            s->voice_po = AUD_open_out(
332
                &s->card,
333
                s->voice_po,
334
                "ac97.po",
335
                s,
336
                po_callback,
337
                &as
338
                );
339
            break;
340

341
        case MC_INDEX:
342
            s->voice_mc = AUD_open_in(
343
                &s->card,
344
                s->voice_mc,
345
                "ac97.mc",
346
                s,
347
                mc_callback,
348
                &as
349
                );
350
            break;
351
        }
352
    } else {
353
        s->invalid_freq[index] = freq;
354
        switch (index) {
355
        case PI_INDEX:
356
            AUD_close_in(&s->card, s->voice_pi);
357
            s->voice_pi = NULL;
358
            break;
359

360
        case PO_INDEX:
361
            AUD_close_out(&s->card, s->voice_po);
362
            s->voice_po = NULL;
363
            break;
364

365
        case MC_INDEX:
366
            AUD_close_in(&s->card, s->voice_mc);
367
            s->voice_mc = NULL;
368
            break;
369
        }
370
    }
371
}
372

373
static void reset_voices(AC97LinkState *s, uint8_t active[LAST_INDEX])
374
{
375
    uint16_t freq;
376

377
    freq = mixer_load(s, AC97_PCM_LR_ADC_Rate);
378
    open_voice(s, PI_INDEX, freq);
379
    AUD_set_active_in(s->voice_pi, active[PI_INDEX]);
380

381
    freq = mixer_load(s, AC97_PCM_Front_DAC_Rate);
382
    open_voice(s, PO_INDEX, freq);
383
    AUD_set_active_out(s->voice_po, active[PO_INDEX]);
384

385
    freq = mixer_load(s, AC97_MIC_ADC_Rate);
386
    open_voice(s, MC_INDEX, freq);
387
    AUD_set_active_in(s->voice_mc, active[MC_INDEX]);
388
}
389

390
static void get_volume(uint16_t vol, uint16_t mask, int inverse,
391
                       int *mute, uint8_t *lvol, uint8_t *rvol)
392
{
393
    *mute = (vol >> MUTE_SHIFT) & 1;
394
    *rvol = (255 * (vol & mask)) / mask;
395
    *lvol = (255 * ((vol >> 8) & mask)) / mask;
396

397
    if (inverse) {
398
        *rvol = 255 - *rvol;
399
        *lvol = 255 - *lvol;
400
    }
401
}
402

403
static void update_combined_volume_out(AC97LinkState *s)
404
{
405
    uint8_t lvol, rvol, plvol, prvol;
406
    int mute, pmute;
407

408
    get_volume(mixer_load(s, AC97_Master_Volume_Mute), 0x3f, 1,
409
               &mute, &lvol, &rvol);
410
    get_volume(mixer_load(s, AC97_PCM_Out_Volume_Mute), 0x1f, 1,
411
               &pmute, &plvol, &prvol);
412

413
    mute = mute | pmute;
414
    lvol = (lvol * plvol) / 255;
415
    rvol = (rvol * prvol) / 255;
416

417
    AUD_set_volume_out(s->voice_po, mute, lvol, rvol);
418
}
419

420
static void update_volume_in(AC97LinkState *s)
421
{
422
    uint8_t lvol, rvol;
423
    int mute;
424

425
    get_volume(mixer_load(s, AC97_Record_Gain_Mute), 0x0f, 0,
426
               &mute, &lvol, &rvol);
427

428
    AUD_set_volume_in(s->voice_pi, mute, lvol, rvol);
429
}
430

431
static void set_volume(AC97LinkState *s, int index, uint32_t val)
432
{
433
    switch (index) {
434
    case AC97_Master_Volume_Mute:
435
        val &= 0xbf3f;
436
        mixer_store(s, index, val);
437
        update_combined_volume_out(s);
438
        break;
439
    case AC97_PCM_Out_Volume_Mute:
440
        val &= 0x9f1f;
441
        mixer_store(s, index, val);
442
        update_combined_volume_out(s);
443
        break;
444
    case AC97_Record_Gain_Mute:
445
        val &= 0x8f0f;
446
        mixer_store(s, index, val);
447
        update_volume_in(s);
448
        break;
449
    }
450
}
451

452
static void record_select(AC97LinkState *s, uint32_t val)
453
{
454
    uint8_t rs = val & REC_MASK;
455
    uint8_t ls = (val >> 8) & REC_MASK;
456
    mixer_store(s, AC97_Record_Select, rs | (ls << 8));
457
}
458

459
static void mixer_reset(AC97LinkState *s)
460
{
461
    uint8_t active[LAST_INDEX];
462

463
    dolog("mixer_reset\n");
464
    memset(s->mixer_data, 0, sizeof(s->mixer_data));
465
    memset(active, 0, sizeof(active));
466
    mixer_store(s, AC97_Reset, 0x0000); /* 6940 */
467
    mixer_store(s, AC97_Headphone_Volume_Mute, 0x0000);
468
    mixer_store(s, AC97_Master_Volume_Mono_Mute, 0x0000);
469
    mixer_store(s, AC97_Master_Tone_RL, 0x0000);
470
    mixer_store(s, AC97_PC_BEEP_Volume_Mute, 0x0000);
471
    mixer_store(s, AC97_Phone_Volume_Mute, 0x0000);
472
    mixer_store(s, AC97_Mic_Volume_Mute, 0x0000);
473
    mixer_store(s, AC97_Line_In_Volume_Mute, 0x0000);
474
    mixer_store(s, AC97_CD_Volume_Mute, 0x0000);
475
    mixer_store(s, AC97_Video_Volume_Mute, 0x0000);
476
    mixer_store(s, AC97_Aux_Volume_Mute, 0x0000);
477
    mixer_store(s, AC97_Record_Gain_Mic_Mute, 0x0000);
478
    mixer_store(s, AC97_General_Purpose, 0x0000);
479
    mixer_store(s, AC97_3D_Control, 0x0000);
480
    mixer_store(s, AC97_Powerdown_Ctrl_Stat, 0x000f);
481

482
    /*
483
     * Sigmatel 9700 (STAC9700)
484
     */
485
    mixer_store(s, AC97_Vendor_ID1, 0x8384);
486
    mixer_store(s, AC97_Vendor_ID2, 0x7600); /* 7608 */
487

488
    mixer_store(s, AC97_Extended_Audio_ID, 0x0809);
489
    mixer_store(s, AC97_Extended_Audio_Ctrl_Stat, 0x0009);
490
    mixer_store(s, AC97_PCM_Front_DAC_Rate, 0xbb80);
491
    mixer_store(s, AC97_PCM_Surround_DAC_Rate, 0xbb80);
492
    mixer_store(s, AC97_PCM_LFE_DAC_Rate, 0xbb80);
493
    mixer_store(s, AC97_PCM_LR_ADC_Rate, 0xbb80);
494
    mixer_store(s, AC97_MIC_ADC_Rate, 0xbb80);
495

496
    record_select(s, 0);
497
    set_volume(s, AC97_Master_Volume_Mute, 0x8000);
498
    set_volume(s, AC97_PCM_Out_Volume_Mute, 0x8808);
499
    set_volume(s, AC97_Record_Gain_Mute, 0x8808);
500

501
    reset_voices(s, active);
502
}
503

504
/**
505
 * Native audio mixer
506
 * I/O Reads
507
 */
508
static uint32_t nam_readb(void *opaque, uint32_t addr)
509
{
510
    AC97LinkState *s = opaque;
511
    dolog("U nam readb 0x%x\n", addr);
512
    s->cas = 0;
513
    return ~0U;
514
}
515

516
static uint32_t nam_readw(void *opaque, uint32_t addr)
517
{
518
    AC97LinkState *s = opaque;
519
    s->cas = 0;
520
    return mixer_load(s, addr);
521
}
522

523
static uint32_t nam_readl(void *opaque, uint32_t addr)
524
{
525
    AC97LinkState *s = opaque;
526
    dolog("U nam readl 0x%x\n", addr);
527
    s->cas = 0;
528
    return ~0U;
529
}
530

531
/**
532
 * Native audio mixer
533
 * I/O Writes
534
 */
535
static void nam_writeb(void *opaque, uint32_t addr, uint32_t val)
536
{
537
    AC97LinkState *s = opaque;
538
    dolog("U nam writeb 0x%x <- 0x%x\n", addr, val);
539
    s->cas = 0;
540
}
541

542
static void nam_writew(void *opaque, uint32_t addr, uint32_t val)
543
{
544
    AC97LinkState *s = opaque;
545

546
    s->cas = 0;
547
    switch (addr) {
548
    case AC97_Reset:
549
        mixer_reset(s);
550
        break;
551
    case AC97_Powerdown_Ctrl_Stat:
552
        val &= ~0x800f;
553
        val |= mixer_load(s, addr) & 0xf;
554
        mixer_store(s, addr, val);
555
        break;
556
    case AC97_PCM_Out_Volume_Mute:
557
    case AC97_Master_Volume_Mute:
558
    case AC97_Record_Gain_Mute:
559
        set_volume(s, addr, val);
560
        break;
561
    case AC97_Record_Select:
562
        record_select(s, val);
563
        break;
564
    case AC97_Vendor_ID1:
565
    case AC97_Vendor_ID2:
566
        dolog("Attempt to write vendor ID to 0x%x\n", val);
567
        break;
568
    case AC97_Extended_Audio_ID:
569
        dolog("Attempt to write extended audio ID to 0x%x\n", val);
570
        break;
571
    case AC97_Extended_Audio_Ctrl_Stat:
572
        if (!(val & EACS_VRA)) {
573
            mixer_store(s, AC97_PCM_Front_DAC_Rate, 0xbb80);
574
            mixer_store(s, AC97_PCM_LR_ADC_Rate,    0xbb80);
575
            open_voice(s, PI_INDEX, 48000);
576
            open_voice(s, PO_INDEX, 48000);
577
        }
578
        if (!(val & EACS_VRM)) {
579
            mixer_store(s, AC97_MIC_ADC_Rate, 0xbb80);
580
            open_voice(s, MC_INDEX, 48000);
581
        }
582
        dolog("Setting extended audio control to 0x%x\n", val);
583
        mixer_store(s, AC97_Extended_Audio_Ctrl_Stat, val);
584
        break;
585
    case AC97_PCM_Front_DAC_Rate:
586
        if (mixer_load(s, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRA) {
587
            mixer_store(s, addr, val);
588
            dolog("Set front DAC rate to %d\n", val);
589
            open_voice(s, PO_INDEX, val);
590
        } else {
591
            dolog("Attempt to set front DAC rate to %d, but VRA is not set\n",
592
                  val);
593
        }
594
        break;
595
    case AC97_MIC_ADC_Rate:
596
        if (mixer_load(s, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRM) {
597
            mixer_store(s, addr, val);
598
            dolog("Set MIC ADC rate to %d\n", val);
599
            open_voice(s, MC_INDEX, val);
600
        } else {
601
            dolog("Attempt to set MIC ADC rate to %d, but VRM is not set\n",
602
                  val);
603
        }
604
        break;
605
    case AC97_PCM_LR_ADC_Rate:
606
        if (mixer_load(s, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRA) {
607
            mixer_store(s, addr, val);
608
            dolog("Set front LR ADC rate to %d\n", val);
609
            open_voice(s, PI_INDEX, val);
610
        } else {
611
            dolog("Attempt to set LR ADC rate to %d, but VRA is not set\n",
612
                  val);
613
        }
614
        break;
615
    case AC97_Headphone_Volume_Mute:
616
    case AC97_Master_Volume_Mono_Mute:
617
    case AC97_Master_Tone_RL:
618
    case AC97_PC_BEEP_Volume_Mute:
619
    case AC97_Phone_Volume_Mute:
620
    case AC97_Mic_Volume_Mute:
621
    case AC97_Line_In_Volume_Mute:
622
    case AC97_CD_Volume_Mute:
623
    case AC97_Video_Volume_Mute:
624
    case AC97_Aux_Volume_Mute:
625
    case AC97_Record_Gain_Mic_Mute:
626
    case AC97_General_Purpose:
627
    case AC97_3D_Control:
628
    case AC97_Sigmatel_Analog:
629
    case AC97_Sigmatel_Dac2Invert:
630
        /* None of the features in these regs are emulated, so they are RO */
631
        break;
632
    default:
633
        dolog("U nam writew 0x%x <- 0x%x\n", addr, val);
634
        mixer_store(s, addr, val);
635
        break;
636
    }
637
}
638

639
static void nam_writel(void *opaque, uint32_t addr, uint32_t val)
640
{
641
    AC97LinkState *s = opaque;
642
    dolog("U nam writel 0x%x <- 0x%x\n", addr, val);
643
    s->cas = 0;
644
}
645

646
/**
647
 * Native audio bus master
648
 * I/O Reads
649
 */
650
static uint32_t nabm_readb(void *opaque, uint32_t addr)
651
{
652
    AC97LinkState *s = opaque;
653
    AC97BusMasterRegs *r = NULL;
654
    uint32_t val = ~0U;
655

656
    switch (addr) {
657
    case CAS:
658
        dolog("CAS %d\n", s->cas);
659
        val = s->cas;
660
        s->cas = 1;
661
        break;
662
    case PI_CIV:
663
    case PO_CIV:
664
    case MC_CIV:
665
        r = &s->bm_regs[GET_BM(addr)];
666
        val = r->civ;
667
        dolog("CIV[%d] -> 0x%x\n", GET_BM(addr), val);
668
        break;
669
    case PI_LVI:
670
    case PO_LVI:
671
    case MC_LVI:
672
        r = &s->bm_regs[GET_BM(addr)];
673
        val = r->lvi;
674
        dolog("LVI[%d] -> 0x%x\n", GET_BM(addr), val);
675
        break;
676
    case PI_PIV:
677
    case PO_PIV:
678
    case MC_PIV:
679
        r = &s->bm_regs[GET_BM(addr)];
680
        val = r->piv;
681
        dolog("PIV[%d] -> 0x%x\n", GET_BM(addr), val);
682
        break;
683
    case PI_CR:
684
    case PO_CR:
685
    case MC_CR:
686
        r = &s->bm_regs[GET_BM(addr)];
687
        val = r->cr;
688
        dolog("CR[%d] -> 0x%x\n", GET_BM(addr), val);
689
        break;
690
    case PI_SR:
691
    case PO_SR:
692
    case MC_SR:
693
        r = &s->bm_regs[GET_BM(addr)];
694
        val = r->sr & 0xff;
695
        dolog("SRb[%d] -> 0x%x\n", GET_BM(addr), val);
696
        break;
697
    default:
698
        dolog("U nabm readb 0x%x -> 0x%x\n", addr, val);
699
        break;
700
    }
701
    return val;
702
}
703

704
static uint32_t nabm_readw(void *opaque, uint32_t addr)
705
{
706
    AC97LinkState *s = opaque;
707
    AC97BusMasterRegs *r = NULL;
708
    uint32_t val = ~0U;
709

710
    switch (addr) {
711
    case PI_SR:
712
    case PO_SR:
713
    case MC_SR:
714
        r = &s->bm_regs[GET_BM(addr)];
715
        val = r->sr;
716
        dolog("SR[%d] -> 0x%x\n", GET_BM(addr), val);
717
        break;
718
    case PI_PICB:
719
    case PO_PICB:
720
    case MC_PICB:
721
        r = &s->bm_regs[GET_BM(addr)];
722
        val = r->picb;
723
        dolog("PICB[%d] -> 0x%x\n", GET_BM(addr), val);
724
        break;
725
    default:
726
        dolog("U nabm readw 0x%x -> 0x%x\n", addr, val);
727
        break;
728
    }
729
    return val;
730
}
731

732
static uint32_t nabm_readl(void *opaque, uint32_t addr)
733
{
734
    AC97LinkState *s = opaque;
735
    AC97BusMasterRegs *r = NULL;
736
    uint32_t val = ~0U;
737

738
    switch (addr) {
739
    case PI_BDBAR:
740
    case PO_BDBAR:
741
    case MC_BDBAR:
742
        r = &s->bm_regs[GET_BM(addr)];
743
        val = r->bdbar;
744
        dolog("BMADDR[%d] -> 0x%x\n", GET_BM(addr), val);
745
        break;
746
    case PI_CIV:
747
    case PO_CIV:
748
    case MC_CIV:
749
        r = &s->bm_regs[GET_BM(addr)];
750
        val = r->civ | (r->lvi << 8) | (r->sr << 16);
751
        dolog("CIV LVI SR[%d] -> 0x%x, 0x%x, 0x%x\n", GET_BM(addr),
752
               r->civ, r->lvi, r->sr);
753
        break;
754
    case PI_PICB:
755
    case PO_PICB:
756
    case MC_PICB:
757
        r = &s->bm_regs[GET_BM(addr)];
758
        val = r->picb | (r->piv << 16) | (r->cr << 24);
759
        dolog("PICB PIV CR[%d] -> 0x%x 0x%x 0x%x 0x%x\n", GET_BM(addr),
760
               val, r->picb, r->piv, r->cr);
761
        break;
762
    case GLOB_CNT:
763
        val = s->glob_cnt;
764
        dolog("glob_cnt -> 0x%x\n", val);
765
        break;
766
    case GLOB_STA:
767
        val = s->glob_sta | GS_S0CR;
768
        dolog("glob_sta -> 0x%x\n", val);
769
        break;
770
    default:
771
        dolog("U nabm readl 0x%x -> 0x%x\n", addr, val);
772
        break;
773
    }
774
    return val;
775
}
776

777
/**
778
 * Native audio bus master
779
 * I/O Writes
780
 */
781
static void nabm_writeb(void *opaque, uint32_t addr, uint32_t val)
782
{
783
    AC97LinkState *s = opaque;
784
    AC97BusMasterRegs *r = NULL;
785

786
    switch (addr) {
787
    case PI_LVI:
788
    case PO_LVI:
789
    case MC_LVI:
790
        r = &s->bm_regs[GET_BM(addr)];
791
        if ((r->cr & CR_RPBM) && (r->sr & SR_DCH)) {
792
            r->sr &= ~(SR_DCH | SR_CELV);
793
            r->civ = r->piv;
794
            r->piv = (r->piv + 1) % 32;
795
            fetch_bd(s, r);
796
        }
797
        r->lvi = val % 32;
798
        dolog("LVI[%d] <- 0x%x\n", GET_BM(addr), val);
799
        break;
800
    case PI_CR:
801
    case PO_CR:
802
    case MC_CR:
803
        r = &s->bm_regs[GET_BM(addr)];
804
        if (val & CR_RR) {
805
            reset_bm_regs(s, r);
806
        } else {
807
            r->cr = val & CR_VALID_MASK;
808
            if (!(r->cr & CR_RPBM)) {
809
                voice_set_active(s, r - s->bm_regs, 0);
810
                r->sr |= SR_DCH;
811
            } else {
812
                r->civ = r->piv;
813
                r->piv = (r->piv + 1) % 32;
814
                fetch_bd(s, r);
815
                r->sr &= ~SR_DCH;
816
                voice_set_active(s, r - s->bm_regs, 1);
817
            }
818
        }
819
        dolog("CR[%d] <- 0x%x (cr 0x%x)\n", GET_BM(addr), val, r->cr);
820
        break;
821
    case PI_SR:
822
    case PO_SR:
823
    case MC_SR:
824
        r = &s->bm_regs[GET_BM(addr)];
825
        r->sr |= val & ~(SR_RO_MASK | SR_WCLEAR_MASK);
826
        update_sr(s, r, r->sr & ~(val & SR_WCLEAR_MASK));
827
        dolog("SR[%d] <- 0x%x (sr 0x%x)\n", GET_BM(addr), val, r->sr);
828
        break;
829
    default:
830
        dolog("U nabm writeb 0x%x <- 0x%x\n", addr, val);
831
        break;
832
    }
833
}
834

835
static void nabm_writew(void *opaque, uint32_t addr, uint32_t val)
836
{
837
    AC97LinkState *s = opaque;
838
    AC97BusMasterRegs *r = NULL;
839

840
    switch (addr) {
841
    case PI_SR:
842
    case PO_SR:
843
    case MC_SR:
844
        r = &s->bm_regs[GET_BM(addr)];
845
        r->sr |= val & ~(SR_RO_MASK | SR_WCLEAR_MASK);
846
        update_sr(s, r, r->sr & ~(val & SR_WCLEAR_MASK));
847
        dolog("SR[%d] <- 0x%x (sr 0x%x)\n", GET_BM(addr), val, r->sr);
848
        break;
849
    default:
850
        dolog("U nabm writew 0x%x <- 0x%x\n", addr, val);
851
        break;
852
    }
853
}
854

855
static void nabm_writel(void *opaque, uint32_t addr, uint32_t val)
856
{
857
    AC97LinkState *s = opaque;
858
    AC97BusMasterRegs *r = NULL;
859

860
    switch (addr) {
861
    case PI_BDBAR:
862
    case PO_BDBAR:
863
    case MC_BDBAR:
864
        r = &s->bm_regs[GET_BM(addr)];
865
        r->bdbar = val & ~3;
866
        dolog("BDBAR[%d] <- 0x%x (bdbar 0x%x)\n", GET_BM(addr), val, r->bdbar);
867
        break;
868
    case GLOB_CNT:
869
        /* TODO: Handle WR or CR being set (warm/cold reset requests) */
870
        if (!(val & (GC_WR | GC_CR))) {
871
            s->glob_cnt = val & GC_VALID_MASK;
872
        }
873
        dolog("glob_cnt <- 0x%x (glob_cnt 0x%x)\n", val, s->glob_cnt);
874
        break;
875
    case GLOB_STA:
876
        s->glob_sta &= ~(val & GS_WCLEAR_MASK);
877
        s->glob_sta |= (val & ~(GS_WCLEAR_MASK | GS_RO_MASK)) & GS_VALID_MASK;
878
        dolog("glob_sta <- 0x%x (glob_sta 0x%x)\n", val, s->glob_sta);
879
        break;
880
    default:
881
        dolog("U nabm writel 0x%x <- 0x%x\n", addr, val);
882
        break;
883
    }
884
}
885

886
static int write_audio(AC97LinkState *s, AC97BusMasterRegs *r,
887
                       int max, int *stop)
888
{
889
    uint8_t tmpbuf[4096];
890
    uint32_t addr = r->bd.addr;
891
    uint32_t temp = r->picb << 1;
892
    uint32_t written = 0;
893
    int to_copy = 0;
894
    temp = MIN(temp, max);
895

896
    if (!temp) {
897
        *stop = 1;
898
        return 0;
899
    }
900

901
    while (temp) {
902
        int copied;
903
        to_copy = MIN(temp, sizeof(tmpbuf));
904
        pci_dma_read(&s->dev, addr, tmpbuf, to_copy);
905
        copied = AUD_write(s->voice_po, tmpbuf, to_copy);
906
        dolog("write_audio max=%x to_copy=%x copied=%x\n",
907
              max, to_copy, copied);
908
        if (!copied) {
909
            *stop = 1;
910
            break;
911
        }
912
        temp -= copied;
913
        addr += copied;
914
        written += copied;
915
    }
916

917
    if (!temp) {
918
        if (to_copy < 4) {
919
            dolog("whoops\n");
920
            s->last_samp = 0;
921
        } else {
922
            s->last_samp = *(uint32_t *)&tmpbuf[to_copy - 4];
923
        }
924
    }
925

926
    r->bd.addr = addr;
927
    return written;
928
}
929

930
static void write_bup(AC97LinkState *s, int elapsed)
931
{
932
    dolog("write_bup\n");
933
    if (!(s->bup_flag & BUP_SET)) {
934
        if (s->bup_flag & BUP_LAST) {
935
            int i;
936
            uint8_t *p = s->silence;
937
            for (i = 0; i < sizeof(s->silence) / 4; i++, p += 4) {
938
                *(uint32_t *) p = s->last_samp;
939
            }
940
        } else {
941
            memset(s->silence, 0, sizeof(s->silence));
942
        }
943
        s->bup_flag |= BUP_SET;
944
    }
945

946
    while (elapsed) {
947
        int temp = MIN(elapsed, sizeof(s->silence));
948
        while (temp) {
949
            int copied = AUD_write(s->voice_po, s->silence, temp);
950
            if (!copied) {
951
                return;
952
            }
953
            temp -= copied;
954
            elapsed -= copied;
955
        }
956
    }
957
}
958

959
static int read_audio(AC97LinkState *s, AC97BusMasterRegs *r,
960
                      int max, int *stop)
961
{
962
    uint8_t tmpbuf[4096];
963
    uint32_t addr = r->bd.addr;
964
    uint32_t temp = r->picb << 1;
965
    uint32_t nread = 0;
966
    int to_copy = 0;
967
    SWVoiceIn *voice = (r - s->bm_regs) == MC_INDEX ? s->voice_mc : s->voice_pi;
968

969
    temp = MIN(temp, max);
970

971
    if (!temp) {
972
        *stop = 1;
973
        return 0;
974
    }
975

976
    while (temp) {
977
        int acquired;
978
        to_copy = MIN(temp, sizeof(tmpbuf));
979
        acquired = AUD_read(voice, tmpbuf, to_copy);
980
        if (!acquired) {
981
            *stop = 1;
982
            break;
983
        }
984
        pci_dma_write(&s->dev, addr, tmpbuf, acquired);
985
        temp -= acquired;
986
        addr += acquired;
987
        nread += acquired;
988
    }
989

990
    r->bd.addr = addr;
991
    return nread;
992
}
993

994
static void transfer_audio(AC97LinkState *s, int index, int elapsed)
995
{
996
    AC97BusMasterRegs *r = &s->bm_regs[index];
997
    int stop = 0;
998

999
    if (s->invalid_freq[index]) {
1000
        AUD_log("ac97", "attempt to use voice %d with invalid frequency %d\n",
1001
                index, s->invalid_freq[index]);
1002
        return;
1003
    }
1004

1005
    if (r->sr & SR_DCH) {
1006
        if (r->cr & CR_RPBM) {
1007
            switch (index) {
1008
            case PO_INDEX:
1009
                write_bup(s, elapsed);
1010
                break;
1011
            }
1012
        }
1013
        return;
1014
    }
1015

1016
    while ((elapsed >> 1) && !stop) {
1017
        int temp;
1018

1019
        if (!r->bd_valid) {
1020
            dolog("invalid bd\n");
1021
            fetch_bd(s, r);
1022
        }
1023

1024
        if (!r->picb) {
1025
            dolog("fresh bd %d is empty 0x%x 0x%x\n",
1026
                  r->civ, r->bd.addr, r->bd.ctl_len);
1027
            if (r->civ == r->lvi) {
1028
                r->sr |= SR_DCH; /* CELV? */
1029
                s->bup_flag = 0;
1030
                break;
1031
            }
1032
            r->sr &= ~SR_CELV;
1033
            r->civ = r->piv;
1034
            r->piv = (r->piv + 1) % 32;
1035
            fetch_bd(s, r);
1036
            return;
1037
        }
1038

1039
        switch (index) {
1040
        case PO_INDEX:
1041
            temp = write_audio(s, r, elapsed, &stop);
1042
            elapsed -= temp;
1043
            r->picb -= (temp >> 1);
1044
            break;
1045

1046
        case PI_INDEX:
1047
        case MC_INDEX:
1048
            temp = read_audio(s, r, elapsed, &stop);
1049
            elapsed -= temp;
1050
            r->picb -= (temp >> 1);
1051
            break;
1052
        }
1053

1054
        if (!r->picb) {
1055
            uint32_t new_sr = r->sr & ~SR_CELV;
1056

1057
            if (r->bd.ctl_len & BD_IOC) {
1058
                new_sr |= SR_BCIS;
1059
            }
1060

1061
            if (r->civ == r->lvi) {
1062
                dolog("Underrun civ (%d) == lvi (%d)\n", r->civ, r->lvi);
1063

1064
                new_sr |= SR_LVBCI | SR_DCH | SR_CELV;
1065
                stop = 1;
1066
                s->bup_flag = (r->bd.ctl_len & BD_BUP) ? BUP_LAST : 0;
1067
            } else {
1068
                r->civ = r->piv;
1069
                r->piv = (r->piv + 1) % 32;
1070
                fetch_bd(s, r);
1071
            }
1072

1073
            update_sr(s, r, new_sr);
1074
        }
1075
    }
1076
}
1077

1078
static void pi_callback(void *opaque, int avail)
1079
{
1080
    transfer_audio(opaque, PI_INDEX, avail);
1081
}
1082

1083
static void mc_callback(void *opaque, int avail)
1084
{
1085
    transfer_audio(opaque, MC_INDEX, avail);
1086
}
1087

1088
static void po_callback(void *opaque, int free)
1089
{
1090
    transfer_audio(opaque, PO_INDEX, free);
1091
}
1092

1093
static const VMStateDescription vmstate_ac97_bm_regs = {
1094
    .name = "ac97_bm_regs",
1095
    .version_id = 1,
1096
    .minimum_version_id = 1,
1097
    .fields = (const VMStateField[]) {
1098
        VMSTATE_UINT32(bdbar, AC97BusMasterRegs),
1099
        VMSTATE_UINT8(civ, AC97BusMasterRegs),
1100
        VMSTATE_UINT8(lvi, AC97BusMasterRegs),
1101
        VMSTATE_UINT16(sr, AC97BusMasterRegs),
1102
        VMSTATE_UINT16(picb, AC97BusMasterRegs),
1103
        VMSTATE_UINT8(piv, AC97BusMasterRegs),
1104
        VMSTATE_UINT8(cr, AC97BusMasterRegs),
1105
        VMSTATE_UINT32(bd_valid, AC97BusMasterRegs),
1106
        VMSTATE_UINT32(bd.addr, AC97BusMasterRegs),
1107
        VMSTATE_UINT32(bd.ctl_len, AC97BusMasterRegs),
1108
        VMSTATE_END_OF_LIST()
1109
    }
1110
};
1111

1112
static int ac97_post_load(void *opaque, int version_id)
1113
{
1114
    uint8_t active[LAST_INDEX];
1115
    AC97LinkState *s = opaque;
1116

1117
    record_select(s, mixer_load(s, AC97_Record_Select));
1118
    set_volume(s, AC97_Master_Volume_Mute,
1119
               mixer_load(s, AC97_Master_Volume_Mute));
1120
    set_volume(s, AC97_PCM_Out_Volume_Mute,
1121
               mixer_load(s, AC97_PCM_Out_Volume_Mute));
1122
    set_volume(s, AC97_Record_Gain_Mute,
1123
               mixer_load(s, AC97_Record_Gain_Mute));
1124

1125
    active[PI_INDEX] = !!(s->bm_regs[PI_INDEX].cr & CR_RPBM);
1126
    active[PO_INDEX] = !!(s->bm_regs[PO_INDEX].cr & CR_RPBM);
1127
    active[MC_INDEX] = !!(s->bm_regs[MC_INDEX].cr & CR_RPBM);
1128
    reset_voices(s, active);
1129

1130
    s->bup_flag = 0;
1131
    s->last_samp = 0;
1132
    return 0;
1133
}
1134

1135
static bool is_version_2(void *opaque, int version_id)
1136
{
1137
    return version_id == 2;
1138
}
1139

1140
static const VMStateDescription vmstate_ac97 = {
1141
    .name = "ac97",
1142
    .version_id = 3,
1143
    .minimum_version_id = 2,
1144
    .post_load = ac97_post_load,
1145
    .fields = (const VMStateField[]) {
1146
        VMSTATE_PCI_DEVICE(dev, AC97LinkState),
1147
        VMSTATE_UINT32(glob_cnt, AC97LinkState),
1148
        VMSTATE_UINT32(glob_sta, AC97LinkState),
1149
        VMSTATE_UINT32(cas, AC97LinkState),
1150
        VMSTATE_STRUCT_ARRAY(bm_regs, AC97LinkState, 3, 1,
1151
                             vmstate_ac97_bm_regs, AC97BusMasterRegs),
1152
        VMSTATE_BUFFER(mixer_data, AC97LinkState),
1153
        VMSTATE_UNUSED_TEST(is_version_2, 3),
1154
        VMSTATE_END_OF_LIST()
1155
    }
1156
};
1157

1158
static uint64_t nam_read(void *opaque, hwaddr addr, unsigned size)
1159
{
1160
    if ((addr / size) > 256) {
1161
        return -1;
1162
    }
1163

1164
    switch (size) {
1165
    case 1:
1166
        return nam_readb(opaque, addr);
1167
    case 2:
1168
        return nam_readw(opaque, addr);
1169
    case 4:
1170
        return nam_readl(opaque, addr);
1171
    default:
1172
        return -1;
1173
    }
1174
}
1175

1176
static void nam_write(void *opaque, hwaddr addr, uint64_t val,
1177
                      unsigned size)
1178
{
1179
    if ((addr / size) > 256) {
1180
        return;
1181
    }
1182

1183
    switch (size) {
1184
    case 1:
1185
        nam_writeb(opaque, addr, val);
1186
        break;
1187
    case 2:
1188
        nam_writew(opaque, addr, val);
1189
        break;
1190
    case 4:
1191
        nam_writel(opaque, addr, val);
1192
        break;
1193
    }
1194
}
1195

1196
static const MemoryRegionOps ac97_io_nam_ops = {
1197
    .read = nam_read,
1198
    .write = nam_write,
1199
    .impl = {
1200
        .min_access_size = 1,
1201
        .max_access_size = 4,
1202
    },
1203
    .endianness = DEVICE_LITTLE_ENDIAN,
1204
};
1205

1206
static uint64_t nabm_read(void *opaque, hwaddr addr, unsigned size)
1207
{
1208
    if ((addr / size) > 64) {
1209
        return -1;
1210
    }
1211

1212
    switch (size) {
1213
    case 1:
1214
        return nabm_readb(opaque, addr);
1215
    case 2:
1216
        return nabm_readw(opaque, addr);
1217
    case 4:
1218
        return nabm_readl(opaque, addr);
1219
    default:
1220
        return -1;
1221
    }
1222
}
1223

1224
static void nabm_write(void *opaque, hwaddr addr, uint64_t val,
1225
                       unsigned size)
1226
{
1227
    if ((addr / size) > 64) {
1228
        return;
1229
    }
1230

1231
    switch (size) {
1232
    case 1:
1233
        nabm_writeb(opaque, addr, val);
1234
        break;
1235
    case 2:
1236
        nabm_writew(opaque, addr, val);
1237
        break;
1238
    case 4:
1239
        nabm_writel(opaque, addr, val);
1240
        break;
1241
    }
1242
}
1243

1244

1245
static const MemoryRegionOps ac97_io_nabm_ops = {
1246
    .read = nabm_read,
1247
    .write = nabm_write,
1248
    .impl = {
1249
        .min_access_size = 1,
1250
        .max_access_size = 4,
1251
    },
1252
    .endianness = DEVICE_LITTLE_ENDIAN,
1253
};
1254

1255
static void ac97_on_reset(DeviceState *dev)
1256
{
1257
    AC97LinkState *s = AC97(dev);
1258

1259
    reset_bm_regs(s, &s->bm_regs[0]);
1260
    reset_bm_regs(s, &s->bm_regs[1]);
1261
    reset_bm_regs(s, &s->bm_regs[2]);
1262

1263
    /*
1264
     * Reset the mixer too. The Windows XP driver seems to rely on
1265
     * this. At least it wants to read the vendor id before it resets
1266
     * the codec manually.
1267
     */
1268
    mixer_reset(s);
1269
}
1270

1271
static void ac97_realize(PCIDevice *dev, Error **errp)
1272
{
1273
    AC97LinkState *s = AC97(dev);
1274
    uint8_t *c = s->dev.config;
1275

1276
    if (!AUD_register_card ("ac97", &s->card, errp)) {
1277
        return;
1278
    }
1279

1280
    /* TODO: no need to override */
1281
    c[PCI_COMMAND] = 0x00;      /* pcicmd pci command rw, ro */
1282
    c[PCI_COMMAND + 1] = 0x00;
1283

1284
    /* TODO: */
1285
    c[PCI_STATUS] = PCI_STATUS_FAST_BACK;      /* pcists pci status rwc, ro */
1286
    c[PCI_STATUS + 1] = PCI_STATUS_DEVSEL_MEDIUM >> 8;
1287

1288
    c[PCI_CLASS_PROG] = 0x00;      /* pi programming interface ro */
1289

1290
    /* TODO set when bar is registered. no need to override. */
1291
    /* nabmar native audio mixer base address rw */
1292
    c[PCI_BASE_ADDRESS_0] = PCI_BASE_ADDRESS_SPACE_IO;
1293
    c[PCI_BASE_ADDRESS_0 + 1] = 0x00;
1294
    c[PCI_BASE_ADDRESS_0 + 2] = 0x00;
1295
    c[PCI_BASE_ADDRESS_0 + 3] = 0x00;
1296

1297
    /* TODO set when bar is registered. no need to override. */
1298
      /* nabmbar native audio bus mastering base address rw */
1299
    c[PCI_BASE_ADDRESS_0 + 4] = PCI_BASE_ADDRESS_SPACE_IO;
1300
    c[PCI_BASE_ADDRESS_0 + 5] = 0x00;
1301
    c[PCI_BASE_ADDRESS_0 + 6] = 0x00;
1302
    c[PCI_BASE_ADDRESS_0 + 7] = 0x00;
1303

1304
    c[PCI_INTERRUPT_LINE] = 0x00;      /* intr_ln interrupt line rw */
1305
    c[PCI_INTERRUPT_PIN] = 0x01;      /* intr_pn interrupt pin ro */
1306

1307
    memory_region_init_io(&s->io_nam, OBJECT(s), &ac97_io_nam_ops, s,
1308
                          "ac97-nam", 1024);
1309
    memory_region_init_io(&s->io_nabm, OBJECT(s), &ac97_io_nabm_ops, s,
1310
                          "ac97-nabm", 256);
1311
    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_nam);
1312
    pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io_nabm);
1313

1314
    ac97_on_reset(DEVICE(s));
1315
}
1316

1317
static void ac97_exit(PCIDevice *dev)
1318
{
1319
    AC97LinkState *s = AC97(dev);
1320

1321
    AUD_close_in(&s->card, s->voice_pi);
1322
    AUD_close_out(&s->card, s->voice_po);
1323
    AUD_close_in(&s->card, s->voice_mc);
1324
    AUD_remove_card(&s->card);
1325
}
1326

1327
static Property ac97_properties[] = {
1328
    DEFINE_AUDIO_PROPERTIES(AC97LinkState, card),
1329
    DEFINE_PROP_END_OF_LIST(),
1330
};
1331

1332
static void ac97_class_init(ObjectClass *klass, void *data)
1333
{
1334
    DeviceClass *dc = DEVICE_CLASS(klass);
1335
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
1336

1337
    k->realize = ac97_realize;
1338
    k->exit = ac97_exit;
1339
    k->vendor_id = PCI_VENDOR_ID_INTEL;
1340
    k->device_id = PCI_DEVICE_ID_INTEL_82801AA_5;
1341
    k->revision = 0x01;
1342
    k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
1343
    set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
1344
    dc->desc = "Intel 82801AA AC97 Audio";
1345
    dc->vmsd = &vmstate_ac97;
1346
    device_class_set_props(dc, ac97_properties);
1347
    dc->reset = ac97_on_reset;
1348
}
1349

1350
static const TypeInfo ac97_info = {
1351
    .name          = TYPE_AC97,
1352
    .parent        = TYPE_PCI_DEVICE,
1353
    .instance_size = sizeof(AC97LinkState),
1354
    .class_init    = ac97_class_init,
1355
    .interfaces = (InterfaceInfo[]) {
1356
        { INTERFACE_CONVENTIONAL_PCI_DEVICE },
1357
        { },
1358
    },
1359
};
1360

1361
static void ac97_register_types(void)
1362
{
1363
    type_register_static(&ac97_info);
1364
    deprecated_register_soundhw("ac97", "Intel 82801AA AC97 Audio",
1365
                                0, TYPE_AC97);
1366
}
1367

1368
type_init(ac97_register_types)
1369

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.