/*CMD640 emulation
  Currently only legacy mode emulated*/
#include "ibm.h"
#include "cmd640.h"
#include "ide.h"
#include "pci.h"

static uint8_t card_cmd640[256];

void cmd640_write(int func, int addr, uint8_t val, void *priv) {
        //        pclog("cmd640_write: func=%d addr=%02x val=%02x %04x:%08x\n", func, addr, val, CS, cpu_state.pc);
        if (func > 0)
                return;

        switch (addr) {
        case 0x04:
                ide_pri_disable();
                ide_sec_disable();
                if (val & 0x01) {
                        ide_pri_enable();
                        ide_sec_enable();
                }
                card_cmd640[0x04] = val & 0x41;
                break;
        case 0x07:
                card_cmd640[0x07] = val & 0x86;
                break;
        case 0x3c:
                card_cmd640[0x3c] = val;
                break;
        }
}

static uint8_t cmd640_read(int func, int addr, void *p) {
        //        pclog("cmd640_read: func=%d addr=%02x val=%02x %04x:%08x\n", func, addr, card_cmd640[addr], CS, cpu_state.pc);
        if (func > 0)
                return 0xff;

        return card_cmd640[addr];
}

void cmd640b_init(int card) {
        pci_add_specific(card, cmd640_read, cmd640_write, NULL);

        memset(card_cmd640, 0, 256);
        card_cmd640[0x00] = 0x95;
        card_cmd640[0x01] = 0x10; /**/
        card_cmd640[0x02] = 0x40;
        card_cmd640[0x03] = 0x06; /*CMD640*/
        card_cmd640[0x04] = 0x01;
        card_cmd640[0x05] = 0x00;
        card_cmd640[0x06] = 0x00;
        card_cmd640[0x07] = 0x02;
        card_cmd640[0x08] = 0x00; /*Revision*/
        card_cmd640[0x09] = 0x00; /*Programming interface*/
        card_cmd640[0x0a] = 0x01; /*Sub class - IDE controller*/
        card_cmd640[0x0b] = 0x01; /*Base class - Mass storage controller*/

        card_cmd640[0x3c] = 0x0e; /*Interrupt line*/
        card_cmd640[0x3d] = 1;

        card_cmd640[0x50] = 0x02; /*Revision = 2*/
        card_cmd640[0x51] = 0x80; /*2nd port disabled, drive 1 read ahead disabled*/
        card_cmd640[0x57] = 0x0c; /*Drive 2/3 read ahead disabled*/
        card_cmd640[0x59] = 0x40; /*Burst length*/

        ide_pri_disable();
        ide_sec_disable();
}
