branches/alto2/src/emu/machine/diablo_hd.c
| r26264 | r26265 | |
| 63 | 63 | diablo_hd_device::diablo_hd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : |
| 64 | 64 | device_t(mconfig, DIABLO_HD, "Diablo Disk", tag, owner, clock, "diablo_hd", __FILE__), |
| 65 | 65 | #if DIABLO_DEBUG |
| 66 | | m_log_level(0), |
| 66 | m_log_level(8), |
| 67 | 67 | #endif |
| 68 | 68 | m_diablo31(true), |
| 69 | 69 | m_unit(0), |
| r26264 | r26265 | |
| 170 | 170 | #define GUARD_ZONE_BITS (16*32) //!< end of the guard zone at the beginning of a sector (wild guess!) |
| 171 | 171 | |
| 172 | 172 | /** |
| 173 | | * @brief description of the sector layout |
| 173 | * @brief description of the sector layout (reverse engineered) |
| 174 | 174 | * <PRE> |
| 175 | 175 | * |
| 176 | 176 | * xx.x msec sector mark pulses |
| r26264 | r26265 | |
| 280 | 280 | { |
| 281 | 281 | /* If there's no drive, just reset the page number */ |
| 282 | 282 | if (!m_image) { |
| 283 | | LOG_DRIVE((0,"[DHD%u] C/H/S:%d/%d/%d => no image\n", m_unit, m_cylinder, m_head, m_sector)); |
| 283 | LOG_DRIVE((0,"[DHD%u] CHS:%03d/%d/%02d => no image\n", m_unit, m_cylinder, m_head, m_sector)); |
| 284 | 284 | m_page = -1; |
| 285 | 285 | return; |
| 286 | 286 | } |
| 287 | 287 | if (m_cylinder < 0 || m_cylinder >= DIABLO_CYLINDERS) { |
| 288 | | LOG_DRIVE((0,"[DHD%u] C/H/S:%d/%d/%d => invalid cylinder\n", m_unit, m_cylinder, m_head, m_sector)); |
| 288 | LOG_DRIVE((0,"[DHD%u] CHS:%03d/%d/%02d => invalid cylinder\n", m_unit, m_cylinder, m_head, m_sector)); |
| 289 | 289 | m_page = -1; |
| 290 | 290 | return; |
| 291 | 291 | } |
| 292 | 292 | if (m_head < 0 || m_head >= DIABLO_HEADS) { |
| 293 | | LOG_DRIVE((0,"[DHD%u] C/H/S:%d/%d/%d => invalid head\n", m_unit, m_cylinder, m_head, m_sector)); |
| 293 | LOG_DRIVE((0,"[DHD%u] CHS:%03d/%d/%02d => invalid head\n", m_unit, m_cylinder, m_head, m_sector)); |
| 294 | 294 | m_page = -1; |
| 295 | 295 | return; |
| 296 | 296 | } |
| 297 | 297 | if (m_sector < 0 || m_sector >= DIABLO_SPT) { |
| 298 | | LOG_DRIVE((0,"[DHD%u] C/H/S:%d/%d/%d => invalid sector\n", m_unit, m_cylinder, m_head, m_sector)); |
| 298 | LOG_DRIVE((0,"[DHD%u] CHS:%03d/%d/%02d => invalid sector\n", m_unit, m_cylinder, m_head, m_sector)); |
| 299 | 299 | m_page = -1; |
| 300 | 300 | return; |
| 301 | 301 | } |
| 302 | 302 | /* calculate the new disk relative sector offset */ |
| 303 | | m_page = DRIVE_PAGE(m_cylinder, m_head, m_sector); |
| 303 | m_page = DIABLO_PAGE(m_cylinder, m_head, m_sector); |
| 304 | 304 | |
| 305 | 305 | // already have the sector image? |
| 306 | 306 | if (m_cache[m_page]) { |
| 307 | | LOG_DRIVE((6,"[DHD%u] C/H/S:%d/%d/%d => page:%d is cached\n", m_unit, m_cylinder, m_head, m_sector, m_page)); |
| 307 | LOG_DRIVE((6,"[DHD%u] CHS:%03d/%d/%02d => page:%d is cached\n", m_unit, m_cylinder, m_head, m_sector, m_page)); |
| 308 | 308 | return; |
| 309 | 309 | } |
| 310 | 310 | |
| r26264 | r26265 | |
| 313 | 313 | m_cache[m_page] = auto_alloc_array(machine(), UINT8, sizeof(diablo_sector_t)); |
| 314 | 314 | /* and read the page from the hard_disk image */ |
| 315 | 315 | if (hard_disk_read(m_disk, m_page, m_cache[m_page])) { |
| 316 | | LOG_DRIVE((2,"[DHD%u] C/H/S:%d/%d/%d => page:%d loaded\n", m_unit, m_cylinder, m_head, m_sector, m_page)); |
| 316 | LOG_DRIVE((2,"[DHD%u] CHS:%03d/%d/%02d => page:%d loaded\n", m_unit, m_cylinder, m_head, m_sector, m_page)); |
| 317 | 317 | } else { |
| 318 | | LOG_DRIVE((0,"[DHD%u] C/H/S:%d/%d/%d => page:%d read failed\n", m_unit, m_cylinder, m_head, m_sector, m_page)); |
| 318 | LOG_DRIVE((0,"[DHD%u] CHS:%03d/%d/%02d => page:%d read failed\n", m_unit, m_cylinder, m_head, m_sector, m_page)); |
| 319 | 319 | auto_free(machine(), m_cache[m_page]); |
| 320 | 320 | m_cache[m_page] = 0; |
| 321 | 321 | } |
| r26264 | r26265 | |
| 446 | 446 | UINT32 *bits = reinterpret_cast<UINT32 *>(auto_alloc_array(machine(), UINT32, 400)); |
| 447 | 447 | |
| 448 | 448 | if (m_diablo31) { |
| 449 | | /* write sync bit after 31 words - 1 bit */ |
| 450 | | dst = expand_sync(bits, 0, 31); |
| 449 | /* write sync bit after (MFROBL-MRPAL) words - 1 bit */ |
| 450 | dst = expand_sync(bits, 0, (MFROBL - MRPAL)); |
| 451 | 451 | dst = expand_record(bits, dst, s->header, sizeof(s->header)); |
| 452 | 452 | dst = expand_cksum(bits, dst, s->header, sizeof(s->header)); |
| 453 | 453 | |
| 454 | | /* write sync bit after 2 * 5 + 1 words - 1 bit */ |
| 454 | /* write sync bit after 2 * MWPAL + 1 words - 1 bit */ |
| 455 | 455 | dst = expand_sync(bits, dst, 2 * MWPAL); |
| 456 | 456 | dst = expand_record(bits, dst, s->label, sizeof(s->label)); |
| 457 | 457 | dst = expand_cksum(bits, dst, s->label, sizeof(s->label)); |
| 458 | 458 | |
| 459 | | /* write sync bit after 2 * 5 + 1 words - 1 bit */ |
| 459 | /* write sync bit after 2 * MWPAL + 1 words - 1 bit */ |
| 460 | 460 | dst = expand_sync(bits, dst, 2 * MWPAL); |
| 461 | 461 | dst = expand_record(bits, dst, s->data, sizeof(s->data)); |
| 462 | 462 | dst = expand_cksum(bits, dst, s->data, sizeof(s->data)); |
| r26264 | r26265 | |
| 464 | 464 | /* fill MWPAL words of clock and 0 data bits */ |
| 465 | 465 | dst = expand_zeroes(bits, dst, MWPAL); |
| 466 | 466 | } else { |
| 467 | | /* write sync bit after 31 words - 1 bit */ |
| 468 | | dst = expand_sync(bits, 0, 31); |
| 467 | /* write sync bit after (MFROBL - MRPAL) words - 1 bit */ |
| 468 | dst = expand_sync(bits, 0, (MFROBL - MRPAL)); |
| 469 | 469 | dst = expand_record(bits, dst, s->header, sizeof(s->header)); |
| 470 | 470 | dst = expand_cksum(bits, dst, s->header, sizeof(s->header)); |
| 471 | 471 | |
| 472 | | /* write sync bit after 2 * 5 words - 1 bit */ |
| 472 | /* write sync bit after 2 * MWPAL words - 1 bit */ |
| 473 | 473 | dst = expand_sync(bits, dst, 2 * MWPAL); |
| 474 | 474 | dst = expand_record(bits, dst, s->label, sizeof(s->label)); |
| 475 | 475 | dst = expand_cksum(bits, dst, s->label, sizeof(s->label)); |
| 476 | 476 | |
| 477 | | /* write sync bit after 2 * 5 words - 1 bit */ |
| 477 | /* write sync bit after 2 * MWPAL words - 1 bit */ |
| 478 | 478 | dst = expand_sync(bits, dst, 2 * MWPAL); |
| 479 | 479 | dst = expand_record(bits, dst, s->data, sizeof(s->data)); |
| 480 | 480 | dst = expand_cksum(bits, dst, s->data, sizeof(s->data)); |
| r26264 | r26265 | |
| 484 | 484 | } |
| 485 | 485 | m_bits[m_page] = bits; |
| 486 | 486 | |
| 487 | | LOG_DRIVE((0,"[DHD%u] C/H/S:%03d/%d/%02d #%5d bits\n", m_unit, m_cylinder, m_head, m_sector, dst)); |
| 487 | LOG_DRIVE((0,"[DHD%u] CHS:%03d/%d/%02d #%5d bits\n", m_unit, m_cylinder, m_head, m_sector, dst)); |
| 488 | 488 | #if DIABLO_DEBUG |
| 489 | 489 | dump_record(s->pageno, 0, sizeof(s->pageno), "pageno", 0); |
| 490 | 490 | dump_record(s->header, 0, sizeof(s->header), "header", 0); |
| r26264 | r26265 | |
| 680 | 680 | int cksum_header, cksum_label, cksum_data; |
| 681 | 681 | |
| 682 | 682 | if (m_rdfirst >= 0) { |
| 683 | | LOG_DRIVE((0, "[DHD%u] RD CHS:%03d/%d/%02d bit#%-5d ... bit#%-5d\n", |
| 683 | LOG_DRIVE((0, "[DHD%u] READ CHS:%03d/%d/%02d bit#%d ... bit#%d\n", |
| 684 | 684 | m_unit, m_cylinder, m_head, m_sector, m_rdfirst, m_rdlast)); |
| 685 | 685 | } |
| 686 | 686 | m_rdfirst = -1; |
| r26264 | r26265 | |
| 701 | 701 | } |
| 702 | 702 | |
| 703 | 703 | if (m_wrfirst >= 0) { |
| 704 | | LOG_DRIVE((0, "[DHD%u] WR C/H/S:%03d/%d/%02d bit#%-5d ... bit#%-5d\n", |
| 704 | LOG_DRIVE((0, "[DHD%u] WRITE CHS:%03d/%d/%02d bit#%d ... bit#%d\n", |
| 705 | 705 | m_unit, m_cylinder, m_head, m_sector, m_wrfirst, m_wrlast)); |
| 706 | 706 | } |
| 707 | 707 | m_wrfirst = -1; |
| 708 | 708 | m_wrlast = -1; |
| 709 | 709 | |
| 710 | | if (m_page < 0 || m_page >= DIABLO_PAGES) { |
| 710 | if (m_page < 0 || m_page >= m_pages) { |
| 711 | 711 | LOG_DRIVE((0,"[DHD%u] page not set\n", m_unit)); |
| 712 | 712 | return; |
| 713 | 713 | } |
| r26264 | r26265 | |
| 724 | 724 | } |
| 725 | 725 | UINT32 *bits = m_bits[m_page]; |
| 726 | 726 | |
| 727 | | /* pointer to sector buffer */ |
| 727 | // pointer to sector buffer |
| 728 | 728 | s = reinterpret_cast<diablo_sector_t *>(m_cache[m_page]); |
| 729 | 729 | |
| 730 | | /* zap the sector first */ |
| 730 | // zap the sector first |
| 731 | 731 | memset(s, 0, sizeof(*s)); |
| 732 | 732 | |
| 733 | 733 | src = MFRRDL * 32; |
| 734 | | /* skip first words and garbage until 0 bits are coming in */ |
| 735 | | src = squeeze_unsync(bits, src, 40); |
| 736 | | /* sync on header preamble */ |
| 737 | | src = squeeze_sync(bits, src, 40); |
| 734 | src = squeeze_unsync(bits, src, 40); // skip first words and garbage until 0 bits are coming in |
| 735 | src = squeeze_sync(bits, src, 40); // sync on header preamble |
| 738 | 736 | LOG_DRIVE((0,"[DHD%u] header sync bit #%5d\n", m_unit, src)); |
| 739 | 737 | src = squeeze_record(bits, src, s->header, sizeof(s->header)); |
| 740 | 738 | src = squeeze_cksum(bits, src, &cksum_header); |
| r26264 | r26265 | |
| 742 | 740 | dump_record(s->header, 0, sizeof(s->header), "header", 0); |
| 743 | 741 | #endif |
| 744 | 742 | |
| 745 | | /* skip garbage until 0 bits are coming in */ |
| 746 | | src = squeeze_unsync(bits, src, 40); |
| 747 | | /* sync on label preamble */ |
| 748 | | src = squeeze_sync(bits, src, 40); |
| 743 | src = squeeze_unsync(bits, src, 40); // skip garbage until 0 bits are coming in |
| 744 | src = squeeze_sync(bits, src, 40); // sync on label preamble |
| 749 | 745 | LOG_DRIVE((0,"[DHD%u] label sync bit #%5d\n", m_unit, src)); |
| 750 | 746 | src = squeeze_record(bits, src, s->label, sizeof(s->label)); |
| 751 | 747 | src = squeeze_cksum(bits, src, &cksum_label); |
| r26264 | r26265 | |
| 753 | 749 | dump_record(s->label, 0, sizeof(s->label), "label", 0); |
| 754 | 750 | #endif |
| 755 | 751 | |
| 756 | | /* skip garbage until 0 bits are coming in */ |
| 757 | | src = squeeze_unsync(bits, src, 40); |
| 758 | | /* sync on data preamble */ |
| 759 | | src = squeeze_sync(bits, src, 40); |
| 752 | src = squeeze_unsync(bits, src, 40); // skip garbage until 0 bits are coming in |
| 753 | src = squeeze_sync(bits, src, 40); // sync on data preamble |
| 760 | 754 | LOG_DRIVE((0,"[DHD%u] data sync bit #%5d\n", m_unit, src)); |
| 761 | 755 | src = squeeze_record(bits, src, s->data, sizeof(s->data)); |
| 762 | 756 | src = squeeze_cksum(bits, src, &cksum_data); |
| r26264 | r26265 | |
| 764 | 758 | dump_record(s->data, 0, sizeof(s->data), "data", 1); |
| 765 | 759 | #endif |
| 766 | 760 | |
| 767 | | /* TODO: what is the cksum start value for the data record? */ |
| 761 | /* The checksum start value always seems to be 0521 */ |
| 768 | 762 | cksum_header ^= cksum(s->header, sizeof(s->header), 0521); |
| 769 | 763 | cksum_label ^= cksum(s->label, sizeof(s->label), 0521); |
| 770 | 764 | cksum_data ^= cksum(s->data, sizeof(s->data), 0521); |
| r26264 | r26265 | |
| 1122 | 1116 | if (-1 == m_wrfirst) |
| 1123 | 1117 | m_wrfirst = index; |
| 1124 | 1118 | |
| 1125 | | LOG_DRIVE((7,"[DHD%u] C/H/S:%d/%d/%d index #%d bit:%d\n", m_unit, m_cylinder, m_head, m_sector, index, wrdata)); |
| 1119 | LOG_DRIVE((9,"[DHD%u] CHS:%03d/%d/%02d index #%d bit:%d\n", m_unit, m_cylinder, m_head, m_sector, index, wrdata)); |
| 1126 | 1120 | |
| 1127 | 1121 | if (index < GUARD_ZONE_BITS) { |
| 1128 | 1122 | /* don't write in the guard zone (?) */ |
| r26264 | r26265 | |
| 1170 | 1164 | m_rdfirst = index; |
| 1171 | 1165 | |
| 1172 | 1166 | RDBIT(bits,index,bit); |
| 1173 | | LOG_DRIVE((7,"[DHD%u] C/H/S:%d/%d/%d index #%d bit:%d\n", m_unit, m_cylinder, m_head, m_sector, index, bit)); |
| 1167 | LOG_DRIVE((9,"[DHD%u] CHS:%03d/%d/%02d index #%d bit:%d\n", m_unit, m_cylinder, m_head, m_sector, index, bit)); |
| 1174 | 1168 | m_rdlast = index; |
| 1175 | 1169 | return bit; |
| 1176 | 1170 | } |
| r26264 | r26265 | |
| 1215 | 1209 | } else { |
| 1216 | 1210 | clk = 0; |
| 1217 | 1211 | } |
| 1218 | | LOG_DRIVE((7,"[DHD%u] C/H/S:%d/%d/%d index #%d clk:%d\n", m_unit, m_cylinder, m_head, m_sector, index, clk)); |
| 1212 | LOG_DRIVE((9,"[DHD%u] CHS:%03d/%d/%02d index #%d clk:%d\n", m_unit, m_cylinder, m_head, m_sector, index, clk)); |
| 1219 | 1213 | m_rdlast = index; |
| 1220 | 1214 | return clk ^ 1; |
| 1221 | 1215 | } |
| r26264 | r26265 | |
| 1226 | 1220 | */ |
| 1227 | 1221 | void diablo_hd_device::sector_mark_1() |
| 1228 | 1222 | { |
| 1229 | | LOG_DRIVE((9,"[DHD%u] C/H/S:%d/%d/%d sector_mark_0=1\n", m_unit, m_cylinder, m_head, m_sector)); |
| 1223 | LOG_DRIVE((9,"[DHD%u] CHS:%03d/%d/%02d sector_mark_0=1\n", m_unit, m_cylinder, m_head, m_sector)); |
| 1230 | 1224 | m_sector_mark_0 = 1; // deassert sector mark (set to 1) |
| 1231 | 1225 | } |
| 1232 | 1226 | |
| r26264 | r26265 | |
| 1240 | 1234 | */ |
| 1241 | 1235 | void diablo_hd_device::sector_mark_0() |
| 1242 | 1236 | { |
| 1243 | | LOG_DRIVE((9,"[DHD%u] C/H/S:%d/%d/%d sector_mark_0=0\n", m_unit, m_cylinder, m_head, m_sector)); |
| 1237 | LOG_DRIVE((9,"[DHD%u] CHS:%03d/%d/%02d sector_mark_0=0\n", m_unit, m_cylinder, m_head, m_sector)); |
| 1244 | 1238 | |
| 1245 | 1239 | squeeze_sector(); // squeeze previous sector bits, if it was written to |
| 1246 | 1240 | m_sector_mark_0 = 0; // assert sector mark (set to 0) |
| r26264 | r26265 | |
| 1262 | 1256 | m_packs = 1; // FIXME: get from configuration? |
| 1263 | 1257 | m_unit = strstr(m_image->tag(), "diablo0") ? 0 : 1; |
| 1264 | 1258 | |
| 1265 | | m_cache = auto_alloc_array(machine(), UINT8*, DIABLO_PAGES); |
| 1266 | | memset(m_cache, 0, sizeof(UINT8*) * DIABLO_PAGES); |
| 1267 | | m_bits = auto_alloc_array(machine(), UINT32*, DIABLO_PAGES); |
| 1268 | | memset(m_bits, 0, sizeof(UINT32*) * DIABLO_PAGES); |
| 1259 | m_cache = auto_alloc_array(machine(), UINT8*, m_pages); |
| 1260 | memset(m_cache, 0, sizeof(UINT8*) * m_pages); |
| 1261 | m_bits = auto_alloc_array(machine(), UINT32*, m_pages); |
| 1262 | memset(m_bits, 0, sizeof(UINT32*) * m_pages); |
| 1269 | 1263 | |
| 1270 | 1264 | m_timer = timer_alloc(1, 0); |
| 1271 | 1265 | } |