branches/alto2/src/emu/machine/diablo_hd.c
| r26134 | r26135 | |
| 65 | 65 | #if DIABLO_DEBUG |
| 66 | 66 | m_log_level(9), |
| 67 | 67 | #endif |
| 68 | | m_chd(*this, tag), |
| 69 | 68 | m_diablo31(true), |
| 70 | 69 | m_unit(0), |
| 71 | 70 | m_description(), |
| r26134 | r26135 | |
| 89 | 88 | m_sector(-1), |
| 90 | 89 | m_page(-1), |
| 91 | 90 | m_pages(DIABLO_PAGES), |
| 92 | | m_image(0), |
| 91 | m_cache(0), |
| 93 | 92 | m_bits(0), |
| 94 | 93 | m_rdfirst(-1), |
| 95 | 94 | m_rdlast(-1), |
| r26134 | r26135 | |
| 97 | 96 | m_wrlast(-1), |
| 98 | 97 | m_sector_callback(0), |
| 99 | 98 | m_sector_timer(0), |
| 100 | | m_drive(0) |
| 99 | m_image(0), |
| 100 | m_handle(0), |
| 101 | m_disk(0) |
| 101 | 102 | { |
| 102 | 103 | } |
| 103 | 104 | |
| 104 | 105 | diablo_hd_device::~diablo_hd_device() |
| 105 | 106 | { |
| 106 | 107 | for (int page = 0; page < m_pages; page++) { |
| 107 | | if (m_image && m_image[page]) |
| 108 | | global_free(m_image[page]); |
| 108 | if (m_cache && m_cache[page]) |
| 109 | global_free(m_cache[page]); |
| 109 | 110 | if (m_bits && m_bits[page]) |
| 110 | 111 | global_free(m_bits[page]); |
| 111 | 112 | } |
| 112 | | if (m_image) { |
| 113 | | global_free(m_image); |
| 114 | | m_image = 0; |
| 113 | if (m_cache) { |
| 114 | global_free(m_cache); |
| 115 | m_cache = 0; |
| 115 | 116 | } |
| 116 | 117 | if (m_bits) { |
| 117 | 118 | global_free(m_bits); |
| r26134 | r26135 | |
| 120 | 121 | } |
| 121 | 122 | |
| 122 | 123 | #if DIABLO_DEBUG |
| 123 | | void alto2_cpu_device::logprintf(int level, const char* format, ...) |
| 124 | void diablo_hd_device::logprintf(int level, const char* format, ...) |
| 124 | 125 | { |
| 125 | 126 | if (level > m_log_level) |
| 126 | 127 | return; |
| r26134 | r26135 | |
| 265 | 266 | void diablo_hd_device::read_sector() |
| 266 | 267 | { |
| 267 | 268 | /* If there's no drive, just reset the page number */ |
| 268 | | if (!m_drive) { |
| 269 | if (!m_image) { |
| 269 | 270 | m_page = -1; |
| 270 | 271 | return; |
| 271 | 272 | } |
| r26134 | r26135 | |
| 289 | 290 | LOG_DRIVE((9," DRIVE C/H/S:%d/%d/%d => page:%d\n", m_cylinder, m_head, m_sector, m_page)); |
| 290 | 291 | |
| 291 | 292 | // already have the sector image? |
| 292 | | if (m_image[m_page]) |
| 293 | if (m_cache[m_page]) |
| 293 | 294 | return; |
| 294 | 295 | |
| 295 | | hard_disk_file *file = m_drive->get_hard_disk_file(); |
| 296 | | if (!file) { |
| 297 | | LOG_DRIVE((0," no file for unit #%d\n", m_unit)); |
| 298 | | return; |
| 299 | | } |
| 300 | | |
| 301 | 296 | /* allocate a buffer for this page */ |
| 302 | | m_image[m_page] = global_alloc_array(UINT8, sizeof(diablo_sector_t)); |
| 297 | m_cache[m_page] = global_alloc_array(UINT8, sizeof(diablo_sector_t)); |
| 303 | 298 | /* and read the page from the hard_disk image */ |
| 304 | | if (!hard_disk_read(file, m_page, m_image[m_page])) { |
| 299 | if (!hard_disk_read(m_disk, m_page, m_cache[m_page])) { |
| 305 | 300 | LOG_DRIVE((0," read failed for #%d page #%d\n", m_unit, m_page)); |
| 306 | | global_free(m_image[m_page]); |
| 307 | | m_image[m_page] = 0; |
| 301 | global_free(m_cache[m_page]); |
| 302 | m_cache[m_page] = 0; |
| 308 | 303 | return; |
| 309 | 304 | } |
| 310 | 305 | } |
| r26134 | r26135 | |
| 420 | 415 | return m_bits[m_page]; |
| 421 | 416 | |
| 422 | 417 | /* allocate a sector buffer */ |
| 423 | | if (!m_image[m_page]) { |
| 418 | if (!m_cache[m_page]) { |
| 424 | 419 | LOG_DRIVE((0," no image for #%d page #%d\n", m_unit, m_page)); |
| 425 | 420 | return NULL; |
| 426 | 421 | } |
| 427 | | diablo_sector_t *s = reinterpret_cast<diablo_sector_t *>(m_image[m_page]); |
| 422 | diablo_sector_t *s = reinterpret_cast<diablo_sector_t *>(m_cache[m_page]); |
| 428 | 423 | |
| 429 | 424 | /* allocate a bits image */ |
| 430 | 425 | UINT32 *bits = reinterpret_cast<UINT32 *>(global_alloc_array(UINT32, 400)); |
| r26134 | r26135 | |
| 476 | 471 | } |
| 477 | 472 | |
| 478 | 473 | #if DIABLO_DEBUG |
| 479 | | void diablo_hd_device::drive_dump_ascii(UINT8 *src, size_t size) |
| 474 | void diablo_hd_device::dump_ascii(UINT8 *src, size_t size) |
| 480 | 475 | { |
| 481 | 476 | size_t offs; |
| 482 | 477 | LOG_DRIVE((0," [")); |
| r26134 | r26135 | |
| 505 | 500 | LOG_DRIVE((0," %06o", word)); |
| 506 | 501 | } else { |
| 507 | 502 | if (offs > 0) |
| 508 | | drive_dump_ascii(&src[offs-16], 16); |
| 503 | dump_ascii(&src[offs-16], 16); |
| 509 | 504 | LOG_DRIVE((0,"\t%05o: %06o", (addr + offs) / 2, word)); |
| 510 | 505 | } |
| 511 | 506 | } |
| 512 | 507 | if (offs % 16) { |
| 513 | | drive_dump_ascii(&src[offs - (offs % 16)], offs % 16); |
| 508 | dump_ascii(&src[offs - (offs % 16)], offs % 16); |
| 514 | 509 | } else { |
| 515 | | drive_dump_ascii(&src[offs-16], 16); |
| 510 | dump_ascii(&src[offs-16], 16); |
| 516 | 511 | } |
| 517 | 512 | if (cr) { |
| 518 | 513 | LOG_DRIVE((0,"\n")); |
| r26134 | r26135 | |
| 695 | 690 | return; |
| 696 | 691 | } |
| 697 | 692 | |
| 698 | | if (!m_image[m_page]) { |
| 693 | if (!m_cache[m_page]) { |
| 699 | 694 | LOG_DRIVE((0," no image for #%d: %d/%d/%d\n", m_unit, m_cylinder, m_head, m_sector)); |
| 700 | 695 | return; |
| 701 | 696 | } |
| r26134 | r26135 | |
| 708 | 703 | UINT32 *bits = m_bits[m_page]; |
| 709 | 704 | |
| 710 | 705 | /* pointer to sector buffer */ |
| 711 | | s = reinterpret_cast<diablo_sector_t *>(m_image[m_page]); |
| 706 | s = reinterpret_cast<diablo_sector_t *>(m_cache[m_page]); |
| 712 | 707 | |
| 713 | 708 | /* zap the sector first */ |
| 714 | 709 | memset(s, 0, sizeof(*s)); |
| r26134 | r26135 | |
| 762 | 757 | global_free(m_bits[m_page]); |
| 763 | 758 | m_bits[m_page] = 0; |
| 764 | 759 | |
| 765 | | hard_disk_file *file = m_drive->get_hard_disk_file(); |
| 766 | | if (!file) { |
| 767 | | LOG_DRIVE((0," no file for unit #%d\n", m_unit)); |
| 768 | | return; |
| 769 | | } |
| 770 | | |
| 771 | | if (!hard_disk_write(file, m_page, m_image[m_page])) { |
| 760 | if (!hard_disk_write(m_disk, m_page, m_cache[m_page])) { |
| 772 | 761 | LOG_DRIVE((0," write failed for #%d page #%d\n", m_unit, m_page)); |
| 773 | 762 | } |
| 774 | 763 | } |
| r26134 | r26135 | |
| 956 | 945 | printf("select unit:%d head:%d\n", unit, head); |
| 957 | 946 | } |
| 958 | 947 | |
| 959 | | if (m_drive) { |
| 948 | if (m_image) { |
| 960 | 949 | /* it is ready */ |
| 961 | 950 | m_ready_0 = 0; |
| 962 | 951 | /* and can take seek/read/write commands */ |
| r26134 | r26135 | |
| 1104 | 1093 | if (-1 == m_wrfirst) |
| 1105 | 1094 | m_wrfirst = index; |
| 1106 | 1095 | |
| 1107 | | LOG_DRIVE((7," write #%d %d/%d/%d bit #%d bit:%d\n", unit, m_cylinder, m_head, m_sector, index, wrdata)); |
| 1096 | LOG_DRIVE((7," write #%d %d/%d/%d bit #%d bit:%d\n", m_unit, m_cylinder, m_head, m_sector, index, wrdata)); |
| 1108 | 1097 | |
| 1109 | 1098 | if (index < GUARD_ZONE_BITS) { |
| 1110 | 1099 | /* don't write in the guard zone (?) */ |
| r26134 | r26135 | |
| 1151 | 1140 | m_rdfirst = index; |
| 1152 | 1141 | |
| 1153 | 1142 | RDBIT(bits,index,bit); |
| 1154 | | LOG_DRIVE((7," read #%d %d/%d/%d bit #%d:%d\n", unit, m_cylinder, m_head, m_sector, index, bit)); |
| 1143 | LOG_DRIVE((7," read #%d %d/%d/%d bit #%d:%d\n", m_unit, m_cylinder, m_head, m_sector, index, bit)); |
| 1155 | 1144 | m_rdlast = index; |
| 1156 | 1145 | return bit; |
| 1157 | 1146 | } |
| r26134 | r26135 | |
| 1193 | 1182 | } else { |
| 1194 | 1183 | RDBIT(bits,index,clk); |
| 1195 | 1184 | } |
| 1196 | | LOG_DRIVE((7, " read #%d %d/%d/%d clk #%d:%d\n", unit, m_cylinder, m_head, m_sector, index, clk)); |
| 1185 | LOG_DRIVE((7, " read #%d %d/%d/%d clk #%d:%d\n", m_unit, m_cylinder, m_head, m_sector, index, clk)); |
| 1197 | 1186 | m_rdlast = index; |
| 1198 | 1187 | return clk ^ 1; |
| 1199 | 1188 | } |
| r26134 | r26135 | |
| 1272 | 1261 | |
| 1273 | 1262 | void diablo_hd_device::device_start() |
| 1274 | 1263 | { |
| 1264 | m_image = static_cast<diablo_image_device *>(subdevice("drive")); |
| 1265 | LOG_DRIVE((0," m_image=%p\n", m_image)); |
| 1266 | |
| 1267 | m_diablo31 = true; // FIXME: get from m_handle meta data? |
| 1268 | m_packs = 1; // FIXME: get from configuration? |
| 1269 | |
| 1275 | 1270 | if (m_diablo31) { |
| 1276 | 1271 | snprintf(m_description, sizeof(m_description), "DIABLO31"); |
| 1277 | 1272 | m_rotation_time = DIABLO31_ROTATION_TIME; |
| r26134 | r26135 | |
| 1287 | 1282 | m_sector_mark_1_time = DIABLO44_SECTOR_MARK_PULSE_PRE; |
| 1288 | 1283 | m_bit_time = DIABLO44_BIT_TIME(1); |
| 1289 | 1284 | } |
| 1285 | |
| 1286 | m_cache = global_alloc_array(UINT8*, DIABLO_PAGES); |
| 1287 | m_bits = global_alloc_array(UINT32*, DIABLO_PAGES); |
| 1288 | |
| 1290 | 1289 | m_sector_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(diablo_hd_device::next_sector),this)); |
| 1291 | 1290 | m_sector_timer->adjust(m_sector_time - m_sector_mark_0_time, 0); |
| 1292 | 1291 | } |
| 1293 | 1292 | |
| 1294 | 1293 | void diablo_hd_device::device_reset() |
| 1295 | 1294 | { |
| 1295 | m_handle = m_image->get_chd_file(); |
| 1296 | m_disk = m_image->get_hard_disk_file(); |
| 1297 | LOG_DRIVE((0," m_handle=%p m_disk=%p\n", m_image, m_handle, m_disk)); |
| 1298 | |
| 1296 | 1299 | m_s_r_w_0 = 1; /* seek/read/write not ready */ |
| 1297 | 1300 | m_ready_0 = 1; /* drive is not ready */ |
| 1298 | 1301 | m_sector_mark_0 = 1; /* sector mark clear */ |
| r26134 | r26135 | |
| 1316 | 1319 | m_wrlast = -1; |
| 1317 | 1320 | m_rdfirst = -1; |
| 1318 | 1321 | m_rdlast = -1; |
| 1319 | | |
| 1320 | | m_drive = static_cast<diablo_image_device *>(subdevice("drive")); |
| 1321 | 1322 | } |
| 1322 | 1323 | |
| 1323 | 1324 | MACHINE_CONFIG_FRAGMENT( diablo_drive ) |
branches/alto2/src/emu/machine/diablo_hd.h
| r26134 | r26135 | |
| 12 | 12 | #include "emu.h" |
| 13 | 13 | #include "imagedev/diablo.h" |
| 14 | 14 | |
| 15 | | #define DIABLO_DEBUG 0 |
| 15 | #define DIABLO_DEBUG 1 |
| 16 | 16 | |
| 17 | #if DIABLO_DEBUG |
| 18 | #include "debug/debugcon.h" |
| 19 | #endif |
| 20 | |
| 17 | 21 | #define DIABLO_HD_0 "diablo0" |
| 18 | 22 | #define DIABLO_HD_1 "diablo1" |
| 19 | 23 | |
| r26134 | r26135 | |
| 61 | 65 | int m_log_level; |
| 62 | 66 | void logprintf(int level, const char* format, ...); |
| 63 | 67 | # define LOG_DRIVE(x) logprintf x |
| 68 | |
| 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); |
| 64 | 71 | #else |
| 65 | 72 | # define LOG_DRIVE(x) |
| 66 | 73 | #endif |
| 67 | 74 | |
| 68 | | required_device<diablo_image_device> m_chd; //!< image device |
| 69 | | |
| 70 | 75 | static const int DIABLO_UNIT_MAX = 2; //!< max number of drive units |
| 71 | 76 | static const int DIABLO_CYLINDERS = 203; //!< number of cylinders per drive |
| 72 | 77 | static const int DIABLO_CYLINDER_MASK = 0777; //!< bit maks for cylinder number (9 bits) |
| r26134 | r26135 | |
| 101 | 106 | int m_sector; //!< current sector number in track |
| 102 | 107 | int m_page; //!< current page |
| 103 | 108 | int m_pages; //!< total number of pages |
| 104 | | UINT8** m_image; //!< pages raw bytes |
| 109 | UINT8** m_cache; //!< pages raw bytes |
| 105 | 110 | UINT32** m_bits; //!< pages expanded to bits |
| 106 | 111 | int m_rdfirst; //!< set to first bit of a sector that is read from |
| 107 | 112 | int m_rdlast; //!< set to last bit of a sector that was read from |
| r26134 | r26135 | |
| 109 | 114 | int m_wrlast; //!< set to last bit of a sector that was written to |
| 110 | 115 | void (*m_sector_callback)(); //!< callback to call at the start of each sector |
| 111 | 116 | emu_timer* m_sector_timer; //!< sector timer |
| 112 | | diablo_image_device *m_drive; |
| 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 |
| 113 | 120 | |
| 114 | 121 | void read_sector(); //!< translate C/H/S to a page and read the sector |
| 115 | 122 | int cksum(UINT8 *src, size_t size, int start); |