qemu/hw/audio/sb16.c
<<
>>
Prefs
   1/*
   2 * QEMU Soundblaster 16 emulation
   3 *
   4 * Copyright (c) 2003-2005 Vassili Karpov (malc)
   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/hw.h"
  27#include "hw/audio/soundhw.h"
  28#include "audio/audio.h"
  29#include "hw/isa/isa.h"
  30#include "hw/qdev.h"
  31#include "qemu/timer.h"
  32#include "qemu/host-utils.h"
  33#include "qemu/log.h"
  34#include "qemu/module.h"
  35#include "qapi/error.h"
  36
  37#define dolog(...) AUD_log ("sb16", __VA_ARGS__)
  38
  39/* #define DEBUG */
  40/* #define DEBUG_SB16_MOST */
  41
  42#ifdef DEBUG
  43#define ldebug(...) dolog (__VA_ARGS__)
  44#else
  45#define ldebug(...)
  46#endif
  47
  48static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
  49
  50#define TYPE_SB16 "sb16"
  51#define SB16(obj) OBJECT_CHECK (SB16State, (obj), TYPE_SB16)
  52
  53typedef struct SB16State {
  54    ISADevice parent_obj;
  55
  56    QEMUSoundCard card;
  57    qemu_irq pic;
  58    uint32_t irq;
  59    uint32_t dma;
  60    uint32_t hdma;
  61    uint32_t port;
  62    uint32_t ver;
  63    IsaDma *isa_dma;
  64    IsaDma *isa_hdma;
  65
  66    int in_index;
  67    int out_data_len;
  68    int fmt_stereo;
  69    int fmt_signed;
  70    int fmt_bits;
  71    AudioFormat fmt;
  72    int dma_auto;
  73    int block_size;
  74    int fifo;
  75    int freq;
  76    int time_const;
  77    int speaker;
  78    int needed_bytes;
  79    int cmd;
  80    int use_hdma;
  81    int highspeed;
  82    int can_write;
  83
  84    int v2x6;
  85
  86    uint8_t csp_param;
  87    uint8_t csp_value;
  88    uint8_t csp_mode;
  89    uint8_t csp_regs[256];
  90    uint8_t csp_index;
  91    uint8_t csp_reg83[4];
  92    int csp_reg83r;
  93    int csp_reg83w;
  94
  95    uint8_t in2_data[10];
  96    uint8_t out_data[50];
  97    uint8_t test_reg;
  98    uint8_t last_read_byte;
  99    int nzero;
 100
 101    int left_till_irq;
 102
 103    int dma_running;
 104    int bytes_per_second;
 105    int align;
 106    int audio_free;
 107    SWVoiceOut *voice;
 108
 109    QEMUTimer *aux_ts;
 110    /* mixer state */
 111    int mixer_nreg;
 112    uint8_t mixer_regs[256];
 113    PortioList portio_list;
 114} SB16State;
 115
 116static void SB_audio_callback (void *opaque, int free);
 117
 118static int magic_of_irq (int irq)
 119{
 120    switch (irq) {
 121    case 5:
 122        return 2;
 123    case 7:
 124        return 4;
 125    case 9:
 126        return 1;
 127    case 10:
 128        return 8;
 129    default:
 130        qemu_log_mask(LOG_GUEST_ERROR, "bad irq %d\n", irq);
 131        return 2;
 132    }
 133}
 134
 135static int irq_of_magic (int magic)
 136{
 137    switch (magic) {
 138    case 1:
 139        return 9;
 140    case 2:
 141        return 5;
 142    case 4:
 143        return 7;
 144    case 8:
 145        return 10;
 146    default:
 147        qemu_log_mask(LOG_GUEST_ERROR, "bad irq magic %d\n", magic);
 148        return -1;
 149    }
 150}
 151
 152#if 0
 153static void log_dsp (SB16State *dsp)
 154{
 155    ldebug ("%s:%s:%d:%s:dmasize=%d:freq=%d:const=%d:speaker=%d\n",
 156            dsp->fmt_stereo ? "Stereo" : "Mono",
 157            dsp->fmt_signed ? "Signed" : "Unsigned",
 158            dsp->fmt_bits,
 159            dsp->dma_auto ? "Auto" : "Single",
 160            dsp->block_size,
 161            dsp->freq,
 162            dsp->time_const,
 163            dsp->speaker);
 164}
 165#endif
 166
 167static void speaker (SB16State *s, int on)
 168{
 169    s->speaker = on;
 170    /* AUD_enable (s->voice, on); */
 171}
 172
 173static void control (SB16State *s, int hold)
 174{
 175    int dma = s->use_hdma ? s->hdma : s->dma;
 176    IsaDma *isa_dma = s->use_hdma ? s->isa_hdma : s->isa_dma;
 177    IsaDmaClass *k = ISADMA_GET_CLASS(isa_dma);
 178    s->dma_running = hold;
 179
 180    ldebug ("hold %d high %d dma %d\n", hold, s->use_hdma, dma);
 181
 182    if (hold) {
 183        k->hold_DREQ(isa_dma, dma);
 184        AUD_set_active_out (s->voice, 1);
 185    }
 186    else {
 187        k->release_DREQ(isa_dma, dma);
 188        AUD_set_active_out (s->voice, 0);
 189    }
 190}
 191
 192static void aux_timer (void *opaque)
 193{
 194    SB16State *s = opaque;
 195    s->can_write = 1;
 196    qemu_irq_raise (s->pic);
 197}
 198
 199#define DMA8_AUTO 1
 200#define DMA8_HIGH 2
 201
 202static void continue_dma8 (SB16State *s)
 203{
 204    if (s->freq > 0) {
 205        struct audsettings as;
 206
 207        s->audio_free = 0;
 208
 209        as.freq = s->freq;
 210        as.nchannels = 1 << s->fmt_stereo;
 211        as.fmt = s->fmt;
 212        as.endianness = 0;
 213
 214        s->voice = AUD_open_out (
 215            &s->card,
 216            s->voice,
 217            "sb16",
 218            s,
 219            SB_audio_callback,
 220            &as
 221            );
 222    }
 223
 224    control (s, 1);
 225}
 226
 227static void dma_cmd8 (SB16State *s, int mask, int dma_len)
 228{
 229    s->fmt = AUDIO_FORMAT_U8;
 230    s->use_hdma = 0;
 231    s->fmt_bits = 8;
 232    s->fmt_signed = 0;
 233    s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0;
 234    if (-1 == s->time_const) {
 235        if (s->freq <= 0)
 236            s->freq = 11025;
 237    }
 238    else {
 239        int tmp = (256 - s->time_const);
 240        s->freq = (1000000 + (tmp / 2)) / tmp;
 241    }
 242
 243    if (dma_len != -1) {
 244        s->block_size = dma_len << s->fmt_stereo;
 245    }
 246    else {
 247        /* This is apparently the only way to make both Act1/PL
 248           and SecondReality/FC work
 249
 250           Act1 sets block size via command 0x48 and it's an odd number
 251           SR does the same with even number
 252           Both use stereo, and Creatives own documentation states that
 253           0x48 sets block size in bytes less one.. go figure */
 254        s->block_size &= ~s->fmt_stereo;
 255    }
 256
 257    s->freq >>= s->fmt_stereo;
 258    s->left_till_irq = s->block_size;
 259    s->bytes_per_second = (s->freq << s->fmt_stereo);
 260    /* s->highspeed = (mask & DMA8_HIGH) != 0; */
 261    s->dma_auto = (mask & DMA8_AUTO) != 0;
 262    s->align = (1 << s->fmt_stereo) - 1;
 263
 264    if (s->block_size & s->align) {
 265        qemu_log_mask(LOG_GUEST_ERROR, "warning: misaligned block size %d,"
 266                      " alignment %d\n", s->block_size, s->align + 1);
 267    }
 268
 269    ldebug ("freq %d, stereo %d, sign %d, bits %d, "
 270            "dma %d, auto %d, fifo %d, high %d\n",
 271            s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
 272            s->block_size, s->dma_auto, s->fifo, s->highspeed);
 273
 274    continue_dma8 (s);
 275    speaker (s, 1);
 276}
 277
 278static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
 279{
 280    s->use_hdma = cmd < 0xc0;
 281    s->fifo = (cmd >> 1) & 1;
 282    s->dma_auto = (cmd >> 2) & 1;
 283    s->fmt_signed = (d0 >> 4) & 1;
 284    s->fmt_stereo = (d0 >> 5) & 1;
 285
 286    switch (cmd >> 4) {
 287    case 11:
 288        s->fmt_bits = 16;
 289        break;
 290
 291    case 12:
 292        s->fmt_bits = 8;
 293        break;
 294    }
 295
 296    if (-1 != s->time_const) {
 297#if 1
 298        int tmp = 256 - s->time_const;
 299        s->freq = (1000000 + (tmp / 2)) / tmp;
 300#else
 301        /* s->freq = 1000000 / ((255 - s->time_const) << s->fmt_stereo); */
 302        s->freq = 1000000 / ((255 - s->time_const));
 303#endif
 304        s->time_const = -1;
 305    }
 306
 307    s->block_size = dma_len + 1;
 308    s->block_size <<= (s->fmt_bits == 16);
 309    if (!s->dma_auto) {
 310        /* It is clear that for DOOM and auto-init this value
 311           shouldn't take stereo into account, while Miles Sound Systems
 312           setsound.exe with single transfer mode wouldn't work without it
 313           wonders of SB16 yet again */
 314        s->block_size <<= s->fmt_stereo;
 315    }
 316
 317    ldebug ("freq %d, stereo %d, sign %d, bits %d, "
 318            "dma %d, auto %d, fifo %d, high %d\n",
 319            s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
 320            s->block_size, s->dma_auto, s->fifo, s->highspeed);
 321
 322    if (16 == s->fmt_bits) {
 323        if (s->fmt_signed) {
 324            s->fmt = AUDIO_FORMAT_S16;
 325        }
 326        else {
 327            s->fmt = AUDIO_FORMAT_U16;
 328        }
 329    }
 330    else {
 331        if (s->fmt_signed) {
 332            s->fmt = AUDIO_FORMAT_S8;
 333        }
 334        else {
 335            s->fmt = AUDIO_FORMAT_U8;
 336        }
 337    }
 338
 339    s->left_till_irq = s->block_size;
 340
 341    s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16);
 342    s->highspeed = 0;
 343    s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1;
 344    if (s->block_size & s->align) {
 345        qemu_log_mask(LOG_GUEST_ERROR, "warning: misaligned block size %d,"
 346                      " alignment %d\n", s->block_size, s->align + 1);
 347    }
 348
 349    if (s->freq) {
 350        struct audsettings as;
 351
 352        s->audio_free = 0;
 353
 354        as.freq = s->freq;
 355        as.nchannels = 1 << s->fmt_stereo;
 356        as.fmt = s->fmt;
 357        as.endianness = 0;
 358
 359        s->voice = AUD_open_out (
 360            &s->card,
 361            s->voice,
 362            "sb16",
 363            s,
 364            SB_audio_callback,
 365            &as
 366            );
 367    }
 368
 369    control (s, 1);
 370    speaker (s, 1);
 371}
 372
 373static inline void dsp_out_data (SB16State *s, uint8_t val)
 374{
 375    ldebug ("outdata %#x\n", val);
 376    if ((size_t) s->out_data_len < sizeof (s->out_data)) {
 377        s->out_data[s->out_data_len++] = val;
 378    }
 379}
 380
 381static inline uint8_t dsp_get_data (SB16State *s)
 382{
 383    if (s->in_index) {
 384        return s->in2_data[--s->in_index];
 385    }
 386    else {
 387        dolog ("buffer underflow\n");
 388        return 0;
 389    }
 390}
 391
 392static void command (SB16State *s, uint8_t cmd)
 393{
 394    ldebug ("command %#x\n", cmd);
 395
 396    if (cmd > 0xaf && cmd < 0xd0) {
 397        if (cmd & 8) {
 398            qemu_log_mask(LOG_UNIMP, "ADC not yet supported (command %#x)\n",
 399                          cmd);
 400        }
 401
 402        switch (cmd >> 4) {
 403        case 11:
 404        case 12:
 405            break;
 406        default:
 407            qemu_log_mask(LOG_GUEST_ERROR, "%#x wrong bits\n", cmd);
 408        }
 409        s->needed_bytes = 3;
 410    }
 411    else {
 412        s->needed_bytes = 0;
 413
 414        switch (cmd) {
 415        case 0x03:
 416            dsp_out_data (s, 0x10); /* s->csp_param); */
 417            goto warn;
 418
 419        case 0x04:
 420            s->needed_bytes = 1;
 421            goto warn;
 422
 423        case 0x05:
 424            s->needed_bytes = 2;
 425            goto warn;
 426
 427        case 0x08:
 428            /* __asm__ ("int3"); */
 429            goto warn;
 430
 431        case 0x0e:
 432            s->needed_bytes = 2;
 433            goto warn;
 434
 435        case 0x09:
 436            dsp_out_data (s, 0xf8);
 437            goto warn;
 438
 439        case 0x0f:
 440            s->needed_bytes = 1;
 441            goto warn;
 442
 443        case 0x10:
 444            s->needed_bytes = 1;
 445            goto warn;
 446
 447        case 0x14:
 448            s->needed_bytes = 2;
 449            s->block_size = 0;
 450            break;
 451
 452        case 0x1c:              /* Auto-Initialize DMA DAC, 8-bit */
 453            dma_cmd8 (s, DMA8_AUTO, -1);
 454            break;
 455
 456        case 0x20:              /* Direct ADC, Juice/PL */
 457            dsp_out_data (s, 0xff);
 458            goto warn;
 459
 460        case 0x35:
 461            qemu_log_mask(LOG_UNIMP, "0x35 - MIDI command not implemented\n");
 462            break;
 463
 464        case 0x40:
 465            s->freq = -1;
 466            s->time_const = -1;
 467            s->needed_bytes = 1;
 468            break;
 469
 470        case 0x41:
 471            s->freq = -1;
 472            s->time_const = -1;
 473            s->needed_bytes = 2;
 474            break;
 475
 476        case 0x42:
 477            s->freq = -1;
 478            s->time_const = -1;
 479            s->needed_bytes = 2;
 480            goto warn;
 481
 482        case 0x45:
 483            dsp_out_data (s, 0xaa);
 484            goto warn;
 485
 486        case 0x47:                /* Continue Auto-Initialize DMA 16bit */
 487            break;
 488
 489        case 0x48:
 490            s->needed_bytes = 2;
 491            break;
 492
 493        case 0x74:
 494            s->needed_bytes = 2; /* DMA DAC, 4-bit ADPCM */
 495            qemu_log_mask(LOG_UNIMP, "0x75 - DMA DAC, 4-bit ADPCM not"
 496                          " implemented\n");
 497            break;
 498
 499        case 0x75:              /* DMA DAC, 4-bit ADPCM Reference */
 500            s->needed_bytes = 2;
 501            qemu_log_mask(LOG_UNIMP, "0x74 - DMA DAC, 4-bit ADPCM Reference not"
 502                          " implemented\n");
 503            break;
 504
 505        case 0x76:              /* DMA DAC, 2.6-bit ADPCM */
 506            s->needed_bytes = 2;
 507            qemu_log_mask(LOG_UNIMP, "0x74 - DMA DAC, 2.6-bit ADPCM not"
 508                          " implemented\n");
 509            break;
 510
 511        case 0x77:              /* DMA DAC, 2.6-bit ADPCM Reference */
 512            s->needed_bytes = 2;
 513            qemu_log_mask(LOG_UNIMP, "0x74 - DMA DAC, 2.6-bit ADPCM Reference"
 514                          " not implemented\n");
 515            break;
 516
 517        case 0x7d:
 518            qemu_log_mask(LOG_UNIMP, "0x7d - Autio-Initialize DMA DAC, 4-bit"
 519                          " ADPCM Reference\n");
 520            qemu_log_mask(LOG_UNIMP, "not implemented\n");
 521            break;
 522
 523        case 0x7f:
 524            qemu_log_mask(LOG_UNIMP, "0x7d - Autio-Initialize DMA DAC, 2.6-bit"
 525                          " ADPCM Reference\n");
 526            qemu_log_mask(LOG_UNIMP, "not implemented\n");
 527            break;
 528
 529        case 0x80:
 530            s->needed_bytes = 2;
 531            break;
 532
 533        case 0x90:
 534        case 0x91:
 535            dma_cmd8 (s, ((cmd & 1) == 0) | DMA8_HIGH, -1);
 536            break;
 537
 538        case 0xd0:              /* halt DMA operation. 8bit */
 539            control (s, 0);
 540            break;
 541
 542        case 0xd1:              /* speaker on */
 543            speaker (s, 1);
 544            break;
 545
 546        case 0xd3:              /* speaker off */
 547            speaker (s, 0);
 548            break;
 549
 550        case 0xd4:              /* continue DMA operation. 8bit */
 551            /* KQ6 (or maybe Sierras audblst.drv in general) resets
 552               the frequency between halt/continue */
 553            continue_dma8 (s);
 554            break;
 555
 556        case 0xd5:              /* halt DMA operation. 16bit */
 557            control (s, 0);
 558            break;
 559
 560        case 0xd6:              /* continue DMA operation. 16bit */
 561            control (s, 1);
 562            break;
 563
 564        case 0xd9:              /* exit auto-init DMA after this block. 16bit */
 565            s->dma_auto = 0;
 566            break;
 567
 568        case 0xda:              /* exit auto-init DMA after this block. 8bit */
 569            s->dma_auto = 0;
 570            break;
 571
 572        case 0xe0:              /* DSP identification */
 573            s->needed_bytes = 1;
 574            break;
 575
 576        case 0xe1:
 577            dsp_out_data (s, s->ver & 0xff);
 578            dsp_out_data (s, s->ver >> 8);
 579            break;
 580
 581        case 0xe2:
 582            s->needed_bytes = 1;
 583            goto warn;
 584
 585        case 0xe3:
 586            {
 587                int i;
 588                for (i = sizeof (e3) - 1; i >= 0; --i)
 589                    dsp_out_data (s, e3[i]);
 590            }
 591            break;
 592
 593        case 0xe4:              /* write test reg */
 594            s->needed_bytes = 1;
 595            break;
 596
 597        case 0xe7:
 598            qemu_log_mask(LOG_UNIMP, "Attempt to probe for ESS (0xe7)?\n");
 599            break;
 600
 601        case 0xe8:              /* read test reg */
 602            dsp_out_data (s, s->test_reg);
 603            break;
 604
 605        case 0xf2:
 606        case 0xf3:
 607            dsp_out_data (s, 0xaa);
 608            s->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2;
 609            qemu_irq_raise (s->pic);
 610            break;
 611
 612        case 0xf9:
 613            s->needed_bytes = 1;
 614            goto warn;
 615
 616        case 0xfa:
 617            dsp_out_data (s, 0);
 618            goto warn;
 619
 620        case 0xfc:              /* FIXME */
 621            dsp_out_data (s, 0);
 622            goto warn;
 623
 624        default:
 625            qemu_log_mask(LOG_UNIMP, "Unrecognized command %#x\n", cmd);
 626            break;
 627        }
 628    }
 629
 630    if (!s->needed_bytes) {
 631        ldebug ("\n");
 632    }
 633
 634 exit:
 635    if (!s->needed_bytes) {
 636        s->cmd = -1;
 637    }
 638    else {
 639        s->cmd = cmd;
 640    }
 641    return;
 642
 643 warn:
 644    qemu_log_mask(LOG_UNIMP, "warning: command %#x,%d is not truly understood"
 645                  " yet\n", cmd, s->needed_bytes);
 646    goto exit;
 647
 648}
 649
 650static uint16_t dsp_get_lohi (SB16State *s)
 651{
 652    uint8_t hi = dsp_get_data (s);
 653    uint8_t lo = dsp_get_data (s);
 654    return (hi << 8) | lo;
 655}
 656
 657static uint16_t dsp_get_hilo (SB16State *s)
 658{
 659    uint8_t lo = dsp_get_data (s);
 660    uint8_t hi = dsp_get_data (s);
 661    return (hi << 8) | lo;
 662}
 663
 664static void complete (SB16State *s)
 665{
 666    int d0, d1, d2;
 667    ldebug ("complete command %#x, in_index %d, needed_bytes %d\n",
 668            s->cmd, s->in_index, s->needed_bytes);
 669
 670    if (s->cmd > 0xaf && s->cmd < 0xd0) {
 671        d2 = dsp_get_data (s);
 672        d1 = dsp_get_data (s);
 673        d0 = dsp_get_data (s);
 674
 675        if (s->cmd & 8) {
 676            dolog ("ADC params cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
 677                   s->cmd, d0, d1, d2);
 678        }
 679        else {
 680            ldebug ("cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
 681                    s->cmd, d0, d1, d2);
 682            dma_cmd (s, s->cmd, d0, d1 + (d2 << 8));
 683        }
 684    }
 685    else {
 686        switch (s->cmd) {
 687        case 0x04:
 688            s->csp_mode = dsp_get_data (s);
 689            s->csp_reg83r = 0;
 690            s->csp_reg83w = 0;
 691            ldebug ("CSP command 0x04: mode=%#x\n", s->csp_mode);
 692            break;
 693
 694        case 0x05:
 695            s->csp_param = dsp_get_data (s);
 696            s->csp_value = dsp_get_data (s);
 697            ldebug ("CSP command 0x05: param=%#x value=%#x\n",
 698                    s->csp_param,
 699                    s->csp_value);
 700            break;
 701
 702        case 0x0e:
 703            d0 = dsp_get_data (s);
 704            d1 = dsp_get_data (s);
 705            ldebug ("write CSP register %d <- %#x\n", d1, d0);
 706            if (d1 == 0x83) {
 707                ldebug ("0x83[%d] <- %#x\n", s->csp_reg83r, d0);
 708                s->csp_reg83[s->csp_reg83r % 4] = d0;
 709                s->csp_reg83r += 1;
 710            }
 711            else {
 712                s->csp_regs[d1] = d0;
 713            }
 714            break;
 715
 716        case 0x0f:
 717            d0 = dsp_get_data (s);
 718            ldebug ("read CSP register %#x -> %#x, mode=%#x\n",
 719                    d0, s->csp_regs[d0], s->csp_mode);
 720            if (d0 == 0x83) {
 721                ldebug ("0x83[%d] -> %#x\n",
 722                        s->csp_reg83w,
 723                        s->csp_reg83[s->csp_reg83w % 4]);
 724                dsp_out_data (s, s->csp_reg83[s->csp_reg83w % 4]);
 725                s->csp_reg83w += 1;
 726            }
 727            else {
 728                dsp_out_data (s, s->csp_regs[d0]);
 729            }
 730            break;
 731
 732        case 0x10:
 733            d0 = dsp_get_data (s);
 734            dolog ("cmd 0x10 d0=%#x\n", d0);
 735            break;
 736
 737        case 0x14:
 738            dma_cmd8 (s, 0, dsp_get_lohi (s) + 1);
 739            break;
 740
 741        case 0x40:
 742            s->time_const = dsp_get_data (s);
 743            ldebug ("set time const %d\n", s->time_const);
 744            break;
 745
 746        case 0x41:
 747        case 0x42:
 748            /*
 749             * 0x41 is documented as setting the output sample rate,
 750             * and 0x42 the input sample rate, but in fact SB16 hardware
 751             * seems to have only a single sample rate under the hood,
 752             * and FT2 sets output freq with this (go figure).  Compare:
 753             * http://homepages.cae.wisc.edu/~brodskye/sb16doc/sb16doc.html#SamplingRate
 754             */
 755            s->freq = dsp_get_hilo (s);
 756            ldebug ("set freq %d\n", s->freq);
 757            break;
 758
 759        case 0x48:
 760            s->block_size = dsp_get_lohi (s) + 1;
 761            ldebug ("set dma block len %d\n", s->block_size);
 762            break;
 763
 764        case 0x74:
 765        case 0x75:
 766        case 0x76:
 767        case 0x77:
 768            /* ADPCM stuff, ignore */
 769            break;
 770
 771        case 0x80:
 772            {
 773                int freq, samples, bytes;
 774                int64_t ticks;
 775
 776                freq = s->freq > 0 ? s->freq : 11025;
 777                samples = dsp_get_lohi (s) + 1;
 778                bytes = samples << s->fmt_stereo << (s->fmt_bits == 16);
 779                ticks = muldiv64(bytes, NANOSECONDS_PER_SECOND, freq);
 780                if (ticks < NANOSECONDS_PER_SECOND / 1024) {
 781                    qemu_irq_raise (s->pic);
 782                }
 783                else {
 784                    if (s->aux_ts) {
 785                        timer_mod (
 786                            s->aux_ts,
 787                            qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ticks
 788                            );
 789                    }
 790                }
 791                ldebug ("mix silence %d %d %" PRId64 "\n", samples, bytes, ticks);
 792            }
 793            break;
 794
 795        case 0xe0:
 796            d0 = dsp_get_data (s);
 797            s->out_data_len = 0;
 798            ldebug ("E0 data = %#x\n", d0);
 799            dsp_out_data (s, ~d0);
 800            break;
 801
 802        case 0xe2:
 803#ifdef DEBUG
 804            d0 = dsp_get_data (s);
 805            dolog ("E2 = %#x\n", d0);
 806#endif
 807            break;
 808
 809        case 0xe4:
 810            s->test_reg = dsp_get_data (s);
 811            break;
 812
 813        case 0xf9:
 814            d0 = dsp_get_data (s);
 815            ldebug ("command 0xf9 with %#x\n", d0);
 816            switch (d0) {
 817            case 0x0e:
 818                dsp_out_data (s, 0xff);
 819                break;
 820
 821            case 0x0f:
 822                dsp_out_data (s, 0x07);
 823                break;
 824
 825            case 0x37:
 826                dsp_out_data (s, 0x38);
 827                break;
 828
 829            default:
 830                dsp_out_data (s, 0x00);
 831                break;
 832            }
 833            break;
 834
 835        default:
 836            qemu_log_mask(LOG_UNIMP, "complete: unrecognized command %#x\n",
 837                          s->cmd);
 838            return;
 839        }
 840    }
 841
 842    ldebug ("\n");
 843    s->cmd = -1;
 844}
 845
 846static void legacy_reset (SB16State *s)
 847{
 848    struct audsettings as;
 849
 850    s->freq = 11025;
 851    s->fmt_signed = 0;
 852    s->fmt_bits = 8;
 853    s->fmt_stereo = 0;
 854
 855    as.freq = s->freq;
 856    as.nchannels = 1;
 857    as.fmt = AUDIO_FORMAT_U8;
 858    as.endianness = 0;
 859
 860    s->voice = AUD_open_out (
 861        &s->card,
 862        s->voice,
 863        "sb16",
 864        s,
 865        SB_audio_callback,
 866        &as
 867        );
 868
 869    /* Not sure about that... */
 870    /* AUD_set_active_out (s->voice, 1); */
 871}
 872
 873static void reset (SB16State *s)
 874{
 875    qemu_irq_lower (s->pic);
 876    if (s->dma_auto) {
 877        qemu_irq_raise (s->pic);
 878        qemu_irq_lower (s->pic);
 879    }
 880
 881    s->mixer_regs[0x82] = 0;
 882    s->dma_auto = 0;
 883    s->in_index = 0;
 884    s->out_data_len = 0;
 885    s->left_till_irq = 0;
 886    s->needed_bytes = 0;
 887    s->block_size = -1;
 888    s->nzero = 0;
 889    s->highspeed = 0;
 890    s->v2x6 = 0;
 891    s->cmd = -1;
 892
 893    dsp_out_data (s, 0xaa);
 894    speaker (s, 0);
 895    control (s, 0);
 896    legacy_reset (s);
 897}
 898
 899static void dsp_write(void *opaque, uint32_t nport, uint32_t val)
 900{
 901    SB16State *s = opaque;
 902    int iport;
 903
 904    iport = nport - s->port;
 905
 906    ldebug ("write %#x <- %#x\n", nport, val);
 907    switch (iport) {
 908    case 0x06:
 909        switch (val) {
 910        case 0x00:
 911            if (s->v2x6 == 1) {
 912                reset (s);
 913            }
 914            s->v2x6 = 0;
 915            break;
 916
 917        case 0x01:
 918        case 0x03:              /* FreeBSD kludge */
 919            s->v2x6 = 1;
 920            break;
 921
 922        case 0xc6:
 923            s->v2x6 = 0;        /* Prince of Persia, csp.sys, diagnose.exe */
 924            break;
 925
 926        case 0xb8:              /* Panic */
 927            reset (s);
 928            break;
 929
 930        case 0x39:
 931            dsp_out_data (s, 0x38);
 932            reset (s);
 933            s->v2x6 = 0x39;
 934            break;
 935
 936        default:
 937            s->v2x6 = val;
 938            break;
 939        }
 940        break;
 941
 942    case 0x0c:                  /* write data or command | write status */
 943/*         if (s->highspeed) */
 944/*             break; */
 945
 946        if (s->needed_bytes == 0) {
 947            command (s, val);
 948#if 0
 949            if (0 == s->needed_bytes) {
 950                log_dsp (s);
 951            }
 952#endif
 953        }
 954        else {
 955            if (s->in_index == sizeof (s->in2_data)) {
 956                dolog ("in data overrun\n");
 957            }
 958            else {
 959                s->in2_data[s->in_index++] = val;
 960                if (s->in_index == s->needed_bytes) {
 961                    s->needed_bytes = 0;
 962                    complete (s);
 963#if 0
 964                    log_dsp (s);
 965#endif
 966                }
 967            }
 968        }
 969        break;
 970
 971    default:
 972        ldebug ("(nport=%#x, val=%#x)\n", nport, val);
 973        break;
 974    }
 975}
 976
 977static uint32_t dsp_read(void *opaque, uint32_t nport)
 978{
 979    SB16State *s = opaque;
 980    int iport, retval, ack = 0;
 981
 982    iport = nport - s->port;
 983
 984    switch (iport) {
 985    case 0x06:                  /* reset */
 986        retval = 0xff;
 987        break;
 988
 989    case 0x0a:                  /* read data */
 990        if (s->out_data_len) {
 991            retval = s->out_data[--s->out_data_len];
 992            s->last_read_byte = retval;
 993        }
 994        else {
 995            if (s->cmd != -1) {
 996                dolog ("empty output buffer for command %#x\n",
 997                       s->cmd);
 998            }
 999            retval = s->last_read_byte;
1000            /* goto error; */
1001        }
1002        break;
1003
1004    case 0x0c:                  /* 0 can write */
1005        retval = s->can_write ? 0 : 0x80;
1006        break;
1007
1008    case 0x0d:                  /* timer interrupt clear */
1009        /* dolog ("timer interrupt clear\n"); */
1010        retval = 0;
1011        break;
1012
1013    case 0x0e:                  /* data available status | irq 8 ack */
1014        retval = (!s->out_data_len || s->highspeed) ? 0 : 0x80;
1015        if (s->mixer_regs[0x82] & 1) {
1016            ack = 1;
1017            s->mixer_regs[0x82] &= ~1;
1018            qemu_irq_lower (s->pic);
1019        }
1020        break;
1021
1022    case 0x0f:                  /* irq 16 ack */
1023        retval = 0xff;
1024        if (s->mixer_regs[0x82] & 2) {
1025            ack = 1;
1026            s->mixer_regs[0x82] &= ~2;
1027            qemu_irq_lower (s->pic);
1028        }
1029        break;
1030
1031    default:
1032        goto error;
1033    }
1034
1035    if (!ack) {
1036        ldebug ("read %#x -> %#x\n", nport, retval);
1037    }
1038
1039    return retval;
1040
1041 error:
1042    dolog ("warning: dsp_read %#x error\n", nport);
1043    return 0xff;
1044}
1045
1046static void reset_mixer (SB16State *s)
1047{
1048    int i;
1049
1050    memset (s->mixer_regs, 0xff, 0x7f);
1051    memset (s->mixer_regs + 0x83, 0xff, sizeof (s->mixer_regs) - 0x83);
1052
1053    s->mixer_regs[0x02] = 4;    /* master volume 3bits */
1054    s->mixer_regs[0x06] = 4;    /* MIDI volume 3bits */
1055    s->mixer_regs[0x08] = 0;    /* CD volume 3bits */
1056    s->mixer_regs[0x0a] = 0;    /* voice volume 2bits */
1057
1058    /* d5=input filt, d3=lowpass filt, d1,d2=input source */
1059    s->mixer_regs[0x0c] = 0;
1060
1061    /* d5=output filt, d1=stereo switch */
1062    s->mixer_regs[0x0e] = 0;
1063
1064    /* voice volume L d5,d7, R d1,d3 */
1065    s->mixer_regs[0x04] = (4 << 5) | (4 << 1);
1066    /* master ... */
1067    s->mixer_regs[0x22] = (4 << 5) | (4 << 1);
1068    /* MIDI ... */
1069    s->mixer_regs[0x26] = (4 << 5) | (4 << 1);
1070
1071    for (i = 0x30; i < 0x48; i++) {
1072        s->mixer_regs[i] = 0x20;
1073    }
1074}
1075
1076static void mixer_write_indexb(void *opaque, uint32_t nport, uint32_t val)
1077{
1078    SB16State *s = opaque;
1079    (void) nport;
1080    s->mixer_nreg = val;
1081}
1082
1083static void mixer_write_datab(void *opaque, uint32_t nport, uint32_t val)
1084{
1085    SB16State *s = opaque;
1086
1087    (void) nport;
1088    ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val);
1089
1090    switch (s->mixer_nreg) {
1091    case 0x00:
1092        reset_mixer (s);
1093        break;
1094
1095    case 0x80:
1096        {
1097            int irq = irq_of_magic (val);
1098            ldebug ("setting irq to %d (val=%#x)\n", irq, val);
1099            if (irq > 0) {
1100                s->irq = irq;
1101            }
1102        }
1103        break;
1104
1105    case 0x81:
1106        {
1107            int dma, hdma;
1108
1109            dma = ctz32 (val & 0xf);
1110            hdma = ctz32 (val & 0xf0);
1111            if (dma != s->dma || hdma != s->hdma) {
1112                qemu_log_mask(LOG_GUEST_ERROR, "attempt to change DMA 8bit"
1113                              " %d(%d), 16bit %d(%d) (val=%#x)\n", dma, s->dma,
1114                              hdma, s->hdma, val);
1115            }
1116#if 0
1117            s->dma = dma;
1118            s->hdma = hdma;
1119#endif
1120        }
1121        break;
1122
1123    case 0x82:
1124        qemu_log_mask(LOG_GUEST_ERROR, "attempt to write into IRQ status"
1125                      " register (val=%#x)\n", val);
1126        return;
1127
1128    default:
1129        if (s->mixer_nreg >= 0x80) {
1130            ldebug ("attempt to write mixer[%#x] <- %#x\n", s->mixer_nreg, val);
1131        }
1132        break;
1133    }
1134
1135    s->mixer_regs[s->mixer_nreg] = val;
1136}
1137
1138static uint32_t mixer_read(void *opaque, uint32_t nport)
1139{
1140    SB16State *s = opaque;
1141
1142    (void) nport;
1143#ifndef DEBUG_SB16_MOST
1144    if (s->mixer_nreg != 0x82) {
1145        ldebug ("mixer_read[%#x] -> %#x\n",
1146                s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1147    }
1148#else
1149    ldebug ("mixer_read[%#x] -> %#x\n",
1150            s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1151#endif
1152    return s->mixer_regs[s->mixer_nreg];
1153}
1154
1155static int write_audio (SB16State *s, int nchan, int dma_pos,
1156                        int dma_len, int len)
1157{
1158    IsaDma *isa_dma = nchan == s->dma ? s->isa_dma : s->isa_hdma;
1159    IsaDmaClass *k = ISADMA_GET_CLASS(isa_dma);
1160    int temp, net;
1161    uint8_t tmpbuf[4096];
1162
1163    temp = len;
1164    net = 0;
1165
1166    while (temp) {
1167        int left = dma_len - dma_pos;
1168        int copied;
1169        size_t to_copy;
1170
1171        to_copy = audio_MIN (temp, left);
1172        if (to_copy > sizeof (tmpbuf)) {
1173            to_copy = sizeof (tmpbuf);
1174        }
1175
1176        copied = k->read_memory(isa_dma, nchan, tmpbuf, dma_pos, to_copy);
1177        copied = AUD_write (s->voice, tmpbuf, copied);
1178
1179        temp -= copied;
1180        dma_pos = (dma_pos + copied) % dma_len;
1181        net += copied;
1182
1183        if (!copied) {
1184            break;
1185        }
1186    }
1187
1188    return net;
1189}
1190
1191static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
1192{
1193    SB16State *s = opaque;
1194    int till, copy, written, free;
1195
1196    if (s->block_size <= 0) {
1197        qemu_log_mask(LOG_GUEST_ERROR, "invalid block size=%d nchan=%d"
1198                      " dma_pos=%d dma_len=%d\n", s->block_size, nchan,
1199                      dma_pos, dma_len);
1200        return dma_pos;
1201    }
1202
1203    if (s->left_till_irq < 0) {
1204        s->left_till_irq = s->block_size;
1205    }
1206
1207    if (s->voice) {
1208        free = s->audio_free & ~s->align;
1209        if ((free <= 0) || !dma_len) {
1210            return dma_pos;
1211        }
1212    }
1213    else {
1214        free = dma_len;
1215    }
1216
1217    copy = free;
1218    till = s->left_till_irq;
1219
1220#ifdef DEBUG_SB16_MOST
1221    dolog ("pos:%06d %d till:%d len:%d\n",
1222           dma_pos, free, till, dma_len);
1223#endif
1224
1225    if (till <= copy) {
1226        if (s->dma_auto == 0) {
1227            copy = till;
1228        }
1229    }
1230
1231    written = write_audio (s, nchan, dma_pos, dma_len, copy);
1232    dma_pos = (dma_pos + written) % dma_len;
1233    s->left_till_irq -= written;
1234
1235    if (s->left_till_irq <= 0) {
1236        s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
1237        qemu_irq_raise (s->pic);
1238        if (s->dma_auto == 0) {
1239            control (s, 0);
1240            speaker (s, 0);
1241        }
1242    }
1243
1244#ifdef DEBUG_SB16_MOST
1245    ldebug ("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n",
1246            dma_pos, free, dma_len, s->left_till_irq, copy, written,
1247            s->block_size);
1248#endif
1249
1250    while (s->left_till_irq <= 0) {
1251        s->left_till_irq = s->block_size + s->left_till_irq;
1252    }
1253
1254    return dma_pos;
1255}
1256
1257static void SB_audio_callback (void *opaque, int free)
1258{
1259    SB16State *s = opaque;
1260    s->audio_free = free;
1261}
1262
1263static int sb16_post_load (void *opaque, int version_id)
1264{
1265    SB16State *s = opaque;
1266
1267    if (s->voice) {
1268        AUD_close_out (&s->card, s->voice);
1269        s->voice = NULL;
1270    }
1271
1272    if (s->dma_running) {
1273        if (s->freq) {
1274            struct audsettings as;
1275
1276            s->audio_free = 0;
1277
1278            as.freq = s->freq;
1279            as.nchannels = 1 << s->fmt_stereo;
1280            as.fmt = s->fmt;
1281            as.endianness = 0;
1282
1283            s->voice = AUD_open_out (
1284                &s->card,
1285                s->voice,
1286                "sb16",
1287                s,
1288                SB_audio_callback,
1289                &as
1290                );
1291        }
1292
1293        control (s, 1);
1294        speaker (s, s->speaker);
1295    }
1296    return 0;
1297}
1298
1299static const VMStateDescription vmstate_sb16 = {
1300    .name = "sb16",
1301    .version_id = 1,
1302    .minimum_version_id = 1,
1303    .post_load = sb16_post_load,
1304    .fields = (VMStateField[]) {
1305        VMSTATE_UINT32 (irq, SB16State),
1306        VMSTATE_UINT32 (dma, SB16State),
1307        VMSTATE_UINT32 (hdma, SB16State),
1308        VMSTATE_UINT32 (port, SB16State),
1309        VMSTATE_UINT32 (ver, SB16State),
1310        VMSTATE_INT32 (in_index, SB16State),
1311        VMSTATE_INT32 (out_data_len, SB16State),
1312        VMSTATE_INT32 (fmt_stereo, SB16State),
1313        VMSTATE_INT32 (fmt_signed, SB16State),
1314        VMSTATE_INT32 (fmt_bits, SB16State),
1315        VMSTATE_UINT32 (fmt, SB16State),
1316        VMSTATE_INT32 (dma_auto, SB16State),
1317        VMSTATE_INT32 (block_size, SB16State),
1318        VMSTATE_INT32 (fifo, SB16State),
1319        VMSTATE_INT32 (freq, SB16State),
1320        VMSTATE_INT32 (time_const, SB16State),
1321        VMSTATE_INT32 (speaker, SB16State),
1322        VMSTATE_INT32 (needed_bytes, SB16State),
1323        VMSTATE_INT32 (cmd, SB16State),
1324        VMSTATE_INT32 (use_hdma, SB16State),
1325        VMSTATE_INT32 (highspeed, SB16State),
1326        VMSTATE_INT32 (can_write, SB16State),
1327        VMSTATE_INT32 (v2x6, SB16State),
1328
1329        VMSTATE_UINT8 (csp_param, SB16State),
1330        VMSTATE_UINT8 (csp_value, SB16State),
1331        VMSTATE_UINT8 (csp_mode, SB16State),
1332        VMSTATE_UINT8 (csp_param, SB16State),
1333        VMSTATE_BUFFER (csp_regs, SB16State),
1334        VMSTATE_UINT8 (csp_index, SB16State),
1335        VMSTATE_BUFFER (csp_reg83, SB16State),
1336        VMSTATE_INT32 (csp_reg83r, SB16State),
1337        VMSTATE_INT32 (csp_reg83w, SB16State),
1338
1339        VMSTATE_BUFFER (in2_data, SB16State),
1340        VMSTATE_BUFFER (out_data, SB16State),
1341        VMSTATE_UINT8 (test_reg, SB16State),
1342        VMSTATE_UINT8 (last_read_byte, SB16State),
1343
1344        VMSTATE_INT32 (nzero, SB16State),
1345        VMSTATE_INT32 (left_till_irq, SB16State),
1346        VMSTATE_INT32 (dma_running, SB16State),
1347        VMSTATE_INT32 (bytes_per_second, SB16State),
1348        VMSTATE_INT32 (align, SB16State),
1349
1350        VMSTATE_INT32 (mixer_nreg, SB16State),
1351        VMSTATE_BUFFER (mixer_regs, SB16State),
1352
1353        VMSTATE_END_OF_LIST ()
1354    }
1355};
1356
1357static const MemoryRegionPortio sb16_ioport_list[] = {
1358    {  4, 1, 1, .write = mixer_write_indexb },
1359    {  5, 1, 1, .read = mixer_read, .write = mixer_write_datab },
1360    {  6, 1, 1, .read = dsp_read, .write = dsp_write },
1361    { 10, 1, 1, .read = dsp_read },
1362    { 12, 1, 1, .write = dsp_write },
1363    { 12, 4, 1, .read = dsp_read },
1364    PORTIO_END_OF_LIST (),
1365};
1366
1367
1368static void sb16_initfn (Object *obj)
1369{
1370    SB16State *s = SB16 (obj);
1371
1372    s->cmd = -1;
1373}
1374
1375static void sb16_realizefn (DeviceState *dev, Error **errp)
1376{
1377    ISADevice *isadev = ISA_DEVICE (dev);
1378    SB16State *s = SB16 (dev);
1379    IsaDmaClass *k;
1380
1381    s->isa_hdma = isa_get_dma(isa_bus_from_device(isadev), s->hdma);
1382    s->isa_dma = isa_get_dma(isa_bus_from_device(isadev), s->dma);
1383    if (!s->isa_dma || !s->isa_hdma) {
1384        error_setg(errp, "ISA controller does not support DMA");
1385        return;
1386    }
1387
1388    isa_init_irq (isadev, &s->pic, s->irq);
1389
1390    s->mixer_regs[0x80] = magic_of_irq (s->irq);
1391    s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);
1392    s->mixer_regs[0x82] = 2 << 5;
1393
1394    s->csp_regs[5] = 1;
1395    s->csp_regs[9] = 0xf8;
1396
1397    reset_mixer (s);
1398    s->aux_ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, aux_timer, s);
1399    if (!s->aux_ts) {
1400        error_setg(errp, "warning: Could not create auxiliary timer");
1401    }
1402
1403    isa_register_portio_list(isadev, &s->portio_list, s->port,
1404                             sb16_ioport_list, s, "sb16");
1405
1406    k = ISADMA_GET_CLASS(s->isa_hdma);
1407    k->register_channel(s->isa_hdma, s->hdma, SB_read_DMA, s);
1408
1409    k = ISADMA_GET_CLASS(s->isa_dma);
1410    k->register_channel(s->isa_dma, s->dma, SB_read_DMA, s);
1411
1412    s->can_write = 1;
1413
1414    AUD_register_card ("sb16", &s->card);
1415}
1416
1417static int SB16_init (ISABus *bus)
1418{
1419    isa_create_simple (bus, TYPE_SB16);
1420    return 0;
1421}
1422
1423static Property sb16_properties[] = {
1424    DEFINE_PROP_UINT32 ("version", SB16State, ver,  0x0405), /* 4.5 */
1425    DEFINE_PROP_UINT32 ("iobase",  SB16State, port, 0x220),
1426    DEFINE_PROP_UINT32 ("irq",     SB16State, irq,  5),
1427    DEFINE_PROP_UINT32 ("dma",     SB16State, dma,  1),
1428    DEFINE_PROP_UINT32 ("dma16",   SB16State, hdma, 5),
1429    DEFINE_PROP_END_OF_LIST (),
1430};
1431
1432static void sb16_class_initfn (ObjectClass *klass, void *data)
1433{
1434    DeviceClass *dc = DEVICE_CLASS (klass);
1435
1436    dc->realize = sb16_realizefn;
1437    set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
1438    dc->desc = "Creative Sound Blaster 16";
1439    dc->vmsd = &vmstate_sb16;
1440    dc->props = sb16_properties;
1441}
1442
1443static const TypeInfo sb16_info = {
1444    .name          = TYPE_SB16,
1445    .parent        = TYPE_ISA_DEVICE,
1446    .instance_size = sizeof (SB16State),
1447    .instance_init = sb16_initfn,
1448    .class_init    = sb16_class_initfn,
1449};
1450
1451static void sb16_register_types (void)
1452{
1453    type_register_static (&sb16_info);
1454    isa_register_soundhw("sb16", "Creative Sound Blaster 16", SB16_init);
1455}
1456
1457type_init (sb16_register_types)
1458