branches/alto2/src/emu/cpu/alto2/a2disk.c
| r26171 | r26172 | |
| 911 | 911 | * @brief monoflop 31a pulse duration |
| 912 | 912 | * Rt = 15k, Cext = .47µF (=470000pF) => 2066120ns (~2ms) |
| 913 | 913 | */ |
| 914 | | #define TW_READY attotime::from_nsec(2066120) |
| 914 | #define TW_READY 2066120 |
| 915 | 915 | |
| 916 | 916 | /** |
| 917 | 917 | * @brief monoflop 31b pulse duration |
| r26171 | r26172 | |
| 1460 | 1460 | // check if write and erase gate, or read gate are changed |
| 1461 | 1461 | if ((m_task_wakeup & (1 << task_ksec)) || GET_KCOM_XFEROFF(m_dsk.kcom) || m_dsk.kfer) { |
| 1462 | 1462 | // sector task is active OR xferoff is set OR fatal error |
| 1463 | | dhd->set_egate(1); |
| 1464 | | dhd->set_wrgate(1); |
| 1465 | | dhd->set_rdgate(1); |
| 1463 | dhd->set_egate(m_dsk.egate = 1); |
| 1464 | dhd->set_wrgate(m_dsk.wrgate = 1); |
| 1465 | dhd->set_rdgate(m_dsk.rdgate = 1); |
| 1466 | 1466 | } else { |
| 1467 | 1467 | // assert either erase and read or write gates depending on current record R/W |
| 1468 | 1468 | if (m_dsk.krwc & RWC_WRITE) { |
| 1469 | 1469 | // assert erase and write gates only if OKTORUN is high |
| 1470 | 1470 | if (m_dsk.ok_to_run) { |
| 1471 | | dhd->set_egate(0); |
| 1472 | | dhd->set_wrgate(0); |
| 1471 | dhd->set_egate(m_dsk.egate = 0); |
| 1472 | dhd->set_wrgate(m_dsk.wrgate = 0); |
| 1473 | 1473 | } |
| 1474 | 1474 | } else { |
| 1475 | | // assert read gate |
| 1476 | | dhd->set_rdgate(0); |
| 1475 | // assert read gate only if OKTORUN is high |
| 1476 | if (m_dsk.ok_to_run) { |
| 1477 | dhd->set_rdgate(m_dsk.rdgate = 0); |
| 1478 | } |
| 1477 | 1479 | } |
| 1478 | 1480 | } |
| 1479 | 1481 | |
| r26171 | r26172 | |
| 1653 | 1655 | PUT_KSTAT_SEEKFAIL(m_dsk.kstat, m_dsk.seekok ? 0 : 1); |
| 1654 | 1656 | |
| 1655 | 1657 | /* KSTAT[9] latch the drive seek/read/write status */ |
| 1656 | | PUT_KSTAT_SEEK(m_dsk.kstat, dhd ? dhd->get_seek_read_write_0() : 1); |
| 1658 | PUT_KSTAT_SEEK(m_dsk.kstat, dhd->get_seek_read_write_0()); |
| 1657 | 1659 | |
| 1658 | 1660 | /* KSTAT[10] latch the latched (FF 45a at CLRSTAT) ready status */ |
| 1659 | 1661 | PUT_KSTAT_NOTRDY(m_dsk.kstat, m_dsk.ff_45a & JKFF_Q ? 1 : 0); |
| r26171 | r26172 | |
| 1669 | 1671 | LOG((LOG_DISK,1," ←KSTAT; BUS &= %#o\n", r)); |
| 1670 | 1672 | LOG((LOG_DISK,2," sector : %#o\n", GET_KSTAT_SECTOR(m_dsk.kstat))); |
| 1671 | 1673 | LOG((LOG_DISK,2," done : %#o\n", GET_KSTAT_DONE(m_dsk.kstat))); |
| 1672 | | LOG((LOG_DISK,2," seekfail : %#o\n", GET_KSTAT_SEEKFAIL(m_dsk.kstat))); |
| 1673 | | LOG((LOG_DISK,2," seek : %#o\n", GET_KSTAT_SEEK(m_dsk.kstat))); |
| 1674 | | LOG((LOG_DISK,2," notrdy : %#o\n", GET_KSTAT_NOTRDY(m_dsk.kstat))); |
| 1675 | | LOG((LOG_DISK,2," datalate : %#o\n", GET_KSTAT_DATALATE(m_dsk.kstat))); |
| 1676 | | LOG((LOG_DISK,2," idle : %#o\n", GET_KSTAT_IDLE(m_dsk.kstat))); |
| 1677 | | LOG((LOG_DISK,2," cksum : %#o\n", GET_KSTAT_CKSUM(m_dsk.kstat))); |
| 1674 | LOG((LOG_DISK,2," seekfail : %d\n", GET_KSTAT_SEEKFAIL(m_dsk.kstat))); |
| 1675 | LOG((LOG_DISK,2," seek : %d\n", GET_KSTAT_SEEK(m_dsk.kstat))); |
| 1676 | LOG((LOG_DISK,2," notrdy : %d\n", GET_KSTAT_NOTRDY(m_dsk.kstat))); |
| 1677 | LOG((LOG_DISK,2," datalate : %d\n", GET_KSTAT_DATALATE(m_dsk.kstat))); |
| 1678 | LOG((LOG_DISK,2," idle : %d\n", GET_KSTAT_IDLE(m_dsk.kstat))); |
| 1679 | LOG((LOG_DISK,2," cksum : %d\n", GET_KSTAT_CKSUM(m_dsk.kstat))); |
| 1678 | 1680 | LOG((LOG_DISK,2," completion : %#o\n", GET_KSTAT_COMPLETION(m_dsk.kstat))); |
| 1679 | 1681 | |
| 1680 | 1682 | m_bus &= r; |
| r26171 | r26172 | |
| 1956 | 1958 | m_dsk.ff_45b = update_jkff(s0, s1); |
| 1957 | 1959 | |
| 1958 | 1960 | /* set or reset monoflop 31a, depending on drive READY' */ |
| 1959 | | m_dsk.ready_mf31a = dhd ? dhd->get_ready_0() : 1; |
| 1961 | m_dsk.ready_mf31a = dhd->get_ready_0(); |
| 1960 | 1962 | |
| 1961 | 1963 | /* start monoflop 31a, which resets ready_mf31a */ |
| 1962 | | m_dsk.ready_timer->adjust(TW_READY, 1); |
| 1964 | m_dsk.ready_timer->adjust(attotime::from_nsec(TW_READY), 1); |
| 1963 | 1965 | m_dsk.ready_timer->enable(); |
| 1964 | 1966 | } |
| 1965 | 1967 | |
| r26171 | r26172 | |
| 2015 | 2017 | PUT_KADR_NOXFER(m_dsk.kadr, GET_KADR_NOXFER(m_bus)); |
| 2016 | 2018 | PUT_KADR_UNUSED(m_dsk.kadr, GET_KADR_UNUSED(m_bus)); |
| 2017 | 2019 | |
| 2018 | | /* get selected drive from DATA[14] output (FF 67a really) */ |
| 2019 | | unit = GET_KADDR_DRIVE(m_dsk.kaddr); |
| 2020 | | /* latch head from DATA[13] */ |
| 2021 | | head = GET_KADDR_HEAD(m_dsk.dataout); |
| 2022 | | PUT_KADDR_HEAD(m_dsk.kaddr, head); |
| 2023 | | /* get the selected head, and select drive unit and head */ |
| 2020 | unit = GET_KADDR_DRIVE(m_dsk.kaddr); // get selected drive from DATA[14] output (FF 67a really) |
| 2021 | head = GET_KADDR_HEAD(m_dsk.dataout); // latch head from DATA[13] |
| 2022 | PUT_KADDR_HEAD(m_dsk.kaddr, head); // store in KADDR |
| 2023 | |
| 2024 | /* take the selected head and select drive unit and head in the DIABLO HD */ |
| 2024 | 2025 | diablo_hd_device* dhd = m_drive[unit]; |
| 2025 | | if (dhd) |
| 2026 | | dhd->select(unit, head); |
| 2026 | dhd->select(unit, head); |
| 2027 | 2027 | |
| 2028 | | /* On KDAR← bit 0 of parts #36 and #37 is reset to 0, i.e. recno = 0 */ |
| 2028 | /* On KDAR← load bit 0 of parts #36 and #37 is reset to 0, i.e. recno = 0 */ |
| 2029 | 2029 | m_dsk.krecno = 0; |
| 2030 | 2030 | /* current read/write/check is that for the header */ |
| 2031 | 2031 | m_dsk.krwc = GET_KADR_HEADER(m_dsk.kadr); |
| r26171 | r26172 | |
| 2037 | 2037 | LOG((LOG_DISK,2," data : %s (%#o)\n", rwc_name[GET_KADR_DATA(m_dsk.kadr)], GET_KADR_DATA(m_dsk.kadr))); |
| 2038 | 2038 | LOG((LOG_DISK,2," noxfer : %#o\n", GET_KADR_NOXFER(m_dsk.kadr))); |
| 2039 | 2039 | LOG((LOG_DISK,2," unused : %#o (drive?)\n", GET_KADR_UNUSED(m_dsk.kadr))); |
| 2040 | | |
| 2041 | 2040 | // TODO: show disk indicator in the GUI? |
| 2042 | 2041 | } |
| 2043 | 2042 | |
| r26171 | r26172 | |
| 2350 | 2349 | m_sysclkb1[3] = JKFF_CLK; |
| 2351 | 2350 | |
| 2352 | 2351 | m_dsk.wdtskena = 1; |
| 2352 | m_dsk.egate = 1; |
| 2353 | m_dsk.wrgate = 1; |
| 2354 | m_dsk.rdgate = 1; |
| 2353 | 2355 | |
| 2354 | 2356 | m_dsk.seclate = 0; |
| 2355 | 2357 | m_dsk.ok_to_run = 0; |
branches/alto2/src/emu/machine/diablo_hd.c
| r26171 | r26172 | |
| 1088 | 1088 | */ |
| 1089 | 1089 | void diablo_hd_device::wr_data(int index, int wrdata) |
| 1090 | 1090 | { |
| 1091 | | if (m_wrgate_0) |
| 1091 | if (m_wrgate_0) { |
| 1092 | LOG_DRIVE((0,"[DHD] %s: unit #%d wrgate not asserted\n", __FUNCTION__, m_unit)); |
| 1092 | 1093 | return; // write gate is not asserted (active 0) |
| 1094 | } |
| 1093 | 1095 | |
| 1094 | | if (index < 0 || index >= bits_per_sector()) |
| 1096 | if (index < 0 || index >= bits_per_sector()) { |
| 1097 | LOG_DRIVE((0,"[DHD] %s: unit #%d index out of range (%d)\n", __FUNCTION__, m_unit, index)); |
| 1095 | 1098 | return; // don't write before or beyond the sector |
| 1099 | } |
| 1096 | 1100 | |
| 1097 | | if (-1 == m_page) |
| 1101 | if (-1 == m_page) { |
| 1102 | LOG_DRIVE((0,"[DHD] %s: unit #%d invalid page\n", __FUNCTION__, m_unit)); |
| 1098 | 1103 | return; // invalid page |
| 1104 | } |
| 1099 | 1105 | |
| 1100 | 1106 | UINT32 *bits = expand_sector(); |
| 1101 | 1107 | if (-1 == m_wrfirst) |
| 1102 | 1108 | m_wrfirst = index; |
| 1103 | 1109 | |
| 1104 | | LOG_DRIVE((7,"[DHD] %s: write #%d %d/%d/%d bit #%d bit:%d\n", __FUNCTION__, m_unit, m_cylinder, m_head, m_sector, index, wrdata)); |
| 1110 | LOG_DRIVE((7,"[DHD] %s: unit #%d %d/%d/%d bit #%d bit:%d\n", __FUNCTION__, m_unit, m_cylinder, m_head, m_sector, index, wrdata)); |
| 1105 | 1111 | |
| 1106 | 1112 | if (index < GUARD_ZONE_BITS) { |
| 1107 | 1113 | /* don't write in the guard zone (?) */ |
| r26171 | r26172 | |
| 1124 | 1130 | { |
| 1125 | 1131 | int bit = 0; |
| 1126 | 1132 | |
| 1127 | | if (m_rdgate_0) |
| 1128 | | return 0; // read gate is not asserted (active 0) |
| 1133 | if (m_rdgate_0) { |
| 1134 | LOG_DRIVE((9,"[DHD] %s: unit #%d rdgate not asserted\n", __FUNCTION__, m_unit)); |
| 1135 | return 1; // read gate is not asserted (active 0) |
| 1136 | } |
| 1129 | 1137 | |
| 1130 | | if (index < 0 || index >= bits_per_sector()) |
| 1138 | if (index < 0 || index >= bits_per_sector()) { |
| 1139 | LOG_DRIVE((0,"[DHD] %s: unit #%d index out of range (%d)\n", __FUNCTION__, m_unit, index)); |
| 1131 | 1140 | return 1; // don't read before or beyond the sector |
| 1141 | } |
| 1132 | 1142 | |
| 1133 | | if (0 == m_sector_mark_0) |
| 1134 | | return 1; // no data while sector mark is low (?) |
| 1143 | if (0 == m_sector_mark_0) { |
| 1144 | LOG_DRIVE((0,"[DHD] %s: unit #%d read while sector mark is asserted\n", __FUNCTION__, m_unit)); |
| 1145 | return 1; // no data while sector mark is asserted |
| 1146 | } |
| 1135 | 1147 | |
| 1136 | | if (-1 == m_page) |
| 1148 | if (-1 == m_page) { |
| 1149 | LOG_DRIVE((0,"[DHD] %s: unit #%d invalid page\n", __FUNCTION__, m_unit)); |
| 1137 | 1150 | return 1; // invalid page |
| 1151 | } |
| 1138 | 1152 | |
| 1139 | 1153 | UINT32 *bits = expand_sector(); |
| 1140 | 1154 | if (-1 == m_rdfirst) |
| r26171 | r26172 | |
| 1159 | 1173 | { |
| 1160 | 1174 | int clk = 0; |
| 1161 | 1175 | |
| 1162 | | if (index < 0 || index >= bits_per_sector()) |
| 1176 | if (index < 0 || index >= bits_per_sector()) { |
| 1177 | LOG_DRIVE((0,"[DHD] %s: unit #%d index out of range (%d)\n", __FUNCTION__, m_unit, index)); |
| 1163 | 1178 | return 1; // don't read before or beyond the sector |
| 1179 | } |
| 1164 | 1180 | |
| 1165 | | if (0 == m_sector_mark_0) |
| 1181 | if (0 == m_sector_mark_0) { |
| 1182 | LOG_DRIVE((0,"[DHD] %s: unit #%d read while sector mark is asserted\n", __FUNCTION__, m_unit)); |
| 1166 | 1183 | return 1; // no clock while sector mark is low (?) |
| 1184 | } |
| 1167 | 1185 | |
| 1168 | | if (-1 == m_page) |
| 1186 | if (-1 == m_page) { |
| 1187 | LOG_DRIVE((0,"[DHD] %s: unit #%d invalid page\n", __FUNCTION__, m_unit)); |
| 1169 | 1188 | return 1; // invalid page |
| 1189 | } |
| 1170 | 1190 | |
| 1171 | 1191 | UINT32 *bits = expand_sector(); |
| 1172 | 1192 | if (-1 == m_rdfirst) |
| r26171 | r26172 | |
| 1272 | 1292 | m_seek_incomplete_0 = 1; // deassert drive seek incomplete |
| 1273 | 1293 | |
| 1274 | 1294 | // reset the disk drive's address |
| 1275 | | m_cylinder = -1; |
| 1276 | | m_head = -1; |
| 1277 | | m_sector = -1; |
| 1278 | | m_page = -1; |
| 1295 | m_cylinder = 0; |
| 1296 | m_head = 0; |
| 1297 | m_sector = 0; |
| 1298 | m_page = 0; |
| 1279 | 1299 | |
| 1280 | 1300 | // disable the erase, write and read gates |
| 1281 | 1301 | m_egate_0 = 1; |
| r26171 | r26172 | |
| 1306 | 1326 | */ |
| 1307 | 1327 | void diablo_hd_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) |
| 1308 | 1328 | { |
| 1309 | | LOG_DRIVE((6,"[DHD] %s: id=%d param=%d ptr=%p\n", __FUNCTION__, id, param, ptr)); |
| 1329 | LOG_DRIVE((6,"[DHD] %s: id=%d param=%d ptr=%p @%lldns\n", __FUNCTION__, id, param, ptr, (long long int)(timer.elapsed().as_double() * ATTOSECONDS_PER_NANOSECOND))); |
| 1310 | 1330 | |
| 1311 | 1331 | switch (param) { |
| 1312 | 1332 | case 0: |