gusemu_hal.c

来自「xen虚拟机源代码安装包」· C语言 代码 · 共 555 行 · 第 1/2 页

C
555
字号
/* * GUSEMU32 - bus interface part * * Copyright (C) 2000-2007 Tibor "TS" Schütz * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. *//* * TODO: check mixer: see 7.20 of sdk for panning pos (applies to all gus models?)? */#include "gustate.h"#include "gusemu.h"#define GUSregb(position) (*            (gusptr+(position)))#define GUSregw(position) (*(GUSword *) (gusptr+(position)))#define GUSregd(position) (*(GUSdword *)(gusptr+(position)))/* size given in bytes */unsigned int gus_read(GUSEmuState * state, int port, int size){    int             value_read = 0;    GUSbyte        *gusptr;    gusptr = state->gusdatapos;    GUSregd(portaccesses)++;    switch (port & 0xff0f)    {        /* MixerCtrlReg (read not supported on GUS classic) */        /* case 0x200: return GUSregb(MixerCtrlReg2x0); */    case 0x206:                          /* IRQstatReg / SB2x6IRQ */        /* adlib/sb bits set in port handlers */        /* timer/voice bits set in gus_irqgen() */        /* dma bit set in gus_dma_transferdata */        /* midi not implemented yet */        return GUSregb(IRQStatReg2x6);    /* case 0x308:                       */ /* AdLib388 */    case 0x208:        if (GUSregb(GUS45TimerCtrl) & 1)            return GUSregb(TimerStatus2x8);        return GUSregb(AdLibStatus2x8);  /* AdLibStatus */    case 0x309:                          /* AdLib389 */    case 0x209:        return GUSregb(AdLibData2x9);    /* AdLibData */    case 0x20A:        return GUSregb(AdLibCommand2xA); /* AdLib2x8_2xA */#if 0    case 0x20B:                          /* GUS hidden registers (read not supported on GUS classic) */        switch (GUSregb(RegCtrl_2xF) & 0x07)        {        case 0:                                 /* IRQ/DMA select */            if (GUSregb(MixerCtrlReg2x0) & 0x40)                return GUSregb(IRQ_2xB);        /* control register select bit */            else                return GUSregb(DMA_2xB);            /* case 1-5:                        */ /* general purpose emulation regs  */            /*  return ...                      */ /* + status reset reg (write only) */        case 6:            return GUSregb(Jumper_2xB);         /* Joystick/MIDI enable (JumperReg) */        default:;        }        break;#endif    case 0x20C:                          /* SB2xCd */        value_read = GUSregb(SB2xCd);        if (GUSregb(StatRead_2xF) & 0x20)            GUSregb(SB2xCd) ^= 0x80; /* toggle MSB on read */        return value_read;        /* case 0x20D:                   */ /* SB2xD is write only -> 2xE writes to it*/    case 0x20E:        if (GUSregb(RegCtrl_2xF) & 0x80) /* 2xE read IRQ enabled? */        {            GUSregb(StatRead_2xF) |= 0x80;            GUS_irqrequest(state, state->gusirq, 1);        }        return GUSregb(SB2xE);           /* SB2xE */    case 0x20F:                          /* StatRead_2xF */        /*set/clear fixed bits */        /*value_read = (GUSregb(StatRead_2xF) & 0xf9)|1; */ /*(LSB not set on GUS classic!)*/        value_read = (GUSregb(StatRead_2xF) & 0xf9);        if (GUSregb(MixerCtrlReg2x0) & 0x08)            value_read |= 2;    /* DMA/IRQ enabled flag */        return value_read;    /* case 0x300:                      */ /* MIDI (not implemented) */    /* case 0x301:                      */ /* MIDI (not implemented) */    case 0x302:        return GUSregb(VoiceSelReg3x2); /* VoiceSelReg */    case 0x303:        return GUSregb(FunkSelReg3x3);  /* FunkSelReg */    case 0x304:                         /* DataRegLoByte3x4 + DataRegWord3x4 */    case 0x305:                         /* DataRegHiByte3x5 */        switch (GUSregb(FunkSelReg3x3))        {    /* common functions */        case 0x41:                      /* DramDMAContrReg */            value_read = GUSregb(GUS41DMACtrl); /* &0xfb */            GUSregb(GUS41DMACtrl) &= 0xbb;            if (state->gusdma >= 4)                value_read |= 0x04;            if (GUSregb(IRQStatReg2x6) & 0x80)            {                value_read |= 0x40;                GUSregb(IRQStatReg2x6) &= 0x7f;                if (!GUSregb(IRQStatReg2x6))                    GUS_irqclear(state, state->gusirq);            }            return (GUSbyte) value_read;            /* DramDMAmemPosReg */            /* case 0x42: value_read=GUSregw(GUS42DMAStart); break;*/            /* 43h+44h write only */        case 0x45:            return GUSregb(GUS45TimerCtrl);         /* TimerCtrlReg */            /* 46h+47h write only */            /* 48h: samp freq - write only */        case 0x49:            return GUSregb(GUS49SampCtrl) & 0xbf;   /* SampCtrlReg */        /* case 4bh:                                */ /* joystick trim not supported */        /* case 0x4c: return GUSregb(GUS4cReset);   */ /* GUSreset: write only*/    /* voice specific functions */        case 0x80:        case 0x81:        case 0x82:        case 0x83:        case 0x84:        case 0x85:        case 0x86:        case 0x87:        case 0x88:        case 0x89:        case 0x8a:        case 0x8b:        case 0x8c:        case 0x8d:            {                int             offset = 2 * (GUSregb(FunkSelReg3x3) & 0x0f);                offset += ((int) GUSregb(VoiceSelReg3x2) & 0x1f) << 5; /* = Voice*32 + Funktion*2 */                value_read = GUSregw(offset);            }            break;    /* voice unspecific functions */        case 0x8e:                                  /* NumVoice */            return GUSregb(NumVoices);        case 0x8f:                                  /* irqstatreg */            /* (pseudo IRQ-FIFO is processed during a gus_write(0x3X3,0x8f)) */            return GUSregb(SynVoiceIRQ8f);        default:            return 0xffff;        }        if (size == 1)        {            if ((port & 0xff0f) == 0x305)                value_read = value_read >> 8;            value_read &= 0xff;        }        return (GUSword) value_read;    /* case 0x306:                                  */ /* Mixer/Version info */        /*  return 0xff; */ /* Pre 3.6 boards, ICS mixer NOT present */    case 0x307:                                     /* DRAMaccess */        {            GUSbyte        *adr;            adr = state->himemaddr + (GUSregd(GUSDRAMPOS24bit) & 0xfffff);            return *adr;        }    default:;    }    return 0xffff;}void gus_write(GUSEmuState * state, int port, int size, unsigned int data){    GUSbyte        *gusptr;    gusptr = state->gusdatapos;    GUSregd(portaccesses)++;    switch (port & 0xff0f)    {    case 0x200:                 /* MixerCtrlReg */        GUSregb(MixerCtrlReg2x0) = (GUSbyte) data;        break;    case 0x206:                 /* IRQstatReg / SB2x6IRQ */        if (GUSregb(GUS45TimerCtrl) & 0x20) /* SB IRQ enabled? -> set 2x6IRQ bit */        {            GUSregb(TimerStatus2x8) |= 0x08;            GUSregb(IRQStatReg2x6) = 0x10;            GUS_irqrequest(state, state->gusirq, 1);        }        break;    case 0x308:                /* AdLib 388h */    case 0x208:                /* AdLibCommandReg */        GUSregb(AdLibCommand2xA) = (GUSbyte) data;        break;    case 0x309:                /* AdLib 389h */    case 0x209:                /* AdLibDataReg */        if ((GUSregb(AdLibCommand2xA) == 0x04) && (!(GUSregb(GUS45TimerCtrl) & 1))) /* GUS auto timer mode enabled? */        {            if (data & 0x80)                GUSregb(TimerStatus2x8) &= 0x1f; /* AdLib IRQ reset? -> clear maskable adl. timer int regs */            else                GUSregb(TimerDataReg2x9) = (GUSbyte) data;        }        else        {            GUSregb(AdLibData2x9) = (GUSbyte) data;            if (GUSregb(GUS45TimerCtrl) & 0x02)            {                GUSregb(TimerStatus2x8) |= 0x01;                GUSregb(IRQStatReg2x6) = 0x10;                GUS_irqrequest(state, state->gusirq, 1);            }        }        break;    case 0x20A:        GUSregb(AdLibStatus2x8) = (GUSbyte) data;        break;                 /* AdLibStatus2x8 */    case 0x20B:                /* GUS hidden registers */        switch (GUSregb(RegCtrl_2xF) & 0x7)        {        case 0:            if (GUSregb(MixerCtrlReg2x0) & 0x40)                GUSregb(IRQ_2xB) = (GUSbyte) data; /* control register select bit */            else                GUSregb(DMA_2xB) = (GUSbyte) data;            break;            /* case 1-4: general purpose emulation regs */        case 5:                                    /* clear stat reg 2xF */            GUSregb(StatRead_2xF) = 0; /* ToDo: is this identical with GUS classic? */            if (!GUSregb(IRQStatReg2x6))                GUS_irqclear(state, state->gusirq);            break;        case 6:                                    /* Jumper reg (Joystick/MIDI enable) */            GUSregb(Jumper_2xB) = (GUSbyte) data;            break;        default:;        }        break;    case 0x20C:                /* SB2xCd */        if (GUSregb(GUS45TimerCtrl) & 0x20)        {            GUSregb(TimerStatus2x8) |= 0x10; /* SB IRQ enabled? -> set 2xCIRQ bit */            GUSregb(IRQStatReg2x6) = 0x10;            GUS_irqrequest(state, state->gusirq, 1);        }    case 0x20D:                /* SB2xCd no IRQ */        GUSregb(SB2xCd) = (GUSbyte) data;        break;    case 0x20E:                /* SB2xE */        GUSregb(SB2xE) = (GUSbyte) data;        break;    case 0x20F:        GUSregb(RegCtrl_2xF) = (GUSbyte) data;        break;                 /* CtrlReg2xF */    case 0x302:                /* VoiceSelReg */        GUSregb(VoiceSelReg3x2) = (GUSbyte) data;        break;    case 0x303:                /* FunkSelReg */        GUSregb(FunkSelReg3x3) = (GUSbyte) data;        if ((GUSbyte) data == 0x8f) /* set irqstatreg, get voicereg and clear IRQ */        {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?