#include "ibm.h" #include "82091aa.h" #include "fdc.h" #include "io.h" #include "lpt.h" #include "serial.h" #define AIP_AIPID 0x00 #define AIP_AIPREV 0x01 #define AIP_AIPCFG1 0x02 #define AIP_AIPCFG2 0x03 #define AIP_FCFG1 0x10 #define AIP_FCFG2 0x11 #define AIP_PCFG1 0x20 #define AIP_PCFG2 0x21 #define AIP_SACFG1 0x30 #define AIP_SACFG2 0x31 #define AIP_SBCFG1 0x40 #define AIP_SBCFG2 0x41 #define AIP_IDECFG 0x50 #define FCFG1_FDC_ENA (1 << 0) #define FCFG1_FDC_ADDR (1 << 1) #define PCFG1_PP_ENA (1 << 0) #define PCFG1_PP_ADDR (3 << 1) #define PCFG1_PP_ADDR_378 (0 << 1) #define PCFG1_PP_ADDR_278 (1 << 1) #define PCFG1_PP_ADDR_3BC (2 << 1) #define SxCFG1_ENA (1 << 0) #define SxCFG1_ADDR (7 << 1) #define SxCFG1_ADDR_3F8 (0 << 1) #define SxCFG1_ADDR_2F8 (1 << 1) #define SxCFG1_ADDR_220 (2 << 1) #define SxCFG1_ADDR_228 (3 << 1) #define SxCFG1_ADDR_238 (4 << 1) #define SxCFG1_ADDR_2E8 (5 << 1) #define SxCFG1_ADDR_338 (6 << 1) #define SxCFG1_ADDR_3E8 (7 << 1) #define SxCFG1_IRQ (1 << 4) #define SxCFG1_IRQ_3 (0 << 4) #define SxCFG1_IRQ_4 (1 << 4) static struct { int idx; uint8_t regs[256]; } aip; static uint8_t aip_read(uint16_t addr, void *p) { uint8_t temp; if (!(addr & 1)) temp = aip.idx; else temp = aip.regs[aip.idx]; // pclog("aip_read: addr=%04x val=%02x\n", addr, temp); return temp; } static void aip_write(uint16_t addr, uint8_t val, void *p) { // pclog("aip_write: addr=%04x val=%02x\n", addr, val); if (!(addr & 1)) aip.idx = val; else { // pclog("AIP register write: idx=%02x val=%02x\n", aip.idx, val); switch (aip.idx) { case AIP_AIPCFG1: aip.regs[AIP_AIPCFG1] = (val & ~0x4e) | (aip.regs[AIP_AIPCFG1] & 0x48); break; case AIP_AIPCFG2: aip.regs[AIP_AIPCFG2] = val & 0xf8; break; case AIP_FCFG1: aip.regs[AIP_FCFG1] = val & 0x83; fdc_remove(); if ((aip.regs[AIP_FCFG1] & FCFG1_FDC_ENA) && !(aip.regs[AIP_FCFG1] & FCFG1_FDC_ADDR)) fdc_add(); break; case AIP_FCFG2: aip.regs[AIP_FCFG2] = (val & 0x0d) | (aip.regs[AIP_FCFG2] & 0x02); break; case AIP_PCFG1: aip.regs[AIP_PCFG1] = val & 0xef; lpt1_remove(); if (aip.regs[AIP_PCFG1] & PCFG1_PP_ENA) { switch (aip.regs[AIP_PCFG1] & PCFG1_PP_ADDR) { case PCFG1_PP_ADDR_378: lpt1_init(0x378); break; case PCFG1_PP_ADDR_278: lpt1_init(0x278); break; case PCFG1_PP_ADDR_3BC: lpt1_init(0x3bc); break; } } break; case AIP_PCFG2: aip.regs[AIP_PCFG2] = (val & 0x0d) | (aip.regs[AIP_PCFG2] & 0x22); break; case AIP_SACFG1: aip.regs[AIP_SACFG1] = val & 0x9f; serial1_remove(); if (aip.regs[AIP_SACFG1] & SxCFG1_ENA) { uint16_t base = 0; int irq = 0; switch (aip.regs[AIP_SACFG1] & SxCFG1_ADDR) { case SxCFG1_ADDR_3F8: base = 0x3f8; break; case SxCFG1_ADDR_2F8: base = 0x2f8; break; case SxCFG1_ADDR_220: base = 0x220; break; case SxCFG1_ADDR_228: base = 0x228; break; case SxCFG1_ADDR_238: base = 0x238; break; case SxCFG1_ADDR_2E8: base = 0x2e8; break; case SxCFG1_ADDR_338: base = 0x338; break; case SxCFG1_ADDR_3E8: base = 0x3e8; break; } switch (aip.regs[AIP_SACFG1] & SxCFG1_IRQ) { case SxCFG1_IRQ_3: irq = 3; break; case SxCFG1_IRQ_4: irq = 4; break; } serial1_set(base, irq); } break; case AIP_SACFG2: aip.regs[AIP_SACFG2] = (val & 0x01d) | (aip.regs[AIP_SACFG2] & 0x02); break; case AIP_SBCFG1: aip.regs[AIP_SBCFG1] = val & 0x9f; serial2_remove(); if (aip.regs[AIP_SBCFG1] & SxCFG1_ENA) { uint16_t base = 0; int irq = 0; switch (aip.regs[AIP_SBCFG1] & SxCFG1_ADDR) { case SxCFG1_ADDR_3F8: base = 0x3f8; break; case SxCFG1_ADDR_2F8: base = 0x2f8; break; case SxCFG1_ADDR_220: base = 0x220; break; case SxCFG1_ADDR_228: base = 0x228; break; case SxCFG1_ADDR_238: base = 0x238; break; case SxCFG1_ADDR_2E8: base = 0x2e8; break; case SxCFG1_ADDR_338: base = 0x338; break; case SxCFG1_ADDR_3E8: base = 0x3e8; break; } switch (aip.regs[AIP_SBCFG1] & SxCFG1_IRQ) { case SxCFG1_IRQ_3: irq = 3; break; case SxCFG1_IRQ_4: irq = 4; break; } serial2_set(base, irq); } break; case AIP_SBCFG2: aip.regs[AIP_SACFG2] = (val & 0x01d) | (aip.regs[AIP_SACFG2] & 0x02); break; case AIP_IDECFG: aip.regs[AIP_IDECFG] = val & 0x07; break; } } } void aip_82091aa_init(uint16_t base) { io_sethandler(base, 0x0002, aip_read, NULL, NULL, aip_write, NULL, NULL, NULL); memset(&aip.regs, 0xff, sizeof(aip.regs)); aip.regs[AIP_AIPID] = 0xa0; aip.regs[AIP_AIPREV] = 0x00; aip.regs[AIP_AIPCFG1] = 0x40; aip.regs[AIP_AIPCFG2] = 0x00; aip.regs[AIP_FCFG1] = 0x01; aip.regs[AIP_FCFG2] = 0x00; aip.regs[AIP_PCFG1] = 0x00; aip.regs[AIP_PCFG2] = 0x00; aip.regs[AIP_SACFG1] = 0x00; aip.regs[AIP_SACFG2] = 0x02; aip.regs[AIP_SBCFG1] = 0x00; aip.regs[AIP_SBCFG2] = 0x02; aip.regs[AIP_IDECFG] = 0x01; }