Applied all relevant mainline PCem commits (VME emulation, AT ESDI controller).
This commit is contained in:
@@ -265,6 +265,38 @@ void x86_int_sw(int num)
|
|||||||
CPU_BLOCK_END();
|
CPU_BLOCK_END();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int x86_int_sw_rm(int num)
|
||||||
|
{
|
||||||
|
uint32_t addr;
|
||||||
|
uint16_t new_pc, new_cs;
|
||||||
|
|
||||||
|
flags_rebuild();
|
||||||
|
cycles -= timing_int;
|
||||||
|
|
||||||
|
addr = num << 2;
|
||||||
|
new_pc = readmemw(0, addr);
|
||||||
|
new_cs = readmemw(0, addr + 2);
|
||||||
|
|
||||||
|
if (cpu_state.abrt) return 1;
|
||||||
|
|
||||||
|
writememw(ss,((SP-2)&0xFFFF),flags); if (cpu_state.abrt) {pclog("abrt5\n"); return 1; }
|
||||||
|
writememw(ss,((SP-4)&0xFFFF),CS);
|
||||||
|
writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); if (cpu_state.abrt) {pclog("abrt6\n"); return 1; }
|
||||||
|
SP-=6;
|
||||||
|
|
||||||
|
eflags &= ~VIF_FLAG;
|
||||||
|
flags &= ~T_FLAG;
|
||||||
|
cpu_state.pc = new_pc;
|
||||||
|
loadcs(new_cs);
|
||||||
|
oxpc=cpu_state.pc;
|
||||||
|
|
||||||
|
cycles -= timing_int_rm;
|
||||||
|
trap = 0;
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void x86illegal()
|
void x86illegal()
|
||||||
{
|
{
|
||||||
x86_int(6);
|
x86_int(6);
|
||||||
|
|||||||
@@ -547,7 +547,7 @@ void dumpregs(int force)
|
|||||||
if (is386)
|
if (is386)
|
||||||
{
|
{
|
||||||
printf("386 in %s mode stack in %s mode\n",(use32)?"32-bit":"16-bit",(stack32)?"32-bit":"16-bit");
|
printf("386 in %s mode stack in %s mode\n",(use32)?"32-bit":"16-bit",(stack32)?"32-bit":"16-bit");
|
||||||
printf("CR0=%08X CR2=%08X CR3=%08X\n",cr0,cr2,cr3);
|
printf("CR0=%08X CR2=%08X CR3=%08X CR4=%08x\n",cr0,cr2,cr3, cr4);
|
||||||
}
|
}
|
||||||
printf("Entries in readlookup : %i writelookup : %i\n",readlnum,writelnum);
|
printf("Entries in readlookup : %i writelookup : %i\n",readlnum,writelnum);
|
||||||
for (c=0;c<1024*1024;c++)
|
for (c=0;c<1024*1024;c++)
|
||||||
|
|||||||
@@ -16,11 +16,15 @@ static uint32_t ropSTD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32
|
|||||||
|
|
||||||
static uint32_t ropCLI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
static uint32_t ropCLI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||||
{
|
{
|
||||||
|
if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI)))
|
||||||
|
return 0;
|
||||||
CLEAR_BITS((uintptr_t)&flags, I_FLAG);
|
CLEAR_BITS((uintptr_t)&flags, I_FLAG);
|
||||||
return op_pc;
|
return op_pc;
|
||||||
}
|
}
|
||||||
static uint32_t ropSTI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
static uint32_t ropSTI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||||
{
|
{
|
||||||
|
if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI)))
|
||||||
|
return 0;
|
||||||
SET_BITS((uintptr_t)&flags, I_FLAG);
|
SET_BITS((uintptr_t)&flags, I_FLAG);
|
||||||
return op_pc;
|
return op_pc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ OpFn *x86_opcodes_df_a32;
|
|||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
CPUID_FPU = (1 << 0),
|
CPUID_FPU = (1 << 0),
|
||||||
|
CPUID_VME = (1 << 1),
|
||||||
CPUID_TSC = (1 << 4),
|
CPUID_TSC = (1 << 4),
|
||||||
CPUID_MSR = (1 << 5),
|
CPUID_MSR = (1 << 5),
|
||||||
CPUID_CMPXCHG8B = (1 << 8),
|
CPUID_CMPXCHG8B = (1 << 8),
|
||||||
@@ -90,6 +91,7 @@ int cpu_busspeed;
|
|||||||
int cpu_hasrdtsc;
|
int cpu_hasrdtsc;
|
||||||
int cpu_hasMMX, cpu_hasMSR;
|
int cpu_hasMMX, cpu_hasMSR;
|
||||||
int cpu_hasCR4;
|
int cpu_hasCR4;
|
||||||
|
int cpu_hasVME;
|
||||||
int cpu_use_dynarec;
|
int cpu_use_dynarec;
|
||||||
int cpu_cyrix_alignment;
|
int cpu_cyrix_alignment;
|
||||||
|
|
||||||
@@ -365,8 +367,8 @@ CPU cpus_i486[] =
|
|||||||
{"i486DX2/40", CPU_i486DX, 4, 40000000, 2, 20000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6},
|
{"i486DX2/40", CPU_i486DX, 4, 40000000, 2, 20000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6},
|
||||||
{"i486DX2/50", CPU_i486DX, 5, 50000000, 2, 25000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6},
|
{"i486DX2/50", CPU_i486DX, 5, 50000000, 2, 25000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6},
|
||||||
{"i486DX2/66", CPU_i486DX, 6, 66666666, 2, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6},
|
{"i486DX2/66", CPU_i486DX, 6, 66666666, 2, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6},
|
||||||
{"iDX4/75", CPU_i486DX, 7, 75000000, 3, 25000000, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9}, /*CPUID available on DX4, >= 75 MHz*/
|
{"iDX4/75", CPU_iDX4, 7, 75000000, 3, 25000000, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9}, /*CPUID available on DX4, >= 75 MHz*/
|
||||||
{"iDX4/100", CPU_i486DX,10, 100000000, 3, 33333333, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9}, /*Is on some real Intel DX2s, limit here is pretty arbitary*/
|
{"iDX4/100", CPU_iDX4, 10, 100000000, 3, 33333333, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9}, /*Is on some real Intel DX2s, limit here is pretty arbitary*/
|
||||||
{"Pentium OverDrive/63", CPU_PENTIUM, 6, 62500000, 3, 25000000, 0x1531, 0x1531, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,7,7},
|
{"Pentium OverDrive/63", CPU_PENTIUM, 6, 62500000, 3, 25000000, 0x1531, 0x1531, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,7,7},
|
||||||
{"Pentium OverDrive/83", CPU_PENTIUM, 8, 83333333, 3, 33333333, 0x1532, 0x1532, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,8,8},
|
{"Pentium OverDrive/83", CPU_PENTIUM, 8, 83333333, 3, 33333333, 0x1532, 0x1532, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,8,8},
|
||||||
{"", -1, 0, 0, 0}
|
{"", -1, 0, 0, 0}
|
||||||
@@ -991,6 +993,10 @@ void cpu_set()
|
|||||||
timing_misaligned = 3;
|
timing_misaligned = 3;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CPU_iDX4:
|
||||||
|
cpu_hasCR4 = 1;
|
||||||
|
cpu_hasVME = 1;
|
||||||
|
cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_VME;
|
||||||
case CPU_i486SX:
|
case CPU_i486SX:
|
||||||
case CPU_i486DX:
|
case CPU_i486DX:
|
||||||
x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f);
|
x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f);
|
||||||
@@ -1204,7 +1210,8 @@ void cpu_set()
|
|||||||
cpu_hasMMX = 0;
|
cpu_hasMMX = 0;
|
||||||
cpu_hasMSR = 1;
|
cpu_hasMSR = 1;
|
||||||
cpu_hasCR4 = 1;
|
cpu_hasCR4 = 1;
|
||||||
cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE;
|
cpu_hasVME = 1;
|
||||||
|
cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE;
|
||||||
codegen_timing_set(&codegen_timing_pentium);
|
codegen_timing_set(&codegen_timing_pentium);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1244,7 +1251,8 @@ void cpu_set()
|
|||||||
cpu_hasMMX = 1;
|
cpu_hasMMX = 1;
|
||||||
cpu_hasMSR = 1;
|
cpu_hasMSR = 1;
|
||||||
cpu_hasCR4 = 1;
|
cpu_hasCR4 = 1;
|
||||||
cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE;
|
cpu_hasVME = 1;
|
||||||
|
cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE;
|
||||||
codegen_timing_set(&codegen_timing_pentium);
|
codegen_timing_set(&codegen_timing_pentium);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1443,7 +1451,8 @@ void cpu_set()
|
|||||||
cpu_hasMMX = 1;
|
cpu_hasMMX = 1;
|
||||||
cpu_hasMSR = 1;
|
cpu_hasMSR = 1;
|
||||||
cpu_hasCR4 = 1;
|
cpu_hasCR4 = 1;
|
||||||
cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE;
|
cpu_hasVME = 1;
|
||||||
|
cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE;
|
||||||
codegen_timing_set(&codegen_timing_pentium);
|
codegen_timing_set(&codegen_timing_pentium);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1476,7 +1485,8 @@ void cpu_set()
|
|||||||
cpu_hasMMX = 0;
|
cpu_hasMMX = 0;
|
||||||
cpu_hasMSR = 1;
|
cpu_hasMSR = 1;
|
||||||
cpu_hasCR4 = 1;
|
cpu_hasCR4 = 1;
|
||||||
cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE;
|
cpu_hasVME = 1;
|
||||||
|
cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE;
|
||||||
codegen_timing_set(&codegen_timing_686);
|
codegen_timing_set(&codegen_timing_686);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1510,7 +1520,8 @@ void cpu_set()
|
|||||||
cpu_hasMMX = 1;
|
cpu_hasMMX = 1;
|
||||||
cpu_hasMSR = 1;
|
cpu_hasMSR = 1;
|
||||||
cpu_hasCR4 = 1;
|
cpu_hasCR4 = 1;
|
||||||
cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE;
|
cpu_hasVME = 1;
|
||||||
|
cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE;
|
||||||
codegen_timing_set(&codegen_timing_686);
|
codegen_timing_set(&codegen_timing_686);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
@@ -1544,7 +1555,8 @@ void cpu_set()
|
|||||||
cpu_hasMMX = 1;
|
cpu_hasMMX = 1;
|
||||||
cpu_hasMSR = 1;
|
cpu_hasMSR = 1;
|
||||||
cpu_hasCR4 = 1;
|
cpu_hasCR4 = 1;
|
||||||
cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE | CR4_OSFXSR;
|
cpu_hasVME = 1;
|
||||||
|
cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE | CR4_OSFXSR;
|
||||||
codegen_timing_set(&codegen_timing_686);
|
codegen_timing_set(&codegen_timing_686);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1575,6 +1587,24 @@ void cpu_CPUID()
|
|||||||
EAX = 0;
|
EAX = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CPU_iDX4:
|
||||||
|
if (!EAX)
|
||||||
|
{
|
||||||
|
EAX = 0x00000001;
|
||||||
|
EBX = 0x756e6547;
|
||||||
|
EDX = 0x49656e69;
|
||||||
|
ECX = 0x6c65746e;
|
||||||
|
}
|
||||||
|
else if (EAX == 1)
|
||||||
|
{
|
||||||
|
EAX = CPUID;
|
||||||
|
EBX = ECX = 0;
|
||||||
|
EDX = CPUID_FPU | CPUID_VME;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
EAX = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
case CPU_Am486SX:
|
case CPU_Am486SX:
|
||||||
if (!EAX)
|
if (!EAX)
|
||||||
{
|
{
|
||||||
@@ -1651,7 +1681,7 @@ void cpu_CPUID()
|
|||||||
{
|
{
|
||||||
EAX = CPUID;
|
EAX = CPUID;
|
||||||
EBX = ECX = 0;
|
EBX = ECX = 0;
|
||||||
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B;
|
EDX = CPUID_FPU | CPUID_VME | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
EAX = 0;
|
EAX = 0;
|
||||||
@@ -1739,7 +1769,7 @@ void cpu_CPUID()
|
|||||||
{
|
{
|
||||||
EAX = CPUID;
|
EAX = CPUID;
|
||||||
EBX = ECX = 0;
|
EBX = ECX = 0;
|
||||||
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B;
|
EDX = CPUID_FPU | CPUID_VME | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B;
|
||||||
}
|
}
|
||||||
else if (EAX == 0x80000000)
|
else if (EAX == 0x80000000)
|
||||||
{
|
{
|
||||||
@@ -1750,7 +1780,7 @@ void cpu_CPUID()
|
|||||||
{
|
{
|
||||||
EAX = CPUID + 0x100;
|
EAX = CPUID + 0x100;
|
||||||
EBX = ECX = 0;
|
EBX = ECX = 0;
|
||||||
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_AMDSEP;
|
EDX = CPUID_FPU | CPUID_VME | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_AMDSEP;
|
||||||
}
|
}
|
||||||
else if (EAX == 0x80000002)
|
else if (EAX == 0x80000002)
|
||||||
{
|
{
|
||||||
@@ -1801,7 +1831,7 @@ void cpu_CPUID()
|
|||||||
{
|
{
|
||||||
EAX = CPUID;
|
EAX = CPUID;
|
||||||
EBX = ECX = 0;
|
EBX = ECX = 0;
|
||||||
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX;
|
EDX = CPUID_FPU | CPUID_VME | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
EAX = 0;
|
EAX = 0;
|
||||||
@@ -1896,7 +1926,7 @@ void cpu_CPUID()
|
|||||||
{
|
{
|
||||||
EAX = CPUID;
|
EAX = CPUID;
|
||||||
EBX = ECX = 0;
|
EBX = ECX = 0;
|
||||||
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_SEP | CPUID_CMOV;
|
EDX = CPUID_FPU | CPUID_VME | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_SEP | CPUID_CMOV;
|
||||||
}
|
}
|
||||||
else if (EAX == 2)
|
else if (EAX == 2)
|
||||||
{
|
{
|
||||||
@@ -1917,7 +1947,7 @@ void cpu_CPUID()
|
|||||||
{
|
{
|
||||||
EAX = CPUID;
|
EAX = CPUID;
|
||||||
EBX = ECX = 0;
|
EBX = ECX = 0;
|
||||||
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_SEP | CPUID_CMOV;
|
EDX = CPUID_FPU | CPUID_VME | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_SEP | CPUID_CMOV;
|
||||||
}
|
}
|
||||||
else if (EAX == 2)
|
else if (EAX == 2)
|
||||||
{
|
{
|
||||||
@@ -1941,7 +1971,7 @@ void cpu_CPUID()
|
|||||||
{
|
{
|
||||||
EAX = CPUID;
|
EAX = CPUID;
|
||||||
EBX = ECX = 0;
|
EBX = ECX = 0;
|
||||||
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_SEP | CPUID_FXSR | CPUID_CMOV;
|
EDX = CPUID_FPU | CPUID_VME | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_SEP | CPUID_FXSR | CPUID_CMOV;
|
||||||
}
|
}
|
||||||
else if (EAX == 2)
|
else if (EAX == 2)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -44,26 +44,27 @@ extern int cpu, cpu_manufacturer;
|
|||||||
#define CPU_i486DX 11
|
#define CPU_i486DX 11
|
||||||
#define CPU_Am486DX 12
|
#define CPU_Am486DX 12
|
||||||
#define CPU_Cx486DX 13
|
#define CPU_Cx486DX 13
|
||||||
#define CPU_Cx5x86 14
|
#define CPU_iDX4 14
|
||||||
|
#define CPU_Cx5x86 15
|
||||||
|
|
||||||
/*586 class CPUs*/
|
/*586 class CPUs*/
|
||||||
#define CPU_WINCHIP 15
|
#define CPU_WINCHIP 16
|
||||||
#define CPU_PENTIUM 16
|
#define CPU_PENTIUM 17
|
||||||
#define CPU_PENTIUMMMX 17
|
#define CPU_PENTIUMMMX 18
|
||||||
#define CPU_Cx6x86 18
|
#define CPU_Cx6x86 19
|
||||||
#define CPU_Cx6x86MX 19
|
#define CPU_Cx6x86MX 20
|
||||||
#define CPU_Cx6x86L 20
|
#define CPU_Cx6x86L 21
|
||||||
#define CPU_CxGX1 21
|
#define CPU_CxGX1 22
|
||||||
#define CPU_K5 22
|
#define CPU_K5 23
|
||||||
#define CPU_5K86 23
|
#define CPU_5K86 24
|
||||||
#define CPU_K6 24
|
#define CPU_K6 25
|
||||||
|
|
||||||
/*686 class CPUs*/
|
/*686 class CPUs*/
|
||||||
#define CPU_PENTIUMPRO 25
|
#define CPU_PENTIUMPRO 26
|
||||||
/*
|
/*
|
||||||
#define CPU_PENTIUM2 26
|
#define CPU_PENTIUM2 27
|
||||||
#define CPU_PENTIUM2D 27 */
|
#define CPU_PENTIUM2D 28 */
|
||||||
#define CPU_PENTIUM2D 26
|
#define CPU_PENTIUM2D 27
|
||||||
|
|
||||||
#define MANU_INTEL 0
|
#define MANU_INTEL 0
|
||||||
#define MANU_AMD 1
|
#define MANU_AMD 1
|
||||||
@@ -144,6 +145,7 @@ extern int cpu_hasrdtsc;
|
|||||||
extern int cpu_hasMSR;
|
extern int cpu_hasMSR;
|
||||||
extern int cpu_hasMMX;
|
extern int cpu_hasMMX;
|
||||||
extern int cpu_hasCR4;
|
extern int cpu_hasCR4;
|
||||||
|
extern int cpu_hasVME;
|
||||||
|
|
||||||
#define CR4_TSD (1 << 2)
|
#define CR4_TSD (1 << 2)
|
||||||
#define CR4_DE (1 << 3)
|
#define CR4_DE (1 << 3)
|
||||||
|
|||||||
@@ -26,10 +26,18 @@ static int opCLD(uint32_t fetchdat)
|
|||||||
static int opCLI(uint32_t fetchdat)
|
static int opCLI(uint32_t fetchdat)
|
||||||
{
|
{
|
||||||
if (!IOPLp)
|
if (!IOPLp)
|
||||||
|
{
|
||||||
|
if ((!(eflags & VM_FLAG) && (cr4 & CR4_PVI)) ||
|
||||||
|
((eflags & VM_FLAG) && (cr4 & CR4_VME)))
|
||||||
|
{
|
||||||
|
eflags &= ~VIF_FLAG;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
x86gpf(NULL,0);
|
x86gpf(NULL,0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
flags &= ~I_FLAG;
|
flags &= ~I_FLAG;
|
||||||
|
|
||||||
@@ -56,10 +64,24 @@ static int opSTD(uint32_t fetchdat)
|
|||||||
static int opSTI(uint32_t fetchdat)
|
static int opSTI(uint32_t fetchdat)
|
||||||
{
|
{
|
||||||
if (!IOPLp)
|
if (!IOPLp)
|
||||||
|
{
|
||||||
|
if ((!(eflags & VM_FLAG) && (cr4 & CR4_PVI)) ||
|
||||||
|
((eflags & VM_FLAG) && (cr4 & CR4_VME)))
|
||||||
|
{
|
||||||
|
if (eflags & VIP_FLAG)
|
||||||
{
|
{
|
||||||
x86gpf(NULL,0);
|
x86gpf(NULL,0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
eflags |= VIF_FLAG;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86gpf(NULL,0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
flags |= I_FLAG;
|
flags |= I_FLAG;
|
||||||
|
|
||||||
@@ -93,12 +115,28 @@ static int opLAHF(uint32_t fetchdat)
|
|||||||
static int opPUSHF(uint32_t fetchdat)
|
static int opPUSHF(uint32_t fetchdat)
|
||||||
{
|
{
|
||||||
if ((eflags & VM_FLAG) && (IOPL < 3))
|
if ((eflags & VM_FLAG) && (IOPL < 3))
|
||||||
|
{
|
||||||
|
if (cr4 & CR4_VME)
|
||||||
|
{
|
||||||
|
uint16_t temp;
|
||||||
|
|
||||||
|
flags_rebuild();
|
||||||
|
temp = (flags & ~I_FLAG) | 0x3000;
|
||||||
|
if (eflags & VIF_FLAG)
|
||||||
|
temp |= I_FLAG;
|
||||||
|
PUSH_W(temp);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
x86gpf(NULL,0);
|
x86gpf(NULL,0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
flags_rebuild();
|
flags_rebuild();
|
||||||
PUSH_W(flags);
|
PUSH_W(flags);
|
||||||
|
}
|
||||||
CLOCK_CYCLES(4);
|
CLOCK_CYCLES(4);
|
||||||
PREFETCH_RUN(4, 1, -1, 0,0,1,0, 0);
|
PREFETCH_RUN(4, 1, -1, 0,0,1,0, 0);
|
||||||
return cpu_state.abrt;
|
return cpu_state.abrt;
|
||||||
@@ -111,7 +149,8 @@ static int opPUSHFD(uint32_t fetchdat)
|
|||||||
x86gpf(NULL, 0);
|
x86gpf(NULL, 0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (CPUID) tempw = eflags & 0x24;
|
if (cpu_CR4_mask & CR4_VME) tempw = eflags & 0x3c;
|
||||||
|
else if (CPUID) tempw = eflags & 0x24;
|
||||||
else tempw = eflags & 4;
|
else tempw = eflags & 4;
|
||||||
flags_rebuild();
|
flags_rebuild();
|
||||||
PUSH_L(flags | (tempw << 16));
|
PUSH_L(flags | (tempw << 16));
|
||||||
@@ -151,15 +190,49 @@ static int opPOPF(uint32_t fetchdat)
|
|||||||
|
|
||||||
if ((eflags & VM_FLAG) && (IOPL < 3))
|
if ((eflags & VM_FLAG) && (IOPL < 3))
|
||||||
{
|
{
|
||||||
x86gpf(NULL, 0);
|
if (cr4 & CR4_VME)
|
||||||
|
{
|
||||||
|
uint32_t old_esp = ESP;
|
||||||
|
|
||||||
|
tempw = POP_W();
|
||||||
|
if (cpu_state.abrt)
|
||||||
|
{
|
||||||
|
|
||||||
|
ESP = old_esp;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
tempw = POP_W(); if (cpu_state.abrt) return 1;
|
if ((tempw & T_FLAG) || ((tempw & I_FLAG) && (eflags & VIP_FLAG)))
|
||||||
|
{
|
||||||
|
ESP = old_esp;
|
||||||
|
x86gpf(NULL, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (tempw & I_FLAG)
|
||||||
|
eflags |= VIF_FLAG;
|
||||||
|
else
|
||||||
|
eflags &= ~VIF_FLAG;
|
||||||
|
flags = (flags & 0x3200) | (tempw & 0x4dd5) | 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86gpf(NULL, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tempw = POP_W();
|
||||||
|
if (cpu_state.abrt)
|
||||||
|
return 1;
|
||||||
|
|
||||||
if (!(CPL) || !(msw & 1)) flags = (tempw & 0x7fd5) | 2;
|
if (!(CPL) || !(msw & 1))
|
||||||
else if (IOPLp) flags = (flags & 0x3000) | (tempw & 0x4fd5) | 2;
|
flags = (tempw & 0x7fd5) | 2;
|
||||||
else flags = (flags & 0x3200) | (tempw & 0x4dd5) | 2;
|
else if (IOPLp)
|
||||||
|
flags = (flags & 0x3000) | (tempw & 0x4fd5) | 2;
|
||||||
|
else
|
||||||
|
flags = (flags & 0x3200) | (tempw & 0x4dd5) | 2;
|
||||||
|
}
|
||||||
flags_extract();
|
flags_extract();
|
||||||
|
|
||||||
CLOCK_CYCLES(5);
|
CLOCK_CYCLES(5);
|
||||||
@@ -185,9 +258,10 @@ static int opPOPFD(uint32_t fetchdat)
|
|||||||
else if (IOPLp) flags = (flags & 0x3000) | (templ & 0x4fd5) | 2;
|
else if (IOPLp) flags = (flags & 0x3000) | (templ & 0x4fd5) | 2;
|
||||||
else flags = (flags & 0x3200) | (templ & 0x4dd5) | 2;
|
else flags = (flags & 0x3200) | (templ & 0x4dd5) | 2;
|
||||||
|
|
||||||
templ &= is486 ? 0x240000 : 0;
|
templ &= is486 ? 0x3c0000 : 0;
|
||||||
templ |= ((eflags&3) << 16);
|
templ |= ((eflags&3) << 16);
|
||||||
if (CPUID) eflags = (templ >> 16) & 0x27;
|
if (cpu_CR4_mask & CR4_VME) eflags = (templ >> 16) & 0x3f;
|
||||||
|
else if (CPUID) eflags = (templ >> 16) & 0x27;
|
||||||
else if (is486) eflags = (templ >> 16) & 7;
|
else if (is486) eflags = (templ >> 16) & 7;
|
||||||
else eflags = (templ >> 16) & 3;
|
else eflags = (templ >> 16) & 3;
|
||||||
|
|
||||||
|
|||||||
@@ -29,47 +29,39 @@ static int opINT1(uint32_t fetchdat)
|
|||||||
static int opINT(uint32_t fetchdat)
|
static int opINT(uint32_t fetchdat)
|
||||||
{
|
{
|
||||||
int cycles_old = cycles; UNUSED(cycles_old);
|
int cycles_old = cycles; UNUSED(cycles_old);
|
||||||
uint8_t temp;
|
uint8_t temp = getbytef();
|
||||||
|
|
||||||
/*if (msw&1) pclog("INT %i %i %i\n",cr0&1,eflags&VM_FLAG,IOPL);*/
|
|
||||||
if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3))
|
if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3))
|
||||||
{
|
{
|
||||||
|
if (cr4 & CR4_VME)
|
||||||
|
{
|
||||||
|
uint16_t t;
|
||||||
|
uint8_t d;
|
||||||
|
|
||||||
|
cpl_override = 1;
|
||||||
|
t = readmemw(tr.base, 0x66) - 32;
|
||||||
|
cpl_override = 0;
|
||||||
|
if (cpu_state.abrt) return 1;
|
||||||
|
|
||||||
|
t += (temp >> 3);
|
||||||
|
if (t <= tr.limit)
|
||||||
|
{
|
||||||
|
cpl_override = 1;
|
||||||
|
d = readmemb(tr.base, t);// + (temp >> 3));
|
||||||
|
cpl_override = 0;
|
||||||
|
if (cpu_state.abrt) return 1;
|
||||||
|
|
||||||
|
if (!(d & (1 << (temp & 7))))
|
||||||
|
{
|
||||||
|
x86_int_sw_rm(temp);
|
||||||
|
PREFETCH_RUN(cycles_old-cycles, 2, -1, 0,0,0,0, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
x86gpf(NULL,0);
|
x86gpf(NULL,0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
temp = getbytef();
|
|
||||||
// /*if (temp == 0x10 && AH == 0xe) */pclog("INT %02X : %04X %04X %04X %04X %c %04X:%04X\n", temp, AX, BX, CX, DX, (AL < 32) ? ' ' : AL, CS, pc);
|
|
||||||
// if (CS == 0x0028 && pc == 0xC03813C0)
|
|
||||||
// output = 3;
|
|
||||||
/* if (pc == 0x8028009A)
|
|
||||||
output = 3;
|
|
||||||
if (pc == 0x80282B6F)
|
|
||||||
{
|
|
||||||
__times++;
|
|
||||||
if (__times == 2)
|
|
||||||
fatal("WRONG\n");
|
|
||||||
}
|
|
||||||
if (pc == 0x802809CE)
|
|
||||||
fatal("RIGHT\n");*/
|
|
||||||
// if (CS == 0x0028 && pc == 0x80037FE9)
|
|
||||||
// output = 3;
|
|
||||||
//if (CS == 0x9087 && pc == 0x3763)
|
|
||||||
// fatal("Here\n");
|
|
||||||
//if (CS==0x9087 && pc == 0x0850)
|
|
||||||
// output = 1;
|
|
||||||
|
|
||||||
/* if (output && pc == 0x80033008)
|
|
||||||
{
|
|
||||||
__times++;
|
|
||||||
if (__times == 2)
|
|
||||||
fatal("WRONG\n");
|
|
||||||
}*/
|
|
||||||
/* if (output && pc == 0x80D8)
|
|
||||||
{
|
|
||||||
__times++;
|
|
||||||
if (__times == 2)
|
|
||||||
fatal("RIGHT\n");
|
|
||||||
}*/
|
|
||||||
|
|
||||||
x86_int_sw(temp);
|
x86_int_sw(temp);
|
||||||
PREFETCH_RUN(cycles_old-cycles, 2, -1, 0,0,0,0, 0);
|
PREFETCH_RUN(cycles_old-cycles, 2, -1, 0,0,0,0, 0);
|
||||||
|
|||||||
@@ -140,10 +140,41 @@ static int opIRET(uint32_t fetchdat)
|
|||||||
int cycles_old = cycles; UNUSED(cycles_old);
|
int cycles_old = cycles; UNUSED(cycles_old);
|
||||||
|
|
||||||
if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3))
|
if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3))
|
||||||
|
{
|
||||||
|
if (cr4 & CR4_VME)
|
||||||
|
{
|
||||||
|
uint16_t new_pc, new_cs, new_flags;
|
||||||
|
|
||||||
|
new_pc = readmemw(ss, SP);
|
||||||
|
new_cs = readmemw(ss, ((SP + 2) & 0xffff));
|
||||||
|
new_flags = readmemw(ss, ((SP + 4) & 0xffff));
|
||||||
|
if (cpu_state.abrt)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if ((new_flags & T_FLAG) || ((new_flags & I_FLAG) && (eflags & VIP_FLAG)))
|
||||||
|
{
|
||||||
|
x86gpf(NULL, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
SP += 6;
|
||||||
|
if (new_flags & I_FLAG)
|
||||||
|
eflags |= VIF_FLAG;
|
||||||
|
else
|
||||||
|
eflags &= ~VIF_FLAG;
|
||||||
|
flags = (flags & 0x3300) | (new_flags & 0x4cd5) | 2;
|
||||||
|
loadcs(new_cs);
|
||||||
|
cpu_state.pc = new_pc;
|
||||||
|
|
||||||
|
cycles -= timing_iret_rm;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
x86gpf(NULL,0);
|
x86gpf(NULL,0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (msw&1)
|
if (msw&1)
|
||||||
{
|
{
|
||||||
optype = IRET;
|
optype = IRET;
|
||||||
@@ -171,6 +202,7 @@ static int opIRET(uint32_t fetchdat)
|
|||||||
loadcs(new_cs);
|
loadcs(new_cs);
|
||||||
cycles -= timing_iret_rm;
|
cycles -= timing_iret_rm;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
flags_extract();
|
flags_extract();
|
||||||
nmi_enable = 1;
|
nmi_enable = 1;
|
||||||
CPU_BLOCK_END();
|
CPU_BLOCK_END();
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ DEVOBJ = bugger.o lpt.o serial.o \
|
|||||||
mouse.o mouse_serial.o mouse_ps2.o mouse_bus.o \
|
mouse.o mouse_serial.o mouse_ps2.o mouse_bus.o \
|
||||||
fdd.o fdc.o fdi2raw.o \
|
fdd.o fdc.o fdi2raw.o \
|
||||||
hdd.o hdd_image.o \
|
hdd.o hdd_image.o \
|
||||||
mfm_at.o mfm_xebec.o hdd_esdi.o ide.o xtide.o piix.o \
|
esdi_at.o mfm_at.o mfm_xebec.o hdd_esdi.o ide.o xtide.o piix.o \
|
||||||
disc.o \
|
disc.o \
|
||||||
disc_86f.o disc_fdi.o disc_imd.o disc_img.o \
|
disc_86f.o disc_fdi.o disc_imd.o disc_img.o \
|
||||||
disc_random.o disc_td0.o \
|
disc_random.o disc_td0.o \
|
||||||
|
|||||||
@@ -2538,6 +2538,7 @@ static BOOL CALLBACK win_settings_hard_disks_add_proc(HWND hdlg, UINT message, W
|
|||||||
char *big_buf;
|
char *big_buf;
|
||||||
int b = 0;
|
int b = 0;
|
||||||
uint64_t r = 0;
|
uint64_t r = 0;
|
||||||
|
int j = 0;
|
||||||
|
|
||||||
switch (message)
|
switch (message)
|
||||||
{
|
{
|
||||||
@@ -2852,24 +2853,31 @@ hdd_add_file_open_error:
|
|||||||
fseeko64(f, 0, SEEK_END);
|
fseeko64(f, 0, SEEK_END);
|
||||||
size = ftello64(f);
|
size = ftello64(f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
if (((size % 17) == 0) && (size <= 133693440))
|
if (((size % 17) == 0) && (size <= 142606336))
|
||||||
{
|
{
|
||||||
spt = 17;
|
spt = 17;
|
||||||
if (size <= 26738688)
|
if (size <= 26738688)
|
||||||
{
|
{
|
||||||
hpc = 4;
|
hpc = 4;
|
||||||
}
|
}
|
||||||
else if (size <= 53477376)
|
else if (((size % 3072) == 0) && (size <= 53477376))
|
||||||
{
|
{
|
||||||
hpc = 6;
|
hpc = 6;
|
||||||
}
|
}
|
||||||
else if (size <= 71303168)
|
|
||||||
{
|
|
||||||
hpc = 8;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hpc = 15;
|
for (j = 0; j < 16; j++)
|
||||||
|
{
|
||||||
|
if (((size % (i << 9)) == 0) && (size <= ((i * 17) << 19)))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == 5)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hpc = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
853
src/esdi_at.c
Normal file
853
src/esdi_at.c
Normal file
@@ -0,0 +1,853 @@
|
|||||||
|
#define _LARGEFILE_SOURCE
|
||||||
|
#define _LARGEFILE64_SOURCE
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "ibm.h"
|
||||||
|
#include "device.h"
|
||||||
|
#include "hdd_image.h"
|
||||||
|
#include "io.h"
|
||||||
|
#include "mem.h"
|
||||||
|
#include "pic.h"
|
||||||
|
#include "rom.h"
|
||||||
|
#include "timer.h"
|
||||||
|
|
||||||
|
#include "esdi_at.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define IDE_TIME (TIMER_USEC*10)
|
||||||
|
|
||||||
|
#define STAT_ERR 0x01
|
||||||
|
#define STAT_INDEX 0x02
|
||||||
|
#define STAT_CORRECTED_DATA 0x04
|
||||||
|
#define STAT_DRQ 0x08 /* Data request */
|
||||||
|
#define STAT_DSC 0x10
|
||||||
|
#define STAT_SEEK_COMPLETE 0x20
|
||||||
|
#define STAT_READY 0x40
|
||||||
|
#define STAT_BUSY 0x80
|
||||||
|
|
||||||
|
#define ERR_DAM_NOT_FOUND 0x01 /*Data Address Mark not found*/
|
||||||
|
#define ERR_TR000 0x02 /*Track 0 not found*/
|
||||||
|
#define ERR_ABRT 0x04 /*Command aborted*/
|
||||||
|
#define ERR_ID_NOT_FOUND 0x10 /*ID not found*/
|
||||||
|
#define ERR_DATA_CRC 0x40 /*Data CRC error*/
|
||||||
|
#define ERR_BAD_BLOCK 0x80 /*Bad Block detected*/
|
||||||
|
|
||||||
|
#define CMD_NOP 0x00
|
||||||
|
#define CMD_RESTORE 0x10
|
||||||
|
#define CMD_READ 0x20
|
||||||
|
#define CMD_WRITE 0x30
|
||||||
|
#define CMD_VERIFY 0x40
|
||||||
|
#define CMD_FORMAT 0x50
|
||||||
|
#define CMD_SEEK 0x70
|
||||||
|
#define CMD_DIAGNOSE 0x90
|
||||||
|
#define CMD_SET_PARAMETERS 0x91
|
||||||
|
#define CMD_READ_PARAMETERS 0xec
|
||||||
|
|
||||||
|
extern char ide_fn[4][512];
|
||||||
|
|
||||||
|
typedef struct esdi_drive_t
|
||||||
|
{
|
||||||
|
int cfg_spt;
|
||||||
|
int cfg_hpc;
|
||||||
|
int current_cylinder;
|
||||||
|
int real_spt;
|
||||||
|
int real_hpc;
|
||||||
|
int real_tracks;
|
||||||
|
int present;
|
||||||
|
int hdc_num;
|
||||||
|
} esdi_drive_t;
|
||||||
|
|
||||||
|
typedef struct esdi_t
|
||||||
|
{
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t error;
|
||||||
|
int secount,sector,cylinder,head,cylprecomp;
|
||||||
|
uint8_t command;
|
||||||
|
uint8_t fdisk;
|
||||||
|
int pos;
|
||||||
|
|
||||||
|
int drive_sel;
|
||||||
|
int reset;
|
||||||
|
uint16_t buffer[256];
|
||||||
|
int irqstat;
|
||||||
|
|
||||||
|
int callback;
|
||||||
|
|
||||||
|
esdi_drive_t drives[2];
|
||||||
|
|
||||||
|
rom_t bios_rom;
|
||||||
|
} esdi_t;
|
||||||
|
|
||||||
|
uint16_t esdi_readw(uint16_t port, void *p);
|
||||||
|
void esdi_writew(uint16_t port, uint16_t val, void *p);
|
||||||
|
|
||||||
|
static inline void esdi_irq_raise(esdi_t *esdi)
|
||||||
|
{
|
||||||
|
if (!(esdi->fdisk&2))
|
||||||
|
picint(1 << 14);
|
||||||
|
|
||||||
|
esdi->irqstat=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void esdi_irq_lower(esdi_t *esdi)
|
||||||
|
{
|
||||||
|
picintc(1 << 14);
|
||||||
|
}
|
||||||
|
|
||||||
|
void esdi_irq_update(esdi_t *esdi)
|
||||||
|
{
|
||||||
|
if (esdi->irqstat && !((pic2.pend|pic2.ins)&0x40) && !(esdi->fdisk & 2))
|
||||||
|
picint(1 << 14);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the sector offset for the current register values
|
||||||
|
*/
|
||||||
|
int esdi_get_sector(esdi_t *esdi, off64_t *addr)
|
||||||
|
{
|
||||||
|
esdi_drive_t *drive = &esdi->drives[esdi->drive_sel];
|
||||||
|
int heads = drive->cfg_hpc;
|
||||||
|
int sectors = drive->cfg_spt;
|
||||||
|
|
||||||
|
if (esdi->head > heads)
|
||||||
|
{
|
||||||
|
pclog("esdi_get_sector: past end of configured heads\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (esdi->sector >= sectors+1)
|
||||||
|
{
|
||||||
|
pclog("esdi_get_sector: past end of configured sectors\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drive->cfg_spt == drive->real_spt && drive->cfg_hpc == drive->real_hpc)
|
||||||
|
{
|
||||||
|
*addr = ((((off64_t) esdi->cylinder * heads) + esdi->head) *
|
||||||
|
sectors) + (esdi->sector - 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*When performing translation, the firmware seems to leave 1
|
||||||
|
sector per track inaccessible (spare sector)*/
|
||||||
|
int c, h, s;
|
||||||
|
*addr = ((((off64_t) esdi->cylinder * heads) + esdi->head) *
|
||||||
|
sectors) + (esdi->sector - 1);
|
||||||
|
|
||||||
|
s = *addr % (drive->real_spt - 1);
|
||||||
|
h = (*addr / (drive->real_spt - 1)) % drive->real_hpc;
|
||||||
|
c = (*addr / (drive->real_spt - 1)) / drive->real_hpc;
|
||||||
|
|
||||||
|
*addr = ((((off64_t) c * drive->real_hpc) + h) *
|
||||||
|
drive->real_spt) + s;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move to the next sector using CHS addressing
|
||||||
|
*/
|
||||||
|
void esdi_next_sector(esdi_t *esdi)
|
||||||
|
{
|
||||||
|
esdi_drive_t *drive = &esdi->drives[esdi->drive_sel];
|
||||||
|
|
||||||
|
esdi->sector++;
|
||||||
|
if (esdi->sector == (drive->cfg_spt + 1))
|
||||||
|
{
|
||||||
|
esdi->sector = 1;
|
||||||
|
esdi->head++;
|
||||||
|
if (esdi->head == drive->cfg_hpc)
|
||||||
|
{
|
||||||
|
esdi->head = 0;
|
||||||
|
esdi->cylinder++;
|
||||||
|
if (drive->current_cylinder < drive->real_tracks)
|
||||||
|
drive->current_cylinder++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void esdi_write(uint16_t port, uint8_t val, void *p)
|
||||||
|
{
|
||||||
|
esdi_t *esdi = (esdi_t *)p;
|
||||||
|
|
||||||
|
switch (port)
|
||||||
|
{
|
||||||
|
case 0x1F0: /* Data */
|
||||||
|
esdi_writew(port, val | (val << 8), p);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 0x1F1: /* Write precompenstation */
|
||||||
|
esdi->cylprecomp = val;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 0x1F2: /* Sector count */
|
||||||
|
esdi->secount = val;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 0x1F3: /* Sector */
|
||||||
|
esdi->sector = val;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 0x1F4: /* Cylinder low */
|
||||||
|
esdi->cylinder = (esdi->cylinder & 0xFF00) | val;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 0x1F5: /* Cylinder high */
|
||||||
|
esdi->cylinder = (esdi->cylinder & 0xFF) | (val << 8);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 0x1F6: /* Drive/Head */
|
||||||
|
esdi->head = val & 0xF;
|
||||||
|
esdi->drive_sel = (val & 0x10) ? 1 : 0;
|
||||||
|
if (esdi->drives[esdi->drive_sel].present)
|
||||||
|
esdi->status = 0;
|
||||||
|
else
|
||||||
|
esdi->status = STAT_READY | STAT_DSC;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 0x1F7: /* Command register */
|
||||||
|
esdi_irq_lower(esdi);
|
||||||
|
esdi->command = val;
|
||||||
|
esdi->error = 0;
|
||||||
|
|
||||||
|
switch (val & 0xf0)
|
||||||
|
{
|
||||||
|
case CMD_RESTORE:
|
||||||
|
esdi->command &= ~0x0f; /*Mask off step rate*/
|
||||||
|
esdi->status = STAT_BUSY;
|
||||||
|
timer_process();
|
||||||
|
esdi->callback = 200*IDE_TIME;
|
||||||
|
timer_update_outstanding();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_SEEK:
|
||||||
|
esdi->command &= ~0x0f; /*Mask off step rate*/
|
||||||
|
esdi->status = STAT_BUSY;
|
||||||
|
timer_process();
|
||||||
|
esdi->callback = 200*IDE_TIME;
|
||||||
|
timer_update_outstanding();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
switch (val)
|
||||||
|
{
|
||||||
|
case CMD_NOP:
|
||||||
|
esdi->status = STAT_BUSY;
|
||||||
|
timer_process();
|
||||||
|
esdi->callback = 200*IDE_TIME;
|
||||||
|
timer_update_outstanding();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_READ: case CMD_READ+1:
|
||||||
|
case CMD_READ+2: case CMD_READ+3:
|
||||||
|
esdi->command &= ~3;
|
||||||
|
if (val & 2)
|
||||||
|
fatal("Read with ECC\n");
|
||||||
|
case 0xa0:
|
||||||
|
esdi->status = STAT_BUSY;
|
||||||
|
timer_process();
|
||||||
|
esdi->callback = 200*IDE_TIME;
|
||||||
|
timer_update_outstanding();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_WRITE: case CMD_WRITE+1:
|
||||||
|
case CMD_WRITE+2: case CMD_WRITE+3:
|
||||||
|
esdi->command &= ~3;
|
||||||
|
if (val & 2)
|
||||||
|
fatal("Write with ECC\n");
|
||||||
|
esdi->status = STAT_DRQ | STAT_DSC;
|
||||||
|
esdi->pos=0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_VERIFY: case CMD_VERIFY+1:
|
||||||
|
esdi->command &= ~1;
|
||||||
|
esdi->status = STAT_BUSY;
|
||||||
|
timer_process();
|
||||||
|
esdi->callback = 200 * IDE_TIME;
|
||||||
|
timer_update_outstanding();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_FORMAT:
|
||||||
|
esdi->status = STAT_DRQ;
|
||||||
|
esdi->pos=0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */
|
||||||
|
esdi->status = STAT_BUSY;
|
||||||
|
timer_process();
|
||||||
|
esdi->callback = 30*IDE_TIME;
|
||||||
|
timer_update_outstanding();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_DIAGNOSE: /* Execute Drive Diagnostics */
|
||||||
|
esdi->status = STAT_BUSY;
|
||||||
|
timer_process();
|
||||||
|
esdi->callback = 200*IDE_TIME;
|
||||||
|
timer_update_outstanding();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xe0: /*???*/
|
||||||
|
case CMD_READ_PARAMETERS:
|
||||||
|
esdi->status = STAT_BUSY;
|
||||||
|
timer_process();
|
||||||
|
esdi->callback = 200*IDE_TIME;
|
||||||
|
timer_update_outstanding();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
pclog("Bad esdi command %02X\n", val);
|
||||||
|
case 0xe8: /*???*/
|
||||||
|
esdi->status = STAT_BUSY;
|
||||||
|
timer_process();
|
||||||
|
esdi->callback = 200*IDE_TIME;
|
||||||
|
timer_update_outstanding();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x3F6: /* Device control */
|
||||||
|
if ((esdi->fdisk & 4) && !(val & 4))
|
||||||
|
{
|
||||||
|
timer_process();
|
||||||
|
esdi->callback = 500*IDE_TIME;
|
||||||
|
timer_update_outstanding();
|
||||||
|
esdi->reset = 1;
|
||||||
|
esdi->status = STAT_BUSY;
|
||||||
|
}
|
||||||
|
if (val & 4)
|
||||||
|
{
|
||||||
|
/*Drive held in reset*/
|
||||||
|
timer_process();
|
||||||
|
esdi->callback = 0;
|
||||||
|
timer_update_outstanding();
|
||||||
|
esdi->status = STAT_BUSY;
|
||||||
|
}
|
||||||
|
esdi->fdisk = val;
|
||||||
|
esdi_irq_update(esdi);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void esdi_writew(uint16_t port, uint16_t val, void *p)
|
||||||
|
{
|
||||||
|
esdi_t *esdi = (esdi_t *)p;
|
||||||
|
|
||||||
|
esdi->buffer[esdi->pos >> 1] = val;
|
||||||
|
esdi->pos += 2;
|
||||||
|
|
||||||
|
if (esdi->pos >= 512)
|
||||||
|
{
|
||||||
|
esdi->pos = 0;
|
||||||
|
esdi->status = STAT_BUSY;
|
||||||
|
timer_process();
|
||||||
|
esdi->callback = 6*IDE_TIME;
|
||||||
|
timer_update_outstanding();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t esdi_read(uint16_t port, void *p)
|
||||||
|
{
|
||||||
|
esdi_t *esdi = (esdi_t *)p;
|
||||||
|
uint8_t temp = 0xff;
|
||||||
|
|
||||||
|
switch (port)
|
||||||
|
{
|
||||||
|
case 0x1F0: /* Data */
|
||||||
|
temp = esdi_readw(port, esdi) & 0xff;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x1F1: /* Error */
|
||||||
|
temp = esdi->error;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x1F2: /* Sector count */
|
||||||
|
temp = (uint8_t)esdi->secount;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x1F3: /* Sector */
|
||||||
|
temp = (uint8_t)esdi->sector;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x1F4: /* Cylinder low */
|
||||||
|
temp = (uint8_t)(esdi->cylinder&0xFF);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x1F5: /* Cylinder high */
|
||||||
|
temp = (uint8_t)(esdi->cylinder>>8);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x1F6: /* Drive/Head */
|
||||||
|
temp = (uint8_t)(esdi->head | (esdi->drive_sel ? 0x10 : 0) | 0xa0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x1F7: /* Status */
|
||||||
|
esdi_irq_lower(esdi);
|
||||||
|
temp = esdi->status;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t esdi_readw(uint16_t port, void *p)
|
||||||
|
{
|
||||||
|
esdi_t *esdi = (esdi_t *)p;
|
||||||
|
uint16_t temp;
|
||||||
|
|
||||||
|
temp = esdi->buffer[esdi->pos >> 1];
|
||||||
|
esdi->pos += 2;
|
||||||
|
|
||||||
|
if (esdi->pos >= 512)
|
||||||
|
{
|
||||||
|
esdi->pos=0;
|
||||||
|
esdi->status = STAT_READY | STAT_DSC;
|
||||||
|
if (esdi->command == CMD_READ || esdi->command == 0xa0)
|
||||||
|
{
|
||||||
|
esdi->secount = (esdi->secount - 1) & 0xff;
|
||||||
|
if (esdi->secount)
|
||||||
|
{
|
||||||
|
esdi_next_sector(esdi);
|
||||||
|
esdi->status = STAT_BUSY;
|
||||||
|
timer_process();
|
||||||
|
esdi->callback = 6*IDE_TIME;
|
||||||
|
timer_update_outstanding();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void esdi_callback(void *p)
|
||||||
|
{
|
||||||
|
esdi_t *esdi = (esdi_t *)p;
|
||||||
|
esdi_drive_t *drive = &esdi->drives[esdi->drive_sel];
|
||||||
|
off64_t addr;
|
||||||
|
|
||||||
|
esdi->callback = 0;
|
||||||
|
if (esdi->reset)
|
||||||
|
{
|
||||||
|
esdi->status = STAT_READY | STAT_DSC;
|
||||||
|
esdi->error = 1;
|
||||||
|
esdi->secount = 1;
|
||||||
|
esdi->sector = 1;
|
||||||
|
esdi->head = 0;
|
||||||
|
esdi->cylinder = 0;
|
||||||
|
esdi->reset = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (esdi->command)
|
||||||
|
{
|
||||||
|
case CMD_RESTORE:
|
||||||
|
if (!drive->present)
|
||||||
|
{
|
||||||
|
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
|
||||||
|
esdi->error = ERR_ABRT;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
drive->current_cylinder = 0;
|
||||||
|
esdi->status = STAT_READY | STAT_DSC;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_SEEK:
|
||||||
|
if (!drive->present)
|
||||||
|
{
|
||||||
|
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
|
||||||
|
esdi->error = ERR_ABRT;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
esdi->status = STAT_READY | STAT_DSC;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_READ:
|
||||||
|
if (!drive->present)
|
||||||
|
{
|
||||||
|
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
|
||||||
|
esdi->error = ERR_ABRT;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (esdi_get_sector(esdi, &addr))
|
||||||
|
{
|
||||||
|
esdi->error = ERR_ID_NOT_FOUND;
|
||||||
|
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (hdd_image_read_ex(drive->hdc_num, addr, 1, (uint8_t *) esdi->buffer))
|
||||||
|
{
|
||||||
|
esdi->error = ERR_ID_NOT_FOUND;
|
||||||
|
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
esdi->pos = 0;
|
||||||
|
esdi->status = STAT_DRQ | STAT_READY | STAT_DSC;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
update_status_bar_icon(SB_HDD | HDD_BUS_RLL, 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_WRITE:
|
||||||
|
if (!drive->present)
|
||||||
|
{
|
||||||
|
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
|
||||||
|
esdi->error = ERR_ABRT;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (esdi_get_sector(esdi, &addr))
|
||||||
|
{
|
||||||
|
esdi->error = ERR_ID_NOT_FOUND;
|
||||||
|
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (hdd_image_write_ex(drive->hdc_num, addr, 1, (uint8_t *) esdi->buffer))
|
||||||
|
{
|
||||||
|
esdi->error = ERR_ID_NOT_FOUND;
|
||||||
|
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
esdi->secount = (esdi->secount - 1) & 0xff;
|
||||||
|
if (esdi->secount)
|
||||||
|
{
|
||||||
|
esdi->status = STAT_DRQ | STAT_READY | STAT_DSC;
|
||||||
|
esdi->pos = 0;
|
||||||
|
esdi_next_sector(esdi);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
esdi->status = STAT_READY | STAT_DSC;
|
||||||
|
update_status_bar_icon(SB_HDD | HDD_BUS_RLL, 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_VERIFY:
|
||||||
|
if (!drive->present)
|
||||||
|
{
|
||||||
|
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
|
||||||
|
esdi->error = ERR_ABRT;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (esdi_get_sector(esdi, &addr))
|
||||||
|
{
|
||||||
|
esdi->error = ERR_ID_NOT_FOUND;
|
||||||
|
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (hdd_image_read_ex(drive->hdc_num, addr, 1, (uint8_t *) esdi->buffer))
|
||||||
|
{
|
||||||
|
esdi->error = ERR_ID_NOT_FOUND;
|
||||||
|
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
update_status_bar_icon(SB_HDD | HDD_BUS_RLL, 1);
|
||||||
|
esdi_next_sector(esdi);
|
||||||
|
esdi->secount = (esdi->secount - 1) & 0xff;
|
||||||
|
if (esdi->secount)
|
||||||
|
esdi->callback = 6*IDE_TIME;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
esdi->pos = 0;
|
||||||
|
esdi->status = STAT_READY | STAT_DSC;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_FORMAT:
|
||||||
|
if (!drive->present)
|
||||||
|
{
|
||||||
|
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
|
||||||
|
esdi->error = ERR_ABRT;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (esdi_get_sector(esdi, &addr))
|
||||||
|
{
|
||||||
|
esdi->error = ERR_ID_NOT_FOUND;
|
||||||
|
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (hdd_image_zero_ex(drive->hdc_num, addr, esdi->secount))
|
||||||
|
{
|
||||||
|
esdi->error = ERR_ID_NOT_FOUND;
|
||||||
|
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
esdi->status = STAT_READY | STAT_DSC;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
update_status_bar_icon(SB_HDD | HDD_BUS_RLL, 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_DIAGNOSE:
|
||||||
|
if (!drive->present)
|
||||||
|
{
|
||||||
|
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
|
||||||
|
esdi->error = ERR_ABRT;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
esdi->error = 1; /*No error detected*/
|
||||||
|
esdi->status = STAT_READY | STAT_DSC;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */
|
||||||
|
if (!drive->present)
|
||||||
|
{
|
||||||
|
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
|
||||||
|
esdi->error = ERR_ABRT;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
drive->cfg_spt = esdi->secount;
|
||||||
|
drive->cfg_hpc = esdi->head+1;
|
||||||
|
pclog("Parameters: spt=%i hpc=%i\n", drive->cfg_spt,drive->cfg_hpc);
|
||||||
|
if (!esdi->secount)
|
||||||
|
fatal("secount=0\n");
|
||||||
|
esdi->status = STAT_READY | STAT_DSC;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_NOP:
|
||||||
|
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
|
||||||
|
esdi->error = ERR_ABRT;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xe0:
|
||||||
|
if (!drive->present)
|
||||||
|
{
|
||||||
|
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
|
||||||
|
esdi->error = ERR_ABRT;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (esdi->cylinder >> 8)
|
||||||
|
{
|
||||||
|
case 0x31:
|
||||||
|
esdi->cylinder = drive->real_tracks;
|
||||||
|
break;
|
||||||
|
case 0x33:
|
||||||
|
esdi->cylinder = drive->real_hpc;
|
||||||
|
break;
|
||||||
|
case 0x35:
|
||||||
|
esdi->cylinder = 0x200;
|
||||||
|
break;
|
||||||
|
case 0x36:
|
||||||
|
esdi->cylinder = drive->real_spt;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pclog("EDSI Bad read config %02x\n", esdi->cylinder >> 8);
|
||||||
|
}
|
||||||
|
esdi->status = STAT_READY | STAT_DSC;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xa0:
|
||||||
|
if (!drive->present)
|
||||||
|
{
|
||||||
|
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
|
||||||
|
esdi->error = ERR_ABRT;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset(esdi->buffer, 0, 512);
|
||||||
|
memset(&esdi->buffer[3], 0xff, 512-6);
|
||||||
|
esdi->pos = 0;
|
||||||
|
esdi->status = STAT_DRQ | STAT_READY | STAT_DSC;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_READ_PARAMETERS:
|
||||||
|
if (!drive->present)
|
||||||
|
{
|
||||||
|
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
|
||||||
|
esdi->error = ERR_ABRT;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset(esdi->buffer, 0, 512);
|
||||||
|
|
||||||
|
esdi->buffer[0] = 0x44; /* general configuration */
|
||||||
|
esdi->buffer[1] = drive->real_tracks; /* number of non-removable cylinders */
|
||||||
|
esdi->buffer[2] = 0; /* number of removable cylinders */
|
||||||
|
esdi->buffer[3] = drive->real_hpc; /* number of heads */
|
||||||
|
esdi->buffer[5] = esdi->buffer[4] * drive->real_spt; /* number of unformatted bytes/sector */
|
||||||
|
esdi->buffer[4] = 600; /* number of unformatted bytes/track */
|
||||||
|
esdi->buffer[6] = drive->real_spt; /* number of sectors */
|
||||||
|
esdi->buffer[7] = 0; /*minimum bytes in inter-sector gap*/
|
||||||
|
esdi->buffer[8] = 0; /* minimum bytes in postamble */
|
||||||
|
esdi->buffer[9] = 0; /* number of words of vendor status */
|
||||||
|
/* controller info */
|
||||||
|
esdi->buffer[20] = 2; /* controller type */
|
||||||
|
esdi->buffer[21] = 1; /* sector buffer size, in sectors */
|
||||||
|
esdi->buffer[22] = 0; /* ecc bytes appended */
|
||||||
|
esdi->buffer[27] = 'W' | ('D' << 8);
|
||||||
|
esdi->buffer[28] = '1' | ('0' << 8);
|
||||||
|
esdi->buffer[29] = '0' | ('7' << 8);
|
||||||
|
esdi->buffer[30] = 'V' | ('-' << 8);
|
||||||
|
esdi->buffer[31] = 'S' | ('E' << 8);
|
||||||
|
esdi->buffer[32] = '1';
|
||||||
|
esdi->buffer[47] = 0; /* sectors per interrupt */
|
||||||
|
esdi->buffer[48] = 0;/* can use double word read/write? */
|
||||||
|
esdi->pos = 0;
|
||||||
|
esdi->status = STAT_DRQ | STAT_READY | STAT_DSC;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
pclog("ESDI Callback on unknown command %02x\n", esdi->command);
|
||||||
|
case 0xe8:
|
||||||
|
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
|
||||||
|
esdi->error = ERR_ABRT;
|
||||||
|
esdi_irq_raise(esdi);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
update_status_bar_icon(SB_HDD | HDD_BUS_RLL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void esdi_rom_write(uint32_t addr, uint8_t val, void *p)
|
||||||
|
{
|
||||||
|
rom_t *rom = (rom_t *)p;
|
||||||
|
|
||||||
|
addr &= rom->mask;
|
||||||
|
|
||||||
|
if (addr >= 0x1f00 && addr < 0x2000)
|
||||||
|
rom->rom[addr] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void loadhd(esdi_t *esdi, int hdc_num, int d, const wchar_t *fn)
|
||||||
|
{
|
||||||
|
esdi_drive_t *drive = &esdi->drives[d];
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = hdd_image_load(hdc_num);
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
drive->present = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
drive->cfg_spt = drive->real_spt = hdc[hdc_num].spt;
|
||||||
|
drive->cfg_hpc = drive->real_hpc = hdc[hdc_num].hpc;
|
||||||
|
drive->real_tracks = hdc[hdc_num].tracks;
|
||||||
|
drive->hdc_num = hdc_num;
|
||||||
|
drive->present = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *wd1007vse1_init()
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int c = 0;
|
||||||
|
|
||||||
|
esdi_t *esdi = malloc(sizeof(esdi_t));
|
||||||
|
memset(esdi, 0, sizeof(esdi_t));
|
||||||
|
|
||||||
|
esdi->drives[0].present = esdi->drives[1].present = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < HDC_NUM; i++)
|
||||||
|
{
|
||||||
|
if ((hdc[i].bus == HDD_BUS_RLL) && (hdc[i].rll_channel < RLL_NUM))
|
||||||
|
{
|
||||||
|
loadhd(esdi, i, hdc[i].rll_channel, hdc[i].fn);
|
||||||
|
c++;
|
||||||
|
if (c >= RLL_NUM) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
esdi->status = STAT_READY | STAT_DSC;
|
||||||
|
esdi->error = 1; /*No errors*/
|
||||||
|
|
||||||
|
rom_init(&esdi->bios_rom, L"roms/62-000279-061.bin", 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
|
||||||
|
|
||||||
|
mem_mapping_set_handler(&esdi->bios_rom.mapping,
|
||||||
|
rom_read, rom_readw, rom_readl,
|
||||||
|
esdi_rom_write, NULL, NULL);
|
||||||
|
|
||||||
|
io_sethandler(0x01f0, 0x0001, esdi_read, esdi_readw, NULL, esdi_write, esdi_writew, NULL, esdi);
|
||||||
|
io_sethandler(0x01f1, 0x0007, esdi_read, NULL, NULL, esdi_write, NULL, NULL, esdi);
|
||||||
|
io_sethandler(0x03f6, 0x0001, NULL, NULL, NULL, esdi_write, NULL, NULL, esdi);
|
||||||
|
|
||||||
|
timer_add(esdi_callback, &esdi->callback, &esdi->callback, esdi);
|
||||||
|
|
||||||
|
return esdi;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wd1007vse1_close(void *p)
|
||||||
|
{
|
||||||
|
esdi_t *esdi = (esdi_t *)p;
|
||||||
|
esdi_drive_t *drive;
|
||||||
|
|
||||||
|
int d;
|
||||||
|
|
||||||
|
esdi->drives[0].present = esdi->drives[1].present = 0;
|
||||||
|
|
||||||
|
for (d = 0; d < 2; d++)
|
||||||
|
{
|
||||||
|
drive = &esdi->drives[d];
|
||||||
|
|
||||||
|
hdd_image_close(drive->hdc_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(esdi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wd1007vse1_available()
|
||||||
|
{
|
||||||
|
return rom_present(L"roms/62-000279-061.bin");
|
||||||
|
}
|
||||||
|
|
||||||
|
device_t wd1007vse1_device =
|
||||||
|
{
|
||||||
|
"Western Digital WD1007V-SE1 (ESDI)",
|
||||||
|
DEVICE_AT,
|
||||||
|
wd1007vse1_init,
|
||||||
|
wd1007vse1_close,
|
||||||
|
wd1007vse1_available,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
1
src/esdi_at.h
Normal file
1
src/esdi_at.h
Normal file
@@ -0,0 +1 @@
|
|||||||
|
extern device_t wd1007vse1_device;
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "hdd.h"
|
#include "hdd.h"
|
||||||
#include "model.h"
|
#include "model.h"
|
||||||
|
|
||||||
|
#include "esdi_at.h"
|
||||||
#include "hdd_esdi.h"
|
#include "hdd_esdi.h"
|
||||||
#include "mfm_at.h"
|
#include "mfm_at.h"
|
||||||
#include "mfm_xebec.h"
|
#include "mfm_xebec.h"
|
||||||
@@ -30,6 +31,7 @@ static struct
|
|||||||
{"DTC 5150X", "dtc5150x", &dtc_5150x_device, 1},
|
{"DTC 5150X", "dtc5150x", &dtc_5150x_device, 1},
|
||||||
{"Fixed Disk Adapter (Xebec)", "mfm_xebec", &mfm_xebec_device, 1},
|
{"Fixed Disk Adapter (Xebec)", "mfm_xebec", &mfm_xebec_device, 1},
|
||||||
{"IBM ESDI Fixed Disk Adapter (MCA)", "esdi_mca", &hdd_esdi_device, 1},
|
{"IBM ESDI Fixed Disk Adapter (MCA)", "esdi_mca", &hdd_esdi_device, 1},
|
||||||
|
{"Western Digital WD1007V-SE1 (ESDI)","wd1007vse1", &wd1007vse1_device, 0},
|
||||||
{"XTIDE", "xtide", &xtide_device, 0},
|
{"XTIDE", "xtide", &xtide_device, 0},
|
||||||
{"XTIDE (AT)", "xtide_at", &xtide_at_device, 0},
|
{"XTIDE (AT)", "xtide_at", &xtide_at_device, 0},
|
||||||
{"XTIDE (PS/2)", "xtide_ps2",&xtide_ps2_device,0},
|
{"XTIDE (PS/2)", "xtide_ps2",&xtide_ps2_device,0},
|
||||||
|
|||||||
@@ -819,6 +819,8 @@ static void *esdi_init()
|
|||||||
rom_init_interleaved(&esdi->bios_rom, L"roms/90x8970.bin", L"roms/90x8969.bin", 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
|
rom_init_interleaved(&esdi->bios_rom, L"roms/90x8970.bin", L"roms/90x8969.bin", 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
|
||||||
mem_mapping_disable(&esdi->bios_rom.mapping);
|
mem_mapping_disable(&esdi->bios_rom.mapping);
|
||||||
|
|
||||||
|
esdi->drives[0].present = esdi->drives[1].present = 0;
|
||||||
|
|
||||||
for (i = 0; i < HDC_NUM; i++)
|
for (i = 0; i < HDC_NUM; i++)
|
||||||
{
|
{
|
||||||
if ((hdc[i].bus == HDD_BUS_RLL) && (hdc[i].rll_channel < RLL_NUM))
|
if ((hdc[i].bus == HDD_BUS_RLL) && (hdc[i].rll_channel < RLL_NUM))
|
||||||
@@ -846,11 +848,15 @@ static void *esdi_init()
|
|||||||
static void esdi_close(void *p)
|
static void esdi_close(void *p)
|
||||||
{
|
{
|
||||||
esdi_t *esdi = (esdi_t *)p;
|
esdi_t *esdi = (esdi_t *)p;
|
||||||
|
esdi_drive_t *drive;
|
||||||
|
|
||||||
int d;
|
int d;
|
||||||
|
|
||||||
|
esdi->drives[0].present = esdi->drives[1].present = 0;
|
||||||
|
|
||||||
for (d = 0; d < 2; d++)
|
for (d = 0; d < 2; d++)
|
||||||
{
|
{
|
||||||
esdi_drive_t *drive = &esdi->drives[d];
|
drive = &esdi->drives[d];
|
||||||
|
|
||||||
hdd_image_close(drive->hdc_num);
|
hdd_image_close(drive->hdc_num);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -361,6 +361,33 @@ void hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer
|
|||||||
fread(buffer, 1, count, hdd_images[id].file);
|
fread(buffer, 1, count, hdd_images[id].file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t hdd_sectors(uint8_t id)
|
||||||
|
{
|
||||||
|
fseeko64(hdd_images[id].file, 0, SEEK_END);
|
||||||
|
return (uint32_t) (ftello64(hdd_images[id].file) >> 9);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hdd_image_read_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
|
||||||
|
{
|
||||||
|
uint32_t transfer_sectors = count;
|
||||||
|
uint32_t sectors = hdd_sectors(id);
|
||||||
|
|
||||||
|
if ((sectors - sector) < transfer_sectors)
|
||||||
|
{
|
||||||
|
transfer_sectors = sectors - sector;
|
||||||
|
}
|
||||||
|
|
||||||
|
hdd_image_seek(id, sector);
|
||||||
|
memset(buffer, 0, transfer_sectors << 9);
|
||||||
|
fread(buffer, 1, transfer_sectors << 9, hdd_images[id].file);
|
||||||
|
|
||||||
|
if (count != transfer_sectors)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
|
void hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
|
||||||
{
|
{
|
||||||
count <<= 9;
|
count <<= 9;
|
||||||
@@ -369,6 +396,27 @@ void hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffe
|
|||||||
fwrite(buffer, 1, count, hdd_images[id].file);
|
fwrite(buffer, 1, count, hdd_images[id].file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int hdd_image_write_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
|
||||||
|
{
|
||||||
|
uint32_t transfer_sectors = count;
|
||||||
|
uint32_t sectors = hdd_sectors(id);
|
||||||
|
|
||||||
|
if ((sectors - sector) < transfer_sectors)
|
||||||
|
{
|
||||||
|
transfer_sectors = sectors - sector;
|
||||||
|
}
|
||||||
|
|
||||||
|
hdd_image_seek(id, sector);
|
||||||
|
memset(buffer, 0, transfer_sectors << 9);
|
||||||
|
fwrite(buffer, 1, transfer_sectors << 9, hdd_images[id].file);
|
||||||
|
|
||||||
|
if (count != transfer_sectors)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count)
|
void hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@@ -386,6 +434,35 @@ void hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count)
|
|||||||
free(b);
|
free(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int hdd_image_zero_ex(uint8_t id, uint32_t sector, uint32_t count)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
uint8_t *b;
|
||||||
|
|
||||||
|
uint32_t transfer_sectors = count;
|
||||||
|
uint32_t sectors = hdd_sectors(id);
|
||||||
|
|
||||||
|
if ((sectors - sector) < transfer_sectors)
|
||||||
|
{
|
||||||
|
transfer_sectors = sectors - sector;
|
||||||
|
}
|
||||||
|
|
||||||
|
b = (uint8_t *) malloc(512);
|
||||||
|
memset(b, 0, 512);
|
||||||
|
|
||||||
|
hdd_image_seek(id, sector);
|
||||||
|
for (i = 0; i < transfer_sectors; i++)
|
||||||
|
{
|
||||||
|
fwrite(b, 1, 512, hdd_images[id].file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count != transfer_sectors)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t hdd_image_get_last_sector(uint8_t id)
|
uint32_t hdd_image_get_last_sector(uint8_t id)
|
||||||
{
|
{
|
||||||
return hdd_images[id].last_sector;
|
return hdd_images[id].last_sector;
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
extern int hdd_image_load(int id);
|
extern int hdd_image_load(int id);
|
||||||
extern void hdd_image_seek(uint8_t id, uint32_t sector);
|
extern void hdd_image_seek(uint8_t id, uint32_t sector);
|
||||||
extern void hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer);
|
extern void hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer);
|
||||||
|
extern int hdd_image_read_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer);
|
||||||
extern void hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer);
|
extern void hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer);
|
||||||
|
extern int hdd_image_write_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer);
|
||||||
extern void hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count);
|
extern void hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count);
|
||||||
|
extern int hdd_image_zero_ex(uint8_t id, uint32_t sector, uint32_t count);
|
||||||
extern uint32_t hdd_image_get_last_sector(uint8_t id);
|
extern uint32_t hdd_image_get_last_sector(uint8_t id);
|
||||||
extern uint8_t hdd_image_get_type(uint8_t id);
|
extern uint8_t hdd_image_get_type(uint8_t id);
|
||||||
extern void hdd_image_specify(uint8_t id, uint64_t hpc, uint64_t spt);
|
extern void hdd_image_specify(uint8_t id, uint64_t hpc, uint64_t spt);
|
||||||
|
|||||||
@@ -256,9 +256,14 @@ extern uint32_t dr[8];
|
|||||||
#define V_FLAG 0x0800
|
#define V_FLAG 0x0800
|
||||||
#define NT_FLAG 0x4000
|
#define NT_FLAG 0x4000
|
||||||
#define VM_FLAG 0x0002 /*In EFLAGS*/
|
#define VM_FLAG 0x0002 /*In EFLAGS*/
|
||||||
|
#define VIF_FLAG 0x0008 /*In EFLAGS*/
|
||||||
|
#define VIP_FLAG 0x0010 /*In EFLAGS*/
|
||||||
|
|
||||||
#define WP_FLAG 0x10000 /*In CR0*/
|
#define WP_FLAG 0x10000 /*In CR0*/
|
||||||
|
|
||||||
|
#define CR4_VME (1 << 0)
|
||||||
|
#define CR4_PVI (1 << 1)
|
||||||
|
|
||||||
#define IOPL ((flags>>12)&3)
|
#define IOPL ((flags>>12)&3)
|
||||||
|
|
||||||
#define IOPLp ((!(msw&1)) || (CPL<=IOPL))
|
#define IOPLp ((!(msw&1)) || (CPL<=IOPL))
|
||||||
@@ -775,6 +780,7 @@ extern void softresetx86(void);
|
|||||||
extern void speedchanged(void);
|
extern void speedchanged(void);
|
||||||
extern void trc_reset(uint8_t val);
|
extern void trc_reset(uint8_t val);
|
||||||
extern void x86_int_sw(int num);
|
extern void x86_int_sw(int num);
|
||||||
|
extern int x86_int_sw_rm(int num);
|
||||||
extern void x86gpf(char *s, uint16_t error);
|
extern void x86gpf(char *s, uint16_t error);
|
||||||
extern void x86np(char *s, uint16_t error);
|
extern void x86np(char *s, uint16_t error);
|
||||||
extern void x86ss(char *s, uint16_t error);
|
extern void x86ss(char *s, uint16_t error);
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ int rom_present(wchar_t *fn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t rom_read(uint32_t addr, void *p)
|
uint8_t rom_read(uint32_t addr, void *p)
|
||||||
{
|
{
|
||||||
rom_t *rom = (rom_t *)p;
|
rom_t *rom = (rom_t *)p;
|
||||||
#ifdef ROM_TRACE
|
#ifdef ROM_TRACE
|
||||||
|
|||||||
@@ -15,3 +15,7 @@ typedef struct rom_t
|
|||||||
|
|
||||||
int rom_init(rom_t *rom, wchar_t *fn, uint32_t address, int size, int mask, int file_offset, uint32_t flags);
|
int rom_init(rom_t *rom, wchar_t *fn, uint32_t address, int size, int mask, int file_offset, uint32_t flags);
|
||||||
int rom_init_interleaved(rom_t *rom, wchar_t *fn_low, wchar_t *fn_high, uint32_t address, int size, int mask, int file_offset, uint32_t flags);
|
int rom_init_interleaved(rom_t *rom, wchar_t *fn_low, wchar_t *fn_high, uint32_t address, int size, int mask, int file_offset, uint32_t flags);
|
||||||
|
|
||||||
|
uint8_t rom_read(uint32_t addr, void *p);
|
||||||
|
uint16_t rom_readw(uint32_t addr, void *p);
|
||||||
|
uint32_t rom_readl(uint32_t addr, void *p);
|
||||||
|
|||||||
Reference in New Issue
Block a user