void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)

{

    VGACommonState *s = opaque;

    int index;



    /* check port range access depending on color/monochrome mode */

    if (vga_ioport_invalid(s, addr)) {

        return;

    }

#ifdef DEBUG_VGA

    printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);

#endif



    switch(addr) {

    case VGA_ATT_W:

        if (s->ar_flip_flop == 0) {

            val &= 0x3f;

            s->ar_index = val;

        } else {

            index = s->ar_index & 0x1f;

            switch(index) {

            case VGA_ATC_PALETTE0 ... VGA_ATC_PALETTEF:

                s->ar[index] = val & 0x3f;

                break;

            case VGA_ATC_MODE:

                s->ar[index] = val & ~0x10;

                break;

            case VGA_ATC_OVERSCAN:

                s->ar[index] = val;

                break;

            case VGA_ATC_PLANE_ENABLE:

                s->ar[index] = val & ~0xc0;

                break;

            case VGA_ATC_PEL:

                s->ar[index] = val & ~0xf0;

                break;

            case VGA_ATC_COLOR_PAGE:

                s->ar[index] = val & ~0xf0;

                break;

            default:

                break;

            }

        }

        s->ar_flip_flop ^= 1;

        break;

    case VGA_MIS_W:

        s->msr = val & ~0x10;

        s->update_retrace_info(s);

        break;

    case VGA_SEQ_I:

        s->sr_index = val & 7;

        break;

    case VGA_SEQ_D:

#ifdef DEBUG_VGA_REG

        printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);

#endif

        s->sr[s->sr_index] = val & sr_mask[s->sr_index];

        vbe_update_vgaregs(s);

        if (s->sr_index == VGA_SEQ_CLOCK_MODE) {

            s->update_retrace_info(s);

        }

        vga_update_memory_access(s);

        break;

    case VGA_PEL_IR:

        s->dac_read_index = val;

        s->dac_sub_index = 0;

        s->dac_state = 3;

        break;

    case VGA_PEL_IW:

        s->dac_write_index = val;

        s->dac_sub_index = 0;

        s->dac_state = 0;

        break;

    case VGA_PEL_D:

        s->dac_cache[s->dac_sub_index] = val;

        if (++s->dac_sub_index == 3) {

            memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);

            s->dac_sub_index = 0;

            s->dac_write_index++;

        }

        break;

    case VGA_GFX_I:

        s->gr_index = val & 0x0f;

        break;

    case VGA_GFX_D:

#ifdef DEBUG_VGA_REG

        printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);

#endif

        s->gr[s->gr_index] = val & gr_mask[s->gr_index];

        vbe_update_vgaregs(s);

        vga_update_memory_access(s);

        break;

    case VGA_CRT_IM:

    case VGA_CRT_IC:

        s->cr_index = val;

        break;

    case VGA_CRT_DM:

    case VGA_CRT_DC:

#ifdef DEBUG_VGA_REG

        printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);

#endif

        /* handle CR0-7 protection */

        if ((s->cr[VGA_CRTC_V_SYNC_END] & VGA_CR11_LOCK_CR0_CR7) &&

            s->cr_index <= VGA_CRTC_OVERFLOW) {

            /* can always write bit 4 of CR7 */

            if (s->cr_index == VGA_CRTC_OVERFLOW) {

                s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x10) |

                    (val & 0x10);

                vbe_update_vgaregs(s);

            }

            return;

        }

        s->cr[s->cr_index] = val;

        vbe_update_vgaregs(s);



        switch(s->cr_index) {

        case VGA_CRTC_H_TOTAL:

        case VGA_CRTC_H_SYNC_START:

        case VGA_CRTC_H_SYNC_END:

        case VGA_CRTC_V_TOTAL:

        case VGA_CRTC_OVERFLOW:

        case VGA_CRTC_V_SYNC_END:

        case VGA_CRTC_MODE:

            s->update_retrace_info(s);

            break;

        }

        break;

    case VGA_IS1_RM:

    case VGA_IS1_RC:

        s->fcr = val & 0x10;

        break;

    }

}
