branches/alto2/src/emu/cpu/alto2/a2disk.c
| r26135 | r26136 | |
| 92 | 92 | }; |
| 93 | 93 | |
| 94 | 94 | #if ALTO2_DEBUG |
| 95 | | /** @brief human readable names for the KADR<- modes */ |
| 95 | /** @brief human readable names for the KADR← modes */ |
| 96 | 96 | static const char *rwc_name[4] = {"read", "check", "write", "write2"}; |
| 97 | 97 | #endif |
| 98 | 98 | |
| r26135 | r26136 | |
| 973 | 973 | * 15, so it counts to 16 on the next rising edge and makes WDDONE' go to 0. |
| 974 | 974 | * |
| 975 | 975 | * If HIORDBIT is 0 at the falling edge of BITCLK, counting continues as it was |
| 976 | | * preset with BUS[4] at the last KCOM<- load: |
| 976 | * preset with BUS[4] at the last KCOM← load: |
| 977 | 977 | * |
| 978 | 978 | * If BUS[4] was 1, both J and K' of the FF (74109) will be 1 at the rising edge |
| 979 | | * of LDCOM' (at the end of KCOM<-) and Q will be 1 => LOAD' is deasserted. |
| 979 | * of LDCOM' (at the end of KCOM←) and Q will be 1 => LOAD' is deasserted. |
| 980 | 980 | * |
| 981 | 981 | * If BUS[4] was 0, both J and K' will be 0, and Q will be 0 => LOAD' asserted. |
| 982 | 982 | * |
| r26135 | r26136 | |
| 1063 | 1063 | } |
| 1064 | 1064 | /* |
| 1065 | 1065 | * Falling edge of BITCLK, counting continues as it was preset |
| 1066 | | * with BUS[4] (WFFO) at the last KCOM<- load, or as set by a |
| 1066 | * with BUS[4] (WFFO) at the last KCOM← load, or as set by a |
| 1067 | 1067 | * 1 bit being read in HIORDBIT. |
| 1068 | 1068 | */ |
| 1069 | 1069 | if (WFFO) { |
| 1070 | 1070 | /* |
| 1071 | 1071 | * If BUS[4] (WFFO) was 1, both J and K' of the FF (74109) will |
| 1072 | | * be 1 at the rising edge of LDCOM' (at the end of KCOM<-) |
| 1072 | * be 1 at the rising edge of LDCOM' (at the end of KCOM←) |
| 1073 | 1073 | * and Q will be 1. LOAD' is deassterted: count on clock. |
| 1074 | 1074 | */ |
| 1075 | 1075 | m_dsk.bitcount = (m_dsk.bitcount + 1) % 16; |
| r26135 | r26136 | |
| 1604 | 1604 | * BUS[9] SRWRDY' from the Winchester drive |
| 1605 | 1605 | * BUS[10] RDYLAT' (latched READY' at last CLRSTAT, FF 45a output Q) |
| 1606 | 1606 | * BUS[11] SEQERR (latched SEQERR at last CLRSTAT, FF 45b output Q') |
| 1607 | | * The signals BUS[12,14-15] are just as they were loaded at KSTAT<- time. |
| 1607 | * The signals BUS[12,14-15] are just as they were loaded at KSTAT← time. |
| 1608 | 1608 | * BUS[13] CHSEMERROR (FF 44b output Q' inverted) |
| 1609 | 1609 | * </PRE> |
| 1610 | 1610 | */ |
| r26135 | r26136 | |
| 1629 | 1629 | /* KSTAT[11] latch the latched (FF 45b at CLRSTAT) seqerr status (Q') */ |
| 1630 | 1630 | PUT_KSTAT_DATALATE(m_dsk.kstat, m_dsk.ff_45b & JKFF_Q ? 0 : 1); |
| 1631 | 1631 | |
| 1632 | | /* KSTAT[13] latch the latched (FF 44b at CLRSTAT/KSTAT<-) checksum status */ |
| 1632 | /* KSTAT[13] latch the latched (FF 44b at CLRSTAT/KSTAT←) checksum status */ |
| 1633 | 1633 | PUT_KSTAT_CKSUM(m_dsk.kstat, m_dsk.ff_44b & JKFF_Q ? 1 : 0); |
| 1634 | 1634 | |
| 1635 | 1635 | r = m_dsk.kstat; |
| 1636 | 1636 | |
| 1637 | | LOG((LOG_DISK,1," <-KSTAT; BUS &= %#o\n", r)); |
| 1637 | LOG((LOG_DISK,1," ←KSTAT; BUS &= %#o\n", r)); |
| 1638 | 1638 | LOG((LOG_DISK,2," sector: %d\n", GET_KSTAT_SECTOR(m_dsk.kstat))); |
| 1639 | 1639 | LOG((LOG_DISK,2," done: %d\n", GET_KSTAT_DONE(m_dsk.kstat))); |
| 1640 | 1640 | LOG((LOG_DISK,2," seekfail: %d\n", GET_KSTAT_SEEKFAIL(m_dsk.kstat))); |
| r26135 | r26136 | |
| 1661 | 1661 | UINT16 r; |
| 1662 | 1662 | /* get the current word from the drive */ |
| 1663 | 1663 | r = m_dsk.datain; |
| 1664 | | LOG((LOG_DISK,1," <-KDATA (%#o)\n", r)); |
| 1664 | LOG((LOG_DISK,1," ←KDATA (%#o)\n", r)); |
| 1665 | 1665 | m_bus &= r; |
| 1666 | 1666 | } |
| 1667 | 1667 | |
| r26135 | r26136 | |
| 1699 | 1699 | void alto2_cpu_device::f1_load_kstat_1() |
| 1700 | 1700 | { |
| 1701 | 1701 | int i; |
| 1702 | | LOG((LOG_DISK,1," KSTAT<-; BUS[12-15] %#o\n", m_bus)); |
| 1702 | LOG((LOG_DISK,1," KSTAT←; BUS[12-15] %#o\n", m_bus)); |
| 1703 | 1703 | LOG((LOG_DISK,2," idle: %d\n", GET_KSTAT_IDLE(m_bus))); |
| 1704 | 1704 | LOG((LOG_DISK,2," cksum: %d\n", GET_KSTAT_CKSUM(m_bus))); |
| 1705 | 1705 | LOG((LOG_DISK,2," completion:%d\n", GET_KSTAT_COMPLETION(m_bus))); |
| r26135 | r26136 | |
| 1711 | 1711 | PUT_KSTAT_COMPLETION(m_dsk.kstat, GET_KSTAT_COMPLETION(m_bus)); |
| 1712 | 1712 | |
| 1713 | 1713 | /* May set the the CKSUM flip-flop 44b |
| 1714 | | * JK flip-flop 44b (KSTAT<- clocked) |
| 1714 | * JK flip-flop 44b (KSTAT← clocked) |
| 1715 | 1715 | * CLK SYSCLKA' |
| 1716 | 1716 | * J !BUS[13] |
| 1717 | 1717 | * K' 1 |
| 1718 | 1718 | * S' 1 |
| 1719 | 1719 | * C' CLRSTAT' (not now) |
| 1720 | | * Q Q' inverted to BUS[13] on <-KSTAT |
| 1720 | * Q Q' inverted to BUS[13] on ←KSTAT |
| 1721 | 1721 | */ |
| 1722 | 1722 | for (i = 0; i < 2; i++) { |
| 1723 | 1723 | UINT8 s0, s1; |
| r26135 | r26136 | |
| 1750 | 1750 | PUT_KADDR_DRIVE(m_dsk.kaddr, GET_KADDR_DRIVE(m_bus)); |
| 1751 | 1751 | m_dsk.drive = GET_KADDR_DRIVE(m_dsk.kaddr); |
| 1752 | 1752 | |
| 1753 | | LOG((LOG_DISK,1," KDATA<-; BUS (%#o) (drive:%d restore:%d %d/%d/%02d)\n", |
| 1753 | LOG((LOG_DISK,1," KDATA←; BUS (%#o) (drive:%d restore:%d %d/%d/%02d)\n", |
| 1754 | 1754 | m_bus, |
| 1755 | 1755 | GET_KADDR_DRIVE(m_dsk.kaddr), |
| 1756 | 1756 | GET_KADDR_RESTORE(m_dsk.kaddr), |
| r26135 | r26136 | |
| 1775 | 1775 | } |
| 1776 | 1776 | #endif |
| 1777 | 1777 | } else { |
| 1778 | | LOG((LOG_DISK,1," KDATA<-; BUS %#o (%#x)\n", m_bus, m_bus)); |
| 1778 | LOG((LOG_DISK,1," KDATA←; BUS %#o (%#x)\n", m_bus, m_bus)); |
| 1779 | 1779 | } |
| 1780 | 1780 | } |
| 1781 | 1781 | |
| r26135 | r26136 | |
| 1792 | 1792 | * Vcc, BUS[08], BUS[10], BUS[12] go to #36 A,B,C,D |
| 1793 | 1793 | * Vcc, BUS[09], BUS[11], BUS[13] go to #37 A,B,C,D |
| 1794 | 1794 | * A is connected to ground on both chips; |
| 1795 | | * both shifters are loaded with KADR<- |
| 1795 | * both shifters are loaded with KADR← |
| 1796 | 1796 | * |
| 1797 | 1797 | * The QA outputs are #36 -> RECNO(0) and #37 -> RECNO(1) |
| 1798 | 1798 | * |
| r26135 | r26136 | |
| 1873 | 1873 | 0); |
| 1874 | 1874 | |
| 1875 | 1875 | /* clears the CKSUM flip-flop 44b |
| 1876 | | * JK flip-flop 44b (KSTAT<- clocked) |
| 1876 | * JK flip-flop 44b (KSTAT← clocked) |
| 1877 | 1877 | * CLK SYSCLKA' (not used here, just clearing) |
| 1878 | | * J 1 (BUS[13] during KSTAT<-) |
| 1878 | * J 1 (BUS[13] during KSTAT←) |
| 1879 | 1879 | * K' 1 |
| 1880 | 1880 | * S' 1 |
| 1881 | 1881 | * C' CLRSTAT' |
| r26135 | r26136 | |
| 1953 | 1953 | { |
| 1954 | 1954 | if (m_dsk.kcom != m_bus) { |
| 1955 | 1955 | m_dsk.kcom = m_bus; |
| 1956 | | LOG((LOG_DISK,2," KCOM<-; BUS %06o\n", m_dsk.kcom)); |
| 1956 | LOG((LOG_DISK,2," KCOM←; BUS %06o\n", m_dsk.kcom)); |
| 1957 | 1957 | LOG((LOG_DISK,2," xferoff: %d\n", GET_KCOM_XFEROFF(m_dsk.kcom))); |
| 1958 | 1958 | LOG((LOG_DISK,2," wdinhib: %d\n", GET_KCOM_WDINHIB(m_dsk.kcom))); |
| 1959 | 1959 | LOG((LOG_DISK,2," bclksrc: %d\n", GET_KCOM_BCLKSRC(m_dsk.kcom))); |
| r26135 | r26136 | |
| 1995 | 1995 | if (dhd) |
| 1996 | 1996 | dhd->select(unit, head); |
| 1997 | 1997 | |
| 1998 | | /* On KDAR<- bit 0 of parts #36 and #37 is reset to 0, i.e. recno = 0 */ |
| 1998 | /* On KDAR← bit 0 of parts #36 and #37 is reset to 0, i.e. recno = 0 */ |
| 1999 | 1999 | m_dsk.krecno = 0; |
| 2000 | 2000 | /* current read/write/check is that for the header */ |
| 2001 | 2001 | m_dsk.krwc = GET_KADR_HEADER(m_dsk.kadr); |
| 2002 | 2002 | |
| 2003 | | LOG((LOG_DISK,1," KADR<-; BUS[8-14] #%o\n", m_dsk.kadr)); |
| 2003 | LOG((LOG_DISK,1," KADR←; BUS[8-14] #%o\n", m_dsk.kadr)); |
| 2004 | 2004 | LOG((LOG_DISK,2," seal: %#o\n", GET_KADR_SEAL(m_dsk.kadr))); |
| 2005 | 2005 | LOG((LOG_DISK,2," header: %s\n", rwc_name[GET_KADR_HEADER(m_dsk.kadr)])); |
| 2006 | 2006 | LOG((LOG_DISK,2," label: %s\n", rwc_name[GET_KADR_LABEL(m_dsk.kadr)])); |
| r26135 | r26136 | |
| 2014 | 2014 | /** |
| 2015 | 2015 | * @brief f2_init late: branch on disk word task active and init |
| 2016 | 2016 | * |
| 2017 | | * NEXT <- NEXT OR (WDTASKACT && WDINIT ? 037 : 0) |
| 2017 | * NEXT ← NEXT OR (WDTASKACT && WDINIT ? 037 : 0) |
| 2018 | 2018 | */ |
| 2019 | 2019 | void alto2_cpu_device::f2_init_1() |
| 2020 | 2020 | { |
| r26135 | r26136 | |
| 2027 | 2027 | /** |
| 2028 | 2028 | * @brief f2_rwc late: branch on read/write/check state of the current record |
| 2029 | 2029 | * <PRE> |
| 2030 | | * NEXT <- NEXT OR (current record to be written ? 3 : |
| 2030 | * NEXT ← NEXT OR (current record to be written ? 3 : |
| 2031 | 2031 | * current record to be checked ? 2 : 0); |
| 2032 | 2032 | * |
| 2033 | 2033 | * NB: note how krecno counts 0,2,3,1 ... etc. |
| r26135 | r26136 | |
| 2082 | 2082 | /** |
| 2083 | 2083 | * @brief f2_recno late: branch on the current record number by a lookup table |
| 2084 | 2084 | * <PRE> |
| 2085 | | * NEXT <- NEXT OR MAP (current record number) where |
| 2085 | * NEXT ← NEXT OR MAP (current record number) where |
| 2086 | 2086 | * MAP(0) = 0 (header) |
| 2087 | 2087 | * MAP(1) = 2 (label) |
| 2088 | 2088 | * MAP(2) = 3 (pageno) |
| r26135 | r26136 | |
| 2102 | 2102 | /** |
| 2103 | 2103 | * @brief f2_xfrdat late: branch on the data transfer state |
| 2104 | 2104 | * |
| 2105 | | * NEXT <- NEXT OR (if current command wants data transfer ? 1 : 0) |
| 2105 | * NEXT ← NEXT OR (if current command wants data transfer ? 1 : 0) |
| 2106 | 2106 | */ |
| 2107 | 2107 | void alto2_cpu_device::f2_xfrdat_1() |
| 2108 | 2108 | { |
| r26135 | r26136 | |
| 2116 | 2116 | /** |
| 2117 | 2117 | * @brief f2_swrnrdy late: branch on the disk ready signal |
| 2118 | 2118 | * |
| 2119 | | * NEXT <- NEXT OR (if disk not ready to accept command ? 1 : 0) |
| 2119 | * NEXT ← NEXT OR (if disk not ready to accept command ? 1 : 0) |
| 2120 | 2120 | */ |
| 2121 | 2121 | void alto2_cpu_device::f2_swrnrdy_1() |
| 2122 | 2122 | { |
| r26135 | r26136 | |
| 2132 | 2132 | /** |
| 2133 | 2133 | * @brief f2_nfer late: branch on the disk fatal error condition |
| 2134 | 2134 | * |
| 2135 | | * NEXT <- NEXT OR (if fatal error in latches ? 0 : 1) |
| 2135 | * NEXT ← NEXT OR (if fatal error in latches ? 0 : 1) |
| 2136 | 2136 | */ |
| 2137 | 2137 | void alto2_cpu_device::f2_nfer_1() |
| 2138 | 2138 | { |
| r26135 | r26136 | |
| 2147 | 2147 | /** |
| 2148 | 2148 | * @brief f2_strobon late: branch on the seek busy status |
| 2149 | 2149 | * |
| 2150 | | * NEXT <- NEXT OR (if seek strobe still on ? 1 : 0) |
| 2150 | * NEXT ← NEXT OR (if seek strobe still on ? 1 : 0) |
| 2151 | 2151 | * <PRE> |
| 2152 | 2152 | * The STROBE signal is elongated with the help of two monoflops. |
| 2153 | 2153 | * The first one has a rather short pulse duration: |
| r26135 | r26136 | |
| 2245 | 2245 | * |
| 2246 | 2246 | * @param unit the unit number |
| 2247 | 2247 | */ |
| 2248 | | void alto2_cpu_device::disk_sector_start(int unit) |
| 2248 | void alto2_cpu_device::next_sector(int unit) |
| 2249 | 2249 | { |
| 2250 | 2250 | diablo_hd_device* dhd = m_drive[unit]; |
| 2251 | 2251 | if (m_dsk.bitclk_timer) { |
| r26135 | r26136 | |
| 2269 | 2269 | } |
| 2270 | 2270 | |
| 2271 | 2271 | /** |
| 2272 | * @brief callback is called by the drive timer whenever a new sector starts |
| 2273 | * |
| 2274 | * @param unit the unit number |
| 2275 | */ |
| 2276 | static void disk_sector_start(void* cookie, int unit) |
| 2277 | { |
| 2278 | alto2_cpu_device* cpu = reinterpret_cast<alto2_cpu_device *>(cookie); |
| 2279 | cpu->next_sector(unit); |
| 2280 | } |
| 2281 | |
| 2282 | /** |
| 2272 | 2283 | * @brief initialize the disk context and insert a disk wort timer |
| 2273 | 2284 | * |
| 2274 | 2285 | * @result returns 0 on success, fatal() on error |
| 2275 | 2286 | */ |
| 2276 | 2287 | void alto2_cpu_device::init_disk() |
| 2277 | 2288 | { |
| 2278 | | // diablo_hd_device* dhd; |
| 2279 | | // for (int unit = 0; unit < 2; unit++) { |
| 2280 | | // dhd = m_drive[unit]; |
| 2281 | | // if (!dhd) |
| 2282 | | // continue; |
| 2283 | | // dhd->sector_callback(&alto2_cpu_device::disk_sector_start); |
| 2284 | | // } |
| 2289 | diablo_hd_device* dhd; |
| 2290 | for (int unit = 0; unit < 2; unit++) { |
| 2291 | dhd = m_drive[unit]; |
| 2292 | if (!dhd) |
| 2293 | continue; |
| 2294 | dhd->set_sector_callback(this, &disk_sector_start); |
| 2295 | } |
| 2285 | 2296 | |
| 2286 | 2297 | memset(&m_dsk, 0, sizeof(m_dsk)); |
| 2287 | 2298 | |
branches/alto2/src/emu/machine/diablo_hd.c
| r26135 | r26136 | |
| 94 | 94 | m_rdlast(-1), |
| 95 | 95 | m_wrfirst(-1), |
| 96 | 96 | m_wrlast(-1), |
| 97 | m_sector_callback_cookie(0), |
| 97 | 98 | m_sector_callback(0), |
| 98 | 99 | m_sector_timer(0), |
| 99 | 100 | m_image(0), |
| r26135 | r26136 | |
| 120 | 121 | } |
| 121 | 122 | } |
| 122 | 123 | |
| 124 | void diablo_hd_device::set_sector_callback(void *cookie, void (*callback)(void *, int)) |
| 125 | { |
| 126 | m_sector_callback_cookie = cookie; |
| 127 | m_sector_callback = callback; |
| 128 | } |
| 129 | |
| 123 | 130 | #if DIABLO_DEBUG |
| 124 | 131 | void diablo_hd_device::logprintf(int level, const char* format, ...) |
| 125 | 132 | { |
| r26135 | r26136 | |
| 382 | 389 | } |
| 383 | 390 | |
| 384 | 391 | /** |
| 385 | | * @brief Expand a record's checksum word to 32 bits |
| 392 | * @brief expand a record's checksum word to 32 bits |
| 386 | 393 | * |
| 387 | 394 | * @param bits pointer to the sector bits |
| 388 | 395 | * @param dst destination offset into bits (bit number) |
| r26135 | r26136 | |
| 402 | 409 | } |
| 403 | 410 | |
| 404 | 411 | /** |
| 405 | | * @brief Expand a sector into an array of clock and data bits |
| 412 | * @brief expand a sector into an array of clock and data bits |
| 406 | 413 | * |
| 407 | 414 | * @param page page number (0 to DRIVE_PAGES-1) |
| 408 | 415 | */ |
| r26135 | r26136 | |
| 484 | 491 | |
| 485 | 492 | |
| 486 | 493 | /** |
| 487 | | * @brief Dump a record's contents |
| 494 | * @brief dump a record's contents |
| 488 | 495 | * |
| 489 | 496 | * @param src pointer to a record (header, label, data) |
| 490 | 497 | * @param size size of the record in bytes |
| r26135 | r26136 | |
| 643 | 650 | } |
| 644 | 651 | |
| 645 | 652 | /** |
| 646 | | * @brief Squeeze a array of clock and data bits into a sector's data |
| 653 | * @brief squeeze a array of clock and data bits into a sector's data |
| 654 | * |
| 655 | * Find and squeeze header, label and data and verify for |
| 656 | * zero checksums (starting with 0521) |
| 657 | * Write the page back to the media and free the bitmap |
| 647 | 658 | */ |
| 648 | 659 | void diablo_hd_device::squeeze_sector() |
| 649 | 660 | { |
| r26135 | r26136 | |
| 1218 | 1229 | m_sector_timer->adjust(m_sector_time - m_sector_mark_0_time, 0); |
| 1219 | 1230 | /* call the sector_callback, if any */ |
| 1220 | 1231 | if (m_sector_callback) |
| 1221 | | (*m_sector_callback)(); |
| 1232 | (void)(*m_sector_callback)(m_sector_callback_cookie, m_unit); |
| 1222 | 1233 | } |
| 1223 | 1234 | } |
| 1224 | 1235 | |
| 1225 | 1236 | /** |
| 1226 | | * @brief timer callback that deasserts the sector mark |
| 1237 | * @brief deassert the sector mark |
| 1227 | 1238 | * |
| 1228 | | * @param unit drive unit number |
| 1229 | 1239 | */ |
| 1230 | 1240 | void diablo_hd_device::sector_mark_1() |
| 1231 | 1241 | { |
| r26135 | r26136 | |
| 1235 | 1245 | } |
| 1236 | 1246 | |
| 1237 | 1247 | /** |
| 1238 | | * @brief timer callback that asserts the sector mark |
| 1248 | * @brief assert the sector mark and read the next sector |
| 1239 | 1249 | * |
| 1240 | | * @param unit drive unit number |
| 1250 | * Assert the sector mark and reset the read and write |
| 1251 | * first and last bit indices. |
| 1252 | * Increment the sector number, wrap and read the |
| 1253 | * next sector from the media. |
| 1241 | 1254 | */ |
| 1242 | 1255 | void diablo_hd_device::sector_mark_0() |
| 1243 | 1256 | { |
branches/alto2/src/emu/machine/diablo_hd.h
| r26135 | r26136 | |
| 29 | 29 | diablo_hd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 30 | 30 | ~diablo_hd_device(); |
| 31 | 31 | |
| 32 | void set_sector_callback(void* cookie, void(*callback)(void*, int)); |
| 33 | |
| 32 | 34 | int bits_per_sector() const; |
| 33 | 35 | const char* description() const; |
| 34 | 36 | int unit() const; |
| r26135 | r26136 | |
| 66 | 68 | void logprintf(int level, const char* format, ...); |
| 67 | 69 | # define LOG_DRIVE(x) logprintf x |
| 68 | 70 | |
| 69 | | void dump_ascii(UINT8 *src, size_t size); |
| 70 | | size_t dump_record(UINT8 *src, size_t addr, size_t size, const char *name, int cr); |
| 71 | 71 | #else |
| 72 | 72 | # define LOG_DRIVE(x) |
| 73 | 73 | #endif |
| r26135 | r26136 | |
| 83 | 83 | //! convert a cylinder/head/sector to a logical block address (page) |
| 84 | 84 | static inline int DRIVE_PAGE(int c,int h,int s) { return (c * DIABLO_HEADS + h) * DIABLO_SPT + s; } |
| 85 | 85 | |
| 86 | | bool m_diablo31; //!< true, if this is a DIABLO31 drive |
| 87 | | int m_unit; //!< drive unit number (0 or 1) |
| 88 | | char m_description[32]; //!< description of the drive(s) |
| 89 | | int m_packs; //!< number of packs in drive (1 or 2) |
| 90 | | attotime m_rotation_time; //!< rotation time in atto seconds |
| 91 | | attotime m_sector_time; //!< sector time in atto seconds |
| 92 | | attotime m_sector_mark_0_time; //!< sector mark going 0 before sector pulse time |
| 93 | | attotime m_sector_mark_1_time; //!< sector mark going 1 after sector pulse time |
| 94 | | attotime m_bit_time; //!< bit time in atto seconds |
| 95 | | int m_s_r_w_0; //!< drive seek/read/write signal (active 0) |
| 96 | | int m_ready_0; //!< drive ready signal (active 0) |
| 97 | | int m_sector_mark_0; //!< sector mark (0 if new sector) |
| 98 | | int m_addx_acknowledge_0; //!< address acknowledge, i.e. seek successful (active 0) |
| 99 | | int m_log_addx_interlock_0; //!< log address interlock, i.e. seek in progress (active 0) |
| 100 | | int m_seek_incomplete_0; //!< seek incomplete, i.e. seek in progress (active 0) |
| 101 | | int m_egate_0; //!< erase gate |
| 102 | | int m_wrgate_0; //!< write gate |
| 103 | | int m_rdgate_0; //!< read gate |
| 104 | | int m_cylinder; //!< current cylinder number |
| 105 | | int m_head; //!< current head (track) number on cylinder |
| 106 | | int m_sector; //!< current sector number in track |
| 107 | | int m_page; //!< current page |
| 108 | | int m_pages; //!< total number of pages |
| 109 | | UINT8** m_cache; //!< pages raw bytes |
| 110 | | UINT32** m_bits; //!< pages expanded to bits |
| 111 | | int m_rdfirst; //!< set to first bit of a sector that is read from |
| 112 | | int m_rdlast; //!< set to last bit of a sector that was read from |
| 113 | | int m_wrfirst; //!< set to non-zero if a sector is written to |
| 114 | | int m_wrlast; //!< set to last bit of a sector that was written to |
| 115 | | void (*m_sector_callback)(); //!< callback to call at the start of each sector |
| 116 | | emu_timer* m_sector_timer; //!< sector timer |
| 117 | | diablo_image_device* m_image; //!< diablo_image_device interfacing the CHD |
| 118 | | chd_file* m_handle; //!< underlying CHD handle |
| 119 | | hard_disk_file* m_disk; //!< underlying hard disk file |
| 86 | bool m_diablo31; //!< true, if this is a DIABLO31 drive |
| 87 | int m_unit; //!< drive unit number (0 or 1) |
| 88 | char m_description[32]; //!< description of the drive(s) |
| 89 | int m_packs; //!< number of packs in drive (1 or 2) |
| 90 | attotime m_rotation_time; //!< rotation time in atto seconds |
| 91 | attotime m_sector_time; //!< sector time in atto seconds |
| 92 | attotime m_sector_mark_0_time; //!< sector mark going 0 before sector pulse time |
| 93 | attotime m_sector_mark_1_time; //!< sector mark going 1 after sector pulse time |
| 94 | attotime m_bit_time; //!< bit time in atto seconds |
| 95 | int m_s_r_w_0; //!< drive seek/read/write signal (active 0) |
| 96 | int m_ready_0; //!< drive ready signal (active 0) |
| 97 | int m_sector_mark_0; //!< sector mark (0 if new sector) |
| 98 | int m_addx_acknowledge_0; //!< address acknowledge, i.e. seek successful (active 0) |
| 99 | int m_log_addx_interlock_0; //!< log address interlock, i.e. seek in progress (active 0) |
| 100 | int m_seek_incomplete_0; //!< seek incomplete, i.e. seek in progress (active 0) |
| 101 | int m_egate_0; //!< erase gate |
| 102 | int m_wrgate_0; //!< write gate |
| 103 | int m_rdgate_0; //!< read gate |
| 104 | int m_cylinder; //!< current cylinder number |
| 105 | int m_head; //!< current head (track) number on cylinder |
| 106 | int m_sector; //!< current sector number in track |
| 107 | int m_page; //!< current page |
| 108 | int m_pages; //!< total number of pages |
| 109 | UINT8** m_cache; //!< pages raw bytes |
| 110 | UINT32** m_bits; //!< pages expanded to bits |
| 111 | int m_rdfirst; //!< set to first bit of a sector that is read from |
| 112 | int m_rdlast; //!< set to last bit of a sector that was read from |
| 113 | int m_wrfirst; //!< set to non-zero if a sector is written to |
| 114 | int m_wrlast; //!< set to last bit of a sector that was written to |
| 115 | void *m_sector_callback_cookie; //!< cookie to pass to callback |
| 116 | void (*m_sector_callback)(void*,int); //!< callback to call at the start of each sector |
| 117 | emu_timer* m_sector_timer; //!< sector timer |
| 118 | diablo_image_device* m_image; //!< diablo_image_device interfacing the CHD |
| 119 | chd_file* m_handle; //!< underlying CHD handle |
| 120 | hard_disk_file* m_disk; //!< underlying hard disk file |
| 120 | 121 | |
| 121 | | void read_sector(); //!< translate C/H/S to a page and read the sector |
| 122 | //! translate C/H/S to a page and read the sector |
| 123 | void read_sector(); |
| 124 | |
| 125 | //! compute the checksum of a record |
| 122 | 126 | int cksum(UINT8 *src, size_t size, int start); |
| 127 | |
| 128 | //! expand a series of clock bits and 0 data bits |
| 123 | 129 | size_t expand_zeroes(UINT32 *bits, size_t dst, size_t size); |
| 130 | |
| 131 | //! expand a series of 0 words and write a final sync bit |
| 124 | 132 | size_t expand_sync(UINT32 *bits, size_t dst, size_t size); |
| 133 | |
| 134 | //! expand a record of words into a array of bits at dst |
| 125 | 135 | size_t expand_record(UINT32 *bits, size_t dst, UINT8 *field, size_t size); |
| 136 | |
| 137 | //! expand a record's checksum word to 32 bits |
| 126 | 138 | size_t expand_cksum(UINT32 *bits, size_t dst, UINT8 *field, size_t size); |
| 139 | |
| 140 | //! expand a sector into an array of clock and data bits |
| 127 | 141 | UINT32* expand_sector(); |
| 128 | 142 | |
| 143 | #if DIABLO_DEBUG |
| 144 | //! dump a number of words as ASCII characters |
| 145 | void dump_ascii(UINT8 *src, size_t size); |
| 146 | |
| 147 | //! dump a record's contents |
| 148 | size_t dump_record(UINT8 *src, size_t addr, size_t size, const char *name, int cr); |
| 149 | #endif |
| 150 | |
| 151 | //! find a sync bit in an array of clock and data bits |
| 129 | 152 | size_t squeeze_sync(UINT32 *bits, size_t src, size_t size); |
| 153 | |
| 154 | //! find a 16 x 0 bits sequence in an array of clock and data bits |
| 130 | 155 | size_t squeeze_unsync(UINT32 *bits, size_t src, size_t size); |
| 156 | |
| 157 | //! squeeze an array of clock and data bits into a sector's record |
| 131 | 158 | size_t squeeze_record(UINT32 *bits, size_t src, UINT8 *field, size_t size); |
| 159 | |
| 160 | //! squeeze an array of 32 clock and data bits into a checksum word |
| 132 | 161 | size_t squeeze_cksum(UINT32 *bits, size_t src, int *cksum); |
| 162 | |
| 163 | //! squeeze a array of clock and data bits into a sector's data |
| 133 | 164 | void squeeze_sector(); |
| 134 | 165 | |
| 135 | | void next_sector(void* ptr, int arg); |
| 166 | //! timer callback that is called thrice per sector in the rotation |
| 167 | TIMER_CALLBACK_MEMBER( next_sector ); |
| 168 | |
| 169 | //! deassert the sector mark |
| 136 | 170 | void sector_mark_1(); |
| 171 | |
| 172 | //! assert the sector mark and read the next sector |
| 137 | 173 | void sector_mark_0(); |
| 138 | 174 | }; |
| 139 | 175 | |