| 924 | //----------------------------------------------------------------------------- |
| 925 | |
| 926 | BYTE __stdcall HarddiskInterfaceCard::IOWrite(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles) |
| 927 | { |
| 928 | const UINT slot = ((addr & 0xff) >> 4) - 8; |
| 929 | HarddiskInterfaceCard* pCard = (HarddiskInterfaceCard*)MemGetSlotParameters(slot); |
| 930 | |
| 931 | HardDiskDrive* pHDD = NULL; |
| 932 | BYTE addrIdx = addr & 0xF; |
| 933 | if (addrIdx != 0x2 && addrIdx != 0x3 // GetUnit() depends on m_command & m_unitNum |
| 934 | && !((addrIdx == 0x9 || addrIdx == 0xA) && pCard->m_fifoIdx < 2)) |
| 935 | { |
| 936 | pHDD = pCard->GetUnit(); |
| 937 | if (pHDD == NULL) |
| 938 | { |
| 939 | // Ensure that fifoIdx returns to 0, even if unitNum is out of range |
| 940 | // EG. ProDOS 8 v2.5.0: Bitsy Bye: TAB through S7 volumes |
| 941 | const UINT fifoSize = (addrIdx == 0x9) ? 6 : 7; |
| 942 | pCard->m_fifoIdx = (pCard->m_fifoIdx + 1) % fifoSize; |
| 943 | return SET_STATUS_ERROR(DEVICE_NOT_CONNECTED); |
| 944 | } |
| 945 | } |
| 946 | |
| 947 | if (addrIdx == 0x9 || addrIdx == 0xA) // BLK or SP cmd FIFO |
| 948 | { |
| 949 | if (addrIdx == 0xA && pCard->m_fifoIdx == 0) |
| 950 | d |= SP_Cmd_base; |
| 951 | |
| 952 | const UINT fifoSize = (addrIdx == 0x9) ? 6 : 7; |
| 953 | addrIdx = 0x2 + pCard->m_fifoIdx; |
| 954 | pCard->m_fifoIdx = (pCard->m_fifoIdx + 1) % fifoSize; |
| 955 | } |
| 956 | |
| 957 | switch (addrIdx) |
| 958 | { |
| 959 | case 0x0: // r/o: status |
| 960 | case 0x1: // r/o: execute |
| 961 | // Writing to these read-only registers is a no-op. |
| 962 | // NB. Don't change m_status_next, as UpdateLightStatus() has a huge performance cost! |
| 963 | // Some HDC's firmware has a busy-wait loop doing "rol hd_status,x" |
| 964 | // - this RMW opcode does an IORead() then an IOWrite(), and the loop iterates ~100 times! |
| 965 | break; |
| 966 | case 0x2: |
| 967 | pCard->m_command = d; |
| 968 | break; |
| 969 | case 0x3: |
| 970 | // b7 = drive# |
| 971 | // b6..4 = slot# |
| 972 | // b3..0 = ? |
| 973 | pCard->m_unitNum = d; |
| 974 | pCard->FixupUnitNum(); |
| 975 | break; |
| 976 | case 0x4: |
| 977 | pHDD->m_memblock = (pHDD->m_memblock & 0xFF00) | d; |
| 978 | break; |
| 979 | case 0x5: |
| 980 | pHDD->m_memblock = (pHDD->m_memblock & 0x00FF) | (d << 8); |
| 981 | break; |
| 982 | case 0x6: |
| 983 | if (pCard->m_command != SP_Cmd_status) |
nothing calls this directly
no test coverage detected