trunk/src/emu/machine/hdc9234.c
r32111 | r32112 | |
4 | 4 | Standard Microsystems Corporation (SMC) |
5 | 5 | |
6 | 6 | This controller handles MFM and FM encoded floppy disks and hard disks. |
7 | | A variant, the SMC9224, is used in some DEC systems. |
| 7 | A variant, the HDC9224, is used in some DEC systems. |
8 | 8 | |
9 | 9 | The HDC9234 is used in the Myarc HFDC card for the TI99/4A. |
10 | 10 | |
r32111 | r32112 | |
14 | 14 | The HDC9234 controller is also referred to as the "Universal Disk Controller" (UDC) |
15 | 15 | by the data book |
16 | 16 | |
17 | | Michael Zapf, June 2014 |
| 17 | Michael Zapf, September 2014 |
18 | 18 | |
19 | 19 | ***************************************************************************/ |
20 | 20 | |
r32111 | r32112 | |
25 | 25 | #define TRACE_ACT 0 |
26 | 26 | #define TRACE_SHIFT 0 |
27 | 27 | #define TRACE_LIVE 0 |
28 | | #define TRACE_SYNC 0 |
| 28 | #define TRACE_RWSEC 0 |
| 29 | #define TRACE_LINES 0 |
| 30 | #define TRACE_AUXBUS 0 |
| 31 | #define TRACE_COMMAND 0 |
| 32 | #define TRACE_DELAY 0 |
| 33 | #define TRACE_WRITE 0 |
| 34 | #define TRACE_INDEX 0 |
| 35 | #define TRACE_INT 0 |
| 36 | #define TRACE_SETREG 0 |
| 37 | #define TRACE_DONE 0 |
| 38 | #define TRACE_VERIFY 0 |
29 | 39 | |
30 | 40 | #define UNRELIABLE_MEDIA 0 |
31 | 41 | |
32 | | // Seek complete? |
33 | | |
34 | 42 | // Untested: |
35 | 43 | // Multi-sector read |
36 | 44 | // Seek complete |
37 | 45 | // read sectors physical |
38 | | // |
39 | 46 | |
40 | 47 | /* |
41 | 48 | Register names of the HDC. The left part is the set of write registers, |
r32111 | r32112 | |
180 | 187 | OUT2_REDWRT = 0x40, |
181 | 188 | OUT2_STEPDIR = 0x20, |
182 | 189 | OUT2_STEPPULSE = 0x10, |
183 | | OUT2_HEADSEL3 = 0x08, |
184 | | OUT2_HEADSEL2 = 0x04, |
185 | | OUT2_HEADSEL1 = 0x02, |
186 | | OUT2_HEADSEL0 = 0x01 |
| 190 | OUT2_HEADSEL = 0x0f |
187 | 191 | }; |
188 | 192 | |
189 | 193 | enum |
r32111 | r32112 | |
191 | 195 | TYPE_AT = 0x00, |
192 | 196 | TYPE_HD = 0x01, |
193 | 197 | TYPE_FLOPPY8 = 0x02, |
194 | | TYPE_FLOPPY5 = 0x03 |
| 198 | TYPE_FLOPPY5 = 0x03, |
| 199 | DRIVE_TYPE = 0x03 |
195 | 200 | }; |
196 | 201 | |
197 | | #define DRIVE_TYPE 0x03 |
198 | | |
199 | 202 | /* |
200 | 203 | Timers |
201 | 204 | */ |
r32111 | r32112 | |
231 | 234 | static const int id_field[] = { CURRENT_CYLINDER, CURRENT_HEAD, CURRENT_SECTOR, CURRENT_SIZE, CURRENT_CRC1, CURRENT_CRC2 }; |
232 | 235 | |
233 | 236 | /* |
234 | | Pulse widths for stepping in ??s |
| 237 | Pulse widths for stepping in usec |
235 | 238 | */ |
236 | 239 | enum |
237 | 240 | { |
r32111 | r32112 | |
251 | 254 | |
252 | 255 | enum |
253 | 256 | { |
254 | | UNDEF, |
| 257 | UNDEF = 0x00, |
255 | 258 | IDLE, |
256 | 259 | DONE, |
| 260 | COMMAND_INIT, |
| 261 | REGISTER_ACCESS, |
| 262 | |
257 | 263 | STEP_ON, |
258 | 264 | STEP_OFF, |
259 | 265 | RESTORE_CHECK1, |
260 | 266 | RESTORE_CHECK2, |
261 | 267 | SEEK_COMPLETE, |
262 | 268 | |
263 | | READ_ID, |
| 269 | READ_ID = 0x40, |
264 | 270 | READ_ID1, |
| 271 | READ_ID_STEPON, |
| 272 | READ_ID_STEPOFF, |
265 | 273 | |
266 | | VERIFY, |
| 274 | VERIFY = 0x50, |
267 | 275 | VERIFY1, |
268 | 276 | VERIFY2, |
269 | 277 | VERIFY3, |
270 | 278 | |
271 | | DATA_TRANSFER, |
272 | | DATA_TRANSFER1, |
| 279 | DATA_TRANSFER = 0x60, |
| 280 | DATA_TRANSFER_READ, |
| 281 | DATA_TRANSFER_WRITE, |
273 | 282 | |
274 | 283 | // Live states |
| 284 | LIVE_STATES = 0x80, |
275 | 285 | SEARCH_IDAM, |
276 | 286 | SEARCH_IDAM_FAILED, |
277 | 287 | READ_TWO_MORE_A1_IDAM, |
r32111 | r32112 | |
280 | 290 | READ_TWO_MORE_A1_DAM, |
281 | 291 | SEARCH_DAM_FAILED, |
282 | 292 | READ_SECTOR_DATA, |
283 | | READ_SECTOR_DATA1 |
| 293 | READ_SECTOR_DATA1, |
| 294 | WRITE_DAM_AND_SECTOR, |
| 295 | WRITE_SEC_SKIP_GAP2, |
| 296 | WRITE_SEC_SKIP_GAP2_LOOP, |
| 297 | WRITE_SEC_BYTE, |
| 298 | WRITE_SEC_NEXT_BYTE |
284 | 299 | }; |
285 | 300 | |
| 301 | /* |
| 302 | State machine metastates. |
| 303 | */ |
286 | 304 | enum |
287 | 305 | { |
288 | | NOCMD, |
289 | | RESET, |
290 | | DESELECT, |
291 | | RESTORE, |
292 | | STEP, |
293 | | SELECT, |
294 | | SETREG, |
295 | | READSECL, |
296 | | READSECP |
| 306 | CONTINUE = 0, |
| 307 | WAIT, |
| 308 | NEXT, |
| 309 | ERROR, |
| 310 | SUCCESS |
297 | 311 | }; |
298 | 312 | |
299 | 313 | const hdc9234_device::cmddef hdc9234_device::s_command[] = |
300 | 314 | { |
301 | | { 0x00, 0xff, RESET, &hdc9234_device::device_reset }, |
302 | | { 0x01, 0xff, DESELECT, &hdc9234_device::drive_deselect }, |
303 | | { 0x02, 0xfe, RESTORE, &hdc9234_device::restore_drive }, |
304 | | { 0x04, 0xfc, STEP, &hdc9234_device::step_drive }, |
305 | | { 0x20, 0xe0, SELECT, &hdc9234_device::drive_select }, |
306 | | { 0x40, 0xf0, SETREG, &hdc9234_device::set_register_pointer }, |
307 | | { 0x58, 0xfe, READSECP, &hdc9234_device::read_sector_physical }, |
308 | | { 0x5c, 0xfc, READSECL, &hdc9234_device::read_sector_logical }, |
309 | | { 0, 0, 0, 0 } |
| 315 | { 0x00, 0xff, &hdc9234_device::device_reset }, |
| 316 | { 0x01, 0xff, &hdc9234_device::drive_deselect }, |
| 317 | { 0x02, 0xfe, &hdc9234_device::restore_drive }, |
| 318 | { 0x04, 0xfc, &hdc9234_device::step_drive }, |
| 319 | { 0x20, 0xe0, &hdc9234_device::drive_select }, |
| 320 | { 0x40, 0xf0, &hdc9234_device::set_register_pointer }, |
| 321 | { 0x58, 0xfe, &hdc9234_device::read_sectors }, |
| 322 | { 0x5c, 0xfc, &hdc9234_device::read_sectors }, |
| 323 | { 0xa0, 0xa0, &hdc9234_device::write_sector_logical }, |
| 324 | { 0, 0, 0 } |
310 | 325 | }; |
311 | 326 | |
312 | 327 | /* |
r32111 | r32112 | |
342 | 357 | } |
343 | 358 | |
344 | 359 | /* |
| 360 | Accessor functions for specific parameters. |
| 361 | */ |
| 362 | int hdc9234_device::desired_head() |
| 363 | { |
| 364 | return m_register_w[DESIRED_HEAD] & 0x0f; |
| 365 | } |
| 366 | |
| 367 | int hdc9234_device::desired_cylinder() |
| 368 | { |
| 369 | return (m_register_w[DESIRED_CYLINDER] & 0xff) | (m_register_w[DESIRED_HEAD] & 0x70); |
| 370 | } |
| 371 | |
| 372 | int hdc9234_device::desired_sector() |
| 373 | { |
| 374 | return m_register_w[DESIRED_SECTOR] & 0xff; |
| 375 | } |
| 376 | |
| 377 | int hdc9234_device::current_head() |
| 378 | { |
| 379 | return m_register_r[CURRENT_HEAD] & 0x0f; |
| 380 | } |
| 381 | |
| 382 | int hdc9234_device::current_cylinder() |
| 383 | { |
| 384 | return (m_register_r[CURRENT_CYLINDER] & 0xff) | (m_register_r[CURRENT_HEAD] & 0x70); |
| 385 | } |
| 386 | |
| 387 | int hdc9234_device::current_sector() |
| 388 | { |
| 389 | return m_register_r[CURRENT_SECTOR] & 0xff; |
| 390 | } |
| 391 | |
| 392 | UINT8 hdc9234_device::current_command() |
| 393 | { |
| 394 | return m_register_w[COMMAND]; |
| 395 | } |
| 396 | |
| 397 | /* |
345 | 398 | Set/clear INT |
346 | 399 | |
347 | 400 | Interupts are generated in the following occasions: |
r32111 | r32112 | |
379 | 432 | { |
380 | 433 | set_bits(m_register_r[INT_STATUS], ST_TERMCOD, false); // clear the previously set flags |
381 | 434 | m_register_r[INT_STATUS] |= flags; |
382 | | if (TRACE_ACT) logerror("%s: command %02x done, flags=%02x\n", tag(), m_command, flags); |
| 435 | if (TRACE_DONE) logerror("%s: command %02x done, flags=%02x\n", tag(), current_command(), flags); |
383 | 436 | } |
384 | 437 | else |
385 | 438 | { |
386 | | if (TRACE_ACT) logerror("%s: command %02x done\n", tag(), m_command); |
| 439 | if (TRACE_DONE) logerror("%s: command %02x done\n", tag(), current_command()); |
387 | 440 | } |
388 | 441 | |
389 | 442 | // [1], p. 6 |
390 | | if (TRACE_ACT) logerror("%s: Raise interrupt DONE\n", tag()); |
| 443 | if (TRACE_INT) logerror("%s: Raise interrupt DONE\n", tag()); |
391 | 444 | set_interrupt(ASSERT_LINE); |
392 | 445 | |
393 | | m_substate = IDLE; |
394 | | m_main_state = IDLE; |
395 | | m_command = NOCMD; |
| 446 | m_substate = UNDEF; |
| 447 | m_executing = false; |
396 | 448 | } |
397 | 449 | |
398 | 450 | /* |
r32111 | r32112 | |
405 | 457 | |
406 | 458 | void hdc9234_device::wait_time(emu_timer *tm, int microsec, int next_substate) |
407 | 459 | { |
408 | | if (TRACE_ACT) logerror("%s: Delay by %d microsec\n", tag(), microsec); |
| 460 | if (TRACE_DELAY) logerror("%s: Delay by %d microsec\n", tag(), microsec); |
409 | 461 | tm->adjust(attotime::from_usec(microsec)); |
410 | 462 | m_substate = next_substate; |
411 | 463 | } |
412 | 464 | |
413 | 465 | void hdc9234_device::wait_time(emu_timer *tm, attotime delay, int param) |
414 | 466 | { |
415 | | if (TRACE_ACT) logerror("%s: [%s] Delaying by %4.2f microsecs\n", tag(), ttsn().cstr(), delay.as_double()*1000000); |
| 467 | if (TRACE_DELAY) logerror("%s: [%s] Delaying by %4.2f microsecs\n", tag(), ttsn().cstr(), delay.as_double()*1000000); |
416 | 468 | tm->adjust(delay); |
417 | 469 | m_substate = param; |
418 | 470 | } |
419 | 471 | |
420 | | // =========================================================================== |
421 | | // States |
422 | | // =========================================================================== |
423 | | |
| 472 | // ================================================================== |
| 473 | // Common subroutines READ ID, VERIFY, DATA TRANSFER |
| 474 | // called by all sector access commands |
| 475 | // ================================================================== |
424 | 476 | /* |
425 | | DESELECT DRIVE |
426 | | done when no drive is in use |
| 477 | READ ID FIELD ([1] p. 9) |
| 478 | The controller |
| 479 | - scans for the next IDAM |
| 480 | - reads the ID field values into the CURRENT_HEAD/CYLINDER/SECTOR registers |
| 481 | - checks the CRC |
| 482 | - calculates the number of steps and the direction towards DESIRED_CYLINDER |
| 483 | (must have saved that value before!) |
| 484 | - steps to that location during OUTPUT2 times |
427 | 485 | */ |
428 | | void hdc9234_device::drive_deselect() |
| 486 | void hdc9234_device::read_id(int& cont, bool implied_seek) |
429 | 487 | { |
430 | | if (TRACE_ACT) logerror("%s: deselect command\n", tag()); |
431 | | set_bits(m_output1, OUT1_DRVSEL3|OUT1_DRVSEL2|OUT1_DRVSEL1|OUT1_DRVSEL0, false); |
432 | | sync_latches_out(); |
433 | | set_command_done(TC_SUCCESS); |
434 | | } |
| 488 | cont = CONTINUE; |
435 | 489 | |
436 | | /* |
437 | | "Restore" command |
438 | | // RESTORE DRIVE |
439 | | // bit 0: |
440 | | // 0 -> command ends after last seek pulse, |
441 | | // 1 -> command ends when the drive asserts the seek complete pin |
442 | | */ |
443 | | void hdc9234_device::restore_drive() |
444 | | { |
445 | | if (TRACE_ACT) logerror("%s: restore command %02x\n", tag(), m_command); |
446 | | |
447 | | m_seek_count = 0; |
448 | | m_substate = RESTORE_CHECK1; |
449 | | step_drive_continue(); |
450 | | } |
451 | | |
452 | | /* |
453 | | STEP IN / OUT 1 CYLINDER |
454 | | */ |
455 | | void hdc9234_device::step_drive() |
456 | | { |
457 | | if (TRACE_ACT) logerror("%s: step in/out command %02x\n", tag(), m_command); |
458 | | m_substate = STEP_ON; |
459 | | step_drive_continue(); |
460 | | } |
461 | | |
462 | | void hdc9234_device::step_drive_continue() |
463 | | { |
464 | | while (true) |
| 490 | while (cont==CONTINUE) |
465 | 491 | { |
466 | 492 | switch (m_substate) |
467 | 493 | { |
468 | | case DONE: |
469 | | set_command_done(TC_SUCCESS); |
470 | | return; |
471 | | |
472 | | case STEP_ON: |
473 | | if (TRACE_ACT) logerror("%s: substate STEP_ON\n", tag()); |
474 | | // STEPDIR = 0 -> towards TRK00 |
475 | | set_bits(m_output2, OUT2_STEPDIR, (m_command & 0x02)==0); |
476 | | // Raising edge (note that all signals must be inverted before leading them to the drive) |
477 | | set_bits(m_output2, OUT2_STEPPULSE, true); |
478 | | sync_latches_out(); |
479 | | wait_time(m_timer, pulse_width(), STEP_OFF); |
480 | | return; |
481 | | |
482 | | case STEP_OFF: |
483 | | if (TRACE_ACT) logerror("%s: substate STEP_OFF\n", tag()); |
484 | | set_bits(m_output2, OUT2_STEPPULSE, false); |
485 | | sync_latches_out(); |
486 | | if (m_main_state==RESTORE) |
487 | | { |
488 | | wait_time(m_timer, get_step_time(), RESTORE_CHECK1); |
489 | | } |
490 | | else |
491 | | { |
492 | | wait_time(m_timer, get_step_time(), DONE); |
493 | | } |
494 | | return; |
495 | | |
496 | | case RESTORE_CHECK1: |
497 | | if (TRACE_ACT) logerror("%s: substate RESTORE_CHECK; seek count = %d\n", tag(), m_seek_count); |
498 | | // If the drive is on track 0 or not ready (no drive), terminate the command |
499 | | if (on_track00()) |
500 | | { |
501 | | if (TRACE_ACT) logerror("%s: restore command TRK00 reached\n", tag()); |
502 | | if (m_command & 1) |
503 | | { |
504 | | // Buffered seek; wait for SEEK_COMPLETE |
505 | | wait_line(SEEK_COMPLETE); |
506 | | return; |
507 | | } |
508 | | else |
509 | | { |
510 | | m_substate = DONE; |
511 | | break; |
512 | | } |
513 | | } |
514 | | m_substate = RESTORE_CHECK2; |
515 | | break; |
516 | | |
517 | | case RESTORE_CHECK2: |
518 | | // Track 0 has not been reached yet |
519 | | if ((m_register_r[DRIVE_STATUS] & HDC_DS_READY)==0) |
520 | | { |
521 | | if (TRACE_ACT) logerror("%s: restore command: drive not ready\n", tag()); |
522 | | m_substate = DONE; |
523 | | break; |
524 | | } |
525 | | |
526 | | // Increase step count |
527 | | m_seek_count++; |
528 | | if (m_seek_count>=4096) |
529 | | { |
530 | | if (TRACE_ACT) logerror("%s: restore command: giving up\n", tag()); |
531 | | set_command_done(TC_VRFYERR); |
532 | | return; |
533 | | } |
534 | | |
535 | | m_substate = STEP_ON; |
536 | | break; |
537 | | |
538 | | case SEEK_COMPLETE: |
539 | | m_substate = RESTORE_CHECK2; |
540 | | break; |
541 | | } |
542 | | } |
543 | | } |
544 | | |
545 | | void hdc9234_device::drive_select() |
546 | | { |
547 | | int driveparm = m_command & 0x1f; |
548 | | |
549 | | // Command word |
550 | | // |
551 | | // 7 6 5 4 3 2 1 0 |
552 | | // +-----+-----+-----+-----+-----+-----+-----+-----+ |
553 | | // | 0 | 0 | 1 |Delay| Type | Drive | |
554 | | // +-----+-----+-----+-----+-----+-----+-----+-----+ |
555 | | // |
556 | | // [1] p.5: lower 4 bits of retry count register is put on OUTPUT1 |
557 | | |
558 | | m_output1 = (0x10 << (driveparm & 0x03)) | (m_register_w[RETRY_COUNT]&0x0f); |
559 | | // Bit 7 of OUTPUT2 is complement of Bit 7 of OUTPUT1 |
560 | | |
561 | | // The drive type is used to configure DMA burst mode ([1], p.12) |
562 | | // and to select the timing parameters |
563 | | m_selected_drive_type = (driveparm>>2) & 0x03; |
564 | | m_head_load_delay_enable = (driveparm>>4)&0x01; |
565 | | |
566 | | if (TRACE_ACT) logerror("%s: drive select command (%02x): head load delay=%d, type=%d, drive=%d\n", tag(), m_command, m_head_load_delay_enable, m_selected_drive_type, driveparm&3); |
567 | | |
568 | | // We need to store the type of the drive for the poll_drives command |
569 | | // to be able to correctly select the device (floppy or hard disk). |
570 | | // m_types[driveparm&0x03] = m_selected_drive_type; |
571 | | |
572 | | // Copy the DMA registers to registers CURRENT_HEAD, CURRENT_CYLINDER, |
573 | | // and CURRENT_IDENT. This is required during formatting ([1], p. 14) |
574 | | // as the format command reuses the registers for formatting parameters. |
575 | | m_register_r[CURRENT_HEAD] = m_register_r[DMA7_0]; |
576 | | m_register_r[CURRENT_CYLINDER] = m_register_r[DMA15_8]; |
577 | | m_register_r[CURRENT_IDENT] = m_register_r[DMA23_16]; |
578 | | |
579 | | // Copy the selected drive number to the chip status register |
580 | | m_register_r[CHIP_STATUS] = (m_register_r[CHIP_STATUS] & 0xfc) | (driveparm & 0x03); |
581 | | |
582 | | sync_latches_out(); |
583 | | set_command_done(TC_SUCCESS); |
584 | | } |
585 | | |
586 | | void hdc9234_device::set_register_pointer() |
587 | | { |
588 | | m_register_pointer = m_command & 0xf; |
589 | | if (TRACE_ACT) logerror("%s: setregptr command; start reg=%d\n", tag(), m_register_pointer); |
590 | | // Spec does not say anything about the effect of setting an |
591 | | // invalid value (only "care should be taken") |
592 | | if (m_register_pointer > 10) |
593 | | { |
594 | | logerror("%s: set register pointer: Invalid register number: %d. Setting to 10.\n", tag(), m_register_pointer); |
595 | | m_register_pointer = 10; |
596 | | } |
597 | | set_command_done(TC_SUCCESS); |
598 | | } |
599 | | |
600 | | /* |
601 | | Read the desired sector. For multiple sectors, read the sectors in |
602 | | the order as they appear on the track. The command terminates with the |
603 | | next index pulse or when all sectors have been read before. |
604 | | Opcodes: |
605 | | 58 = transfer disabled |
606 | | 59 = transfer enabled |
607 | | */ |
608 | | void hdc9234_device::read_sector_physical() |
609 | | { |
610 | | if (TRACE_ACT) logerror("%s: read sectors physical command %02x\n", tag(), m_command); |
611 | | if (TRACE_ACT) logerror("%s: sector: C=%d H=%d S=%d\n", tag(), m_register_w[DESIRED_CYLINDER], m_register_w[DESIRED_HEAD],m_register_w[DESIRED_SECTOR]); |
612 | | |
613 | | m_retry_save = m_register_w[RETRY_COUNT]; |
614 | | m_multi_sector = (m_register_w[SECTOR_COUNT] != 1); |
615 | | |
616 | | m_substate = READ_ID; |
617 | | read_sector_continue(); |
618 | | } |
619 | | |
620 | | /* |
621 | | Read the desired sector. For multiple sectors, read the sectors in |
622 | | ascending order (sector n, n+1, n+2 ...). |
623 | | Opcodes: |
624 | | 5c = implied seek / transfer disabled |
625 | | 5d = implied seek / transfer enabled |
626 | | 5e = no implied seek / transfer disabled |
627 | | 5f = no implied seek / transfer enabled |
628 | | */ |
629 | | void hdc9234_device::read_sector_logical() |
630 | | { |
631 | | if (TRACE_ACT) logerror("%s: read sectors logical command %02x\n", tag(), m_command); |
632 | | if (TRACE_ACT) logerror("%s: sector: C=%d H=%d S=%d\n", tag(), m_register_w[DESIRED_CYLINDER], m_register_w[DESIRED_HEAD],m_register_w[DESIRED_SECTOR]); |
633 | | |
634 | | m_retry_save = m_register_w[RETRY_COUNT]; |
635 | | m_multi_sector = (m_register_w[SECTOR_COUNT] != 1); |
636 | | |
637 | | m_substate = READ_ID; |
638 | | read_sector_continue(); |
639 | | } |
640 | | |
641 | | void hdc9234_device::read_sector_continue() |
642 | | { |
643 | | while (true) |
644 | | { |
645 | | switch (m_substate) |
646 | | { |
647 | | /* |
648 | | READ ID FIELD ([1] p. 9) |
649 | | The controller |
650 | | - scans for the next IDAM |
651 | | - reads the ID field values into the CURRENT_HEAD/CYLINDER/SECTOR registers |
652 | | - checks the CRC |
653 | | - calculates the number of steps and the direction towards DESIRED_CYLINDER |
654 | | (must have saved that value before!) |
655 | | - steps to that location during OUTPUT2 times |
656 | | |
657 | | When an error occurs, the COMMAND_TERMINATION bits are set to 01 |
658 | | */ |
659 | 494 | case READ_ID: |
660 | 495 | // Implied seek: Enter the READ_ID subprogram. |
661 | 496 | if (TRACE_ACT) logerror("%s: substate READ_ID\n", tag()); |
662 | 497 | |
663 | | // Bit 1 = 0: enable implied seek (i.e. the controller will seek the desired track) |
664 | | // Bit 1 = 1: disable implied seek (controller will stay on the current track) |
665 | | // Also, do implied seek for read physical |
666 | | if ((m_command & 0x0e)==0x0e) |
667 | | m_substate = VERIFY; |
668 | | else |
669 | | m_substate = READ_ID1; |
| 498 | m_substate = implied_seek? READ_ID1 : VERIFY; |
670 | 499 | |
671 | 500 | // First step: Search the next IDAM, and if found, read the |
672 | 501 | // ID values into the registers |
| 502 | // Depending on the implied seek flag, continue with the read_id, |
| 503 | // else switch to verify. |
673 | 504 | m_live_state.bit_count_total = 0; |
674 | 505 | live_start(SEARCH_IDAM); |
675 | | return; |
| 506 | cont = WAIT; |
| 507 | break; |
676 | 508 | |
677 | 509 | case READ_ID1: |
678 | 510 | // If an error occured (no IDAM found), terminate the command |
679 | 511 | if ((m_register_r[CHIP_STATUS] & CS_SYNCERR) != 0) |
680 | 512 | { |
681 | | if (TRACE_ACT) logerror("%s: READ_ID: No IDAM found\n", tag()); |
682 | | set_command_done(TC_RDIDERR); |
683 | | return; |
| 513 | logerror("%s: READ_ID failed to find an IDAM\n", tag()); |
| 514 | cont = ERROR; |
| 515 | break; |
684 | 516 | } |
685 | 517 | |
686 | 518 | if (TRACE_ACT) |
687 | 519 | { |
688 | 520 | logerror("%s: substate READ_ID1\n", tag()); |
689 | | logerror("%s: DESIRED_CYL = %d; CURRENT_CYL = %d\n", tag(), m_register_w[DESIRED_CYLINDER], m_register_r[CURRENT_CYLINDER]); |
| 521 | logerror("%s: DESIRED_CYL = %d; CURRENT_CYL = %d\n", tag(), desired_cylinder(), current_cylinder()); |
690 | 522 | } |
691 | 523 | |
692 | 524 | // The CRC has been updated automatically with each read_one_bit during the live_run. |
r32111 | r32112 | |
695 | 527 | { |
696 | 528 | logerror("%s: CRC error in sector header\n", tag()); |
697 | 529 | set_bits(m_register_r[CHIP_STATUS], CS_CRCERR, true); |
698 | | set_command_done(TC_RDIDERR); |
699 | | return; |
| 530 | cont = ERROR; |
| 531 | break; |
700 | 532 | } |
701 | 533 | |
702 | 534 | // Calculate the direction and number of step pulses |
703 | 535 | // positive -> towards inner cylinders |
704 | 536 | // negative -> towards outer cylinders |
705 | 537 | // zero -> we're already there |
706 | | m_track_delta = m_register_w[DESIRED_CYLINDER] - m_register_r[CURRENT_CYLINDER]; |
707 | | m_substate = STEP_ON; |
| 538 | m_track_delta = desired_cylinder() - current_cylinder(); |
| 539 | m_substate = READ_ID_STEPON; |
708 | 540 | break; |
709 | 541 | |
710 | | case STEP_ON: |
| 542 | case READ_ID_STEPON: |
711 | 543 | // Any more steps left? |
712 | 544 | if (m_track_delta == 0) |
713 | 545 | { |
714 | 546 | m_substate = VERIFY; |
| 547 | cont = NEXT; |
715 | 548 | break; |
716 | 549 | } |
717 | 550 | |
r32111 | r32112 | |
719 | 552 | // STEPDIR = 0 -> towards TRK00 |
720 | 553 | set_bits(m_output2, OUT2_STEPDIR, (m_track_delta>0)); |
721 | 554 | set_bits(m_output2, OUT2_STEPPULSE, true); |
722 | | sync_latches_out(); |
723 | | wait_time(m_timer, pulse_width(), STEP_OFF); |
724 | | return; |
| 555 | auxbus_out(); |
| 556 | wait_time(m_timer, pulse_width(), READ_ID_STEPOFF); |
| 557 | cont = WAIT; |
| 558 | break; |
725 | 559 | |
726 | | case STEP_OFF: |
| 560 | case READ_ID_STEPOFF: |
727 | 561 | if (TRACE_ACT) logerror("%s: substate STEP_OFF\n", tag()); |
728 | 562 | set_bits(m_output2, OUT2_STEPPULSE, false); |
729 | | sync_latches_out(); |
| 563 | auxbus_out(); |
730 | 564 | m_track_delta += (m_track_delta<0)? 1 : -1; |
731 | 565 | // Return to STEP_ON, check whether there are more steps |
732 | | wait_time(m_timer, get_step_time(), STEP_ON); |
733 | | return; |
| 566 | wait_time(m_timer, step_time(), READ_ID_STEPON); |
| 567 | cont = WAIT; |
| 568 | break; |
734 | 569 | |
| 570 | default: |
| 571 | if (TRACE_ACT) logerror("%s: unknown substate %d in read_id\n", tag(), m_substate); |
| 572 | cont = ERROR; |
| 573 | } |
| 574 | } |
| 575 | |
| 576 | // When an error occurs, the COMMAND_TERMINATION bits are set to 01 |
| 577 | if (cont == ERROR) set_command_done(TC_RDIDERR); |
| 578 | } |
| 579 | |
| 580 | /* |
| 581 | VERIFY ([1] p. 10) |
| 582 | The controller |
| 583 | - continues to read the next ID field until the current values match the |
| 584 | contents of the DESIRED_HEAD/CYLINDER/SECTOR registers |
| 585 | - checks the CRC |
| 586 | */ |
| 587 | void hdc9234_device::verify(int& cont, bool verify_all) |
| 588 | { |
| 589 | cont = CONTINUE; |
| 590 | |
| 591 | while (cont==CONTINUE) |
| 592 | { |
| 593 | switch (m_substate) |
| 594 | { |
735 | 595 | case VERIFY: |
736 | | /* |
737 | | VERIFY ([1] p. 10) |
738 | | The controller |
739 | | - continues to read the next ID field until the current values match the |
740 | | contents of the DESIRED_HEAD/CYLINDER/SECTOR registers |
741 | | - checks the CRC |
742 | | |
743 | | When an error occurs, the COMMAND_TERMINATION bits are set to 10 |
744 | | */ |
745 | 596 | // After seeking (or immediately when implied seek has been disabled), |
746 | 597 | // find the desired sector. |
747 | 598 | |
r32111 | r32112 | |
751 | 602 | // (This test is only relevant when we did not have a seek phase before) |
752 | 603 | if ((m_register_r[CHIP_STATUS] & CS_SYNCERR) != 0) |
753 | 604 | { |
754 | | if (TRACE_ACT) logerror("%s: READ_ID: No IDAM found\n", tag()); |
755 | | set_command_done(TC_VRFYERR); |
756 | | return; |
| 605 | logerror("%s: VERIFY failed to find an IDAM\n", tag()); |
| 606 | cont = ERROR; |
| 607 | break; |
757 | 608 | } |
758 | 609 | |
759 | 610 | // Count from 0 again |
r32111 | r32112 | |
763 | 614 | |
764 | 615 | case VERIFY1: |
765 | 616 | // Check whether we are already there |
766 | | if ((m_register_w[DESIRED_CYLINDER] == m_register_r[CURRENT_CYLINDER]) |
767 | | && (m_register_w[DESIRED_HEAD] == m_register_r[CURRENT_HEAD]) |
768 | | && (m_register_w[DESIRED_SECTOR] == m_register_r[CURRENT_SECTOR])) |
| 617 | if (desired_cylinder() == current_cylinder() |
| 618 | && desired_head() == current_head() |
| 619 | && desired_sector() == current_sector()) |
769 | 620 | { |
770 | | if (TRACE_ACT) logerror("%s: Found the desired sector\n", tag()); |
| 621 | if (TRACE_ACT) logerror("%s: Found the desired sector CHS=(%d,%d,%d)\n", tag(), |
| 622 | desired_cylinder(), |
| 623 | desired_head(), |
| 624 | desired_sector()); |
771 | 625 | m_substate = DATA_TRANSFER; |
| 626 | cont = NEXT; |
772 | 627 | } |
773 | 628 | else |
774 | 629 | { |
775 | | if (TRACE_ACT) logerror("%s: Current CHS=(%d,%d,%d), desired CHS=(%d,%d,%d).\n", tag(), |
776 | | m_register_r[CURRENT_CYLINDER] & 0xff, |
777 | | m_register_r[CURRENT_HEAD] & 0xff, |
778 | | m_register_r[CURRENT_SECTOR] & 0xff, |
779 | | m_register_w[DESIRED_CYLINDER] & 0xff, |
780 | | m_register_w[DESIRED_HEAD] & 0xff, |
781 | | m_register_w[DESIRED_SECTOR] & 0xff); |
| 630 | if (TRACE_VERIFY) logerror("%s: Current CHS=(%d,%d,%d), desired CHS=(%d,%d,%d).\n", tag(), |
| 631 | current_cylinder(), |
| 632 | current_head(), |
| 633 | current_sector(), |
| 634 | desired_cylinder(), |
| 635 | desired_head(), |
| 636 | desired_sector()); |
782 | 637 | m_substate = VERIFY2; |
783 | 638 | } |
784 | 639 | break; |
r32111 | r32112 | |
787 | 642 | // Search the next ID |
788 | 643 | m_substate = VERIFY3; |
789 | 644 | live_start(SEARCH_IDAM); |
790 | | return; |
| 645 | cont = WAIT; |
| 646 | break; |
791 | 647 | |
792 | 648 | case VERIFY3: |
793 | 649 | if ((m_register_r[CHIP_STATUS] & CS_SYNCERR) != 0) |
794 | 650 | { |
795 | | if (TRACE_ACT) logerror("%s: VERIFY: Desired sector not found\n", tag()); |
| 651 | logerror("%s: VERIFY failed to find sector CHS=(%d,%d,%d)\n", tag(), |
| 652 | desired_cylinder(), |
| 653 | desired_head(), |
| 654 | desired_sector()); |
796 | 655 | // live_run has set the sync error; clear it |
797 | 656 | set_bits(m_register_r[CHIP_STATUS], CS_SYNCERR, false); |
798 | 657 | // and set the compare error bit instead |
799 | 658 | set_bits(m_register_r[CHIP_STATUS], CS_COMPERR, true); |
800 | | set_command_done(TC_VRFYERR); |
801 | | return; |
| 659 | cont = ERROR; |
| 660 | break; |
802 | 661 | } |
803 | 662 | |
804 | 663 | // Continue with the loop |
805 | | if ((m_command & 0x0c)==0x0c) |
| 664 | if (verify_all) |
806 | 665 | { |
807 | 666 | // this is for the logical sector reading |
808 | 667 | m_substate = VERIFY1; |
r32111 | r32112 | |
813 | 672 | // do not verify the next ID field |
814 | 673 | m_substate = DATA_TRANSFER; |
815 | 674 | m_wait_for_index = true; |
| 675 | cont = NEXT; |
816 | 676 | } |
817 | 677 | break; |
818 | 678 | |
| 679 | default: |
| 680 | logerror("%s: unknown substate %d in verify\n", tag(), m_substate); |
| 681 | cont = ERROR; |
| 682 | } |
| 683 | } |
| 684 | |
| 685 | // When an error occurs, the COMMAND_TERMINATION bits are set to 10 |
| 686 | if (cont == ERROR) set_command_done(TC_VRFYERR); |
| 687 | } |
| 688 | |
| 689 | /* |
| 690 | DATA TRANSFER ([1], p. 10) |
| 691 | only during READ/WRITE PHYSICAL/LOGICAL |
| 692 | The controller |
| 693 | - scans for the next DAM |
| 694 | - initiates a DMA request and waits for ACK from the system processor |
| 695 | - transfers the contents of the current sector into memory via DMA (read) or |
| 696 | via DMA to the sector (write) |
| 697 | */ |
| 698 | void hdc9234_device::data_transfer(int& cont) |
| 699 | { |
| 700 | cont = CONTINUE; |
| 701 | |
| 702 | while (cont==CONTINUE) |
| 703 | { |
| 704 | switch (m_substate) |
| 705 | { |
819 | 706 | case DATA_TRANSFER: |
820 | | /* |
821 | | DATA TRANSFER ([1], p. 10) |
822 | | only during READ PHYSICAL/LOGICAL |
823 | | The controller |
824 | | - scans for the next DAM |
825 | | - initiates a DMA request and waits for ACK from the system processor |
826 | | - transfers the contents of the current sector into memory via DMA |
827 | | |
828 | | When an error occurs, the COMMAND_TERMINATION bits are set to 11 |
829 | | */ |
830 | 707 | if (TRACE_ACT) logerror("%s: substate DATA_TRANSFER\n", tag()); |
831 | 708 | |
832 | | // Search the DAM and transfer the contents via DMA |
833 | | m_substate = DATA_TRANSFER1; |
834 | | |
835 | 709 | // Count from 0 again |
836 | 710 | m_live_state.bit_count_total = 0; |
837 | 711 | |
838 | | dma_address_out(); |
839 | | live_start(SEARCH_DAM); |
840 | | return; |
| 712 | if (m_transfer_enabled) dma_address_out(); |
841 | 713 | |
842 | | case DATA_TRANSFER1: |
| 714 | if (TRACE_RWSEC) logerror("%s: %s sector CHS=(%d,%d,%d)\n", tag(), m_write? "write" : "read", |
| 715 | desired_cylinder(), |
| 716 | desired_head(), |
| 717 | desired_sector()); |
| 718 | |
| 719 | if (m_write) |
| 720 | { |
| 721 | m_substate = DATA_TRANSFER_WRITE; |
| 722 | live_start(WRITE_DAM_AND_SECTOR); |
| 723 | } |
| 724 | else |
| 725 | { |
| 726 | m_substate = DATA_TRANSFER_READ; |
| 727 | live_start(SEARCH_DAM); |
| 728 | } |
| 729 | |
| 730 | cont = WAIT; |
| 731 | break; |
| 732 | |
| 733 | case DATA_TRANSFER_READ: |
843 | 734 | // OK, sector has been read. |
844 | 735 | // Check CRC |
845 | 736 | if (m_live_state.crc != 0) |
846 | 737 | { |
847 | | if (TRACE_ACT) logerror("%s: CRC error in sector data\n", tag()); |
848 | 738 | // Set Retry Required flag |
849 | 739 | set_bits(m_register_r[CHIP_STATUS], CS_RETREQ, true); |
850 | 740 | |
851 | 741 | // Decrement the retry register (one's complemented value; 0000 = 15) |
852 | 742 | int retry = 15-((m_register_w[RETRY_COUNT] >> 4)&0x0f); |
853 | | if (TRACE_ACT) logerror("%s: CRC error; retries = %d\n", tag(), retry); |
| 743 | |
| 744 | logerror("%s: DATA TRANSFER got CRC error in sector data, retries = %d\n", tag(), retry); |
854 | 745 | m_register_w[RETRY_COUNT] = (m_register_w[RETRY_COUNT] & 0x0f) | ((15-(retry-1))<<4); |
855 | 746 | |
856 | 747 | if (retry == 0) |
857 | 748 | { |
858 | 749 | if (TRACE_ACT) logerror("%s: CRC error; no retries left\n", tag()); |
859 | 750 | set_bits(m_register_r[CHIP_STATUS], CS_CRCERR, true); |
860 | | set_command_done(TC_DATAERR); |
861 | | return; |
| 751 | cont = ERROR; |
862 | 752 | } |
863 | 753 | else |
864 | 754 | { |
r32111 | r32112 | |
869 | 759 | // We'll rely on the properly written software as well. |
870 | 760 | m_live_state.bit_count_total = 0; |
871 | 761 | m_substate = VERIFY2; |
| 762 | cont = NEXT; |
872 | 763 | } |
873 | 764 | } |
874 | 765 | else |
r32111 | r32112 | |
882 | 773 | (m_register_w[DMA15_8] & 0xff) << 8 | |
883 | 774 | (m_register_w[DMA7_0] & 0xff); |
884 | 775 | |
885 | | dma_address = (dma_address + get_sector_size()) & 0xffffff; |
| 776 | dma_address = (dma_address + calc_sector_size()) & 0xffffff; |
886 | 777 | |
887 | 778 | m_register_w[DMA23_16] = m_register_r[DMA23_16] = (dma_address & 0xff0000) >> 16; |
888 | 779 | m_register_w[DMA15_8] = m_register_r[DMA15_8] = (dma_address & 0x00ff00) >> 16; |
r32111 | r32112 | |
904 | 795 | // What happens when we exceed the highest sector number |
905 | 796 | // in the track? We have to assume that this is possible |
906 | 797 | // and that in this case the VERIFY routine fails. |
907 | | m_register_w[DESIRED_SECTOR] = (m_register_w[DESIRED_SECTOR] + 1) & 0xff; |
| 798 | m_register_w[DESIRED_SECTOR] = (desired_sector() + 1) & 0xff; |
908 | 799 | m_substate = VERIFY1; |
| 800 | cont = NEXT; |
909 | 801 | m_live_state.bit_count_total = 0; |
910 | 802 | } |
911 | 803 | else |
| 804 | cont = SUCCESS; |
| 805 | } |
| 806 | break; |
| 807 | |
| 808 | case DATA_TRANSFER_WRITE: |
| 809 | if (TRACE_ACT) logerror("%s: Sector successfully written\n", tag()); |
| 810 | |
| 811 | // Update the DMA registers for multi-sector operations |
| 812 | if (m_multi_sector) |
| 813 | { |
| 814 | int dma_address = (m_register_w[DMA23_16] & 0xff) << 16 | |
| 815 | (m_register_w[DMA15_8] & 0xff) << 8 | |
| 816 | (m_register_w[DMA7_0] & 0xff); |
| 817 | |
| 818 | dma_address = (dma_address + calc_sector_size()) & 0xffffff; |
| 819 | |
| 820 | m_register_w[DMA23_16] = m_register_r[DMA23_16] = (dma_address & 0xff0000) >> 16; |
| 821 | m_register_w[DMA15_8] = m_register_r[DMA15_8] = (dma_address & 0x00ff00) >> 16; |
| 822 | m_register_w[DMA7_0] = m_register_r[DMA7_0] = (dma_address & 0x0000ff) >> 16; |
| 823 | } |
| 824 | |
| 825 | // Decrement the count |
| 826 | m_register_w[SECTOR_COUNT] = (m_register_w[SECTOR_COUNT]-1) & 0xff; |
| 827 | if (m_register_w[SECTOR_COUNT] != 0 && !m_stop_after_index) |
| 828 | { |
| 829 | m_register_w[DESIRED_SECTOR] = (desired_sector() + 1) & 0xff; |
| 830 | m_substate = VERIFY1; |
| 831 | cont = NEXT; |
| 832 | m_live_state.bit_count_total = 0; |
| 833 | } |
| 834 | else |
| 835 | cont = SUCCESS; |
| 836 | |
| 837 | break; |
| 838 | |
| 839 | default: |
| 840 | logerror("%s: unknown substate %d in data_transfer\n", tag(), m_substate); |
| 841 | cont = ERROR; |
| 842 | } |
| 843 | } |
| 844 | |
| 845 | if (cont==SUCCESS) set_command_done(TC_SUCCESS); |
| 846 | |
| 847 | // When an error occurs, the COMMAND_TERMINATION bits are set to 11 |
| 848 | if (cont==ERROR) set_command_done(TC_DATAERR); |
| 849 | } |
| 850 | |
| 851 | // =========================================================================== |
| 852 | // Commands |
| 853 | // =========================================================================== |
| 854 | |
| 855 | /* |
| 856 | DESELECT DRIVE |
| 857 | done when no drive is in use |
| 858 | */ |
| 859 | void hdc9234_device::drive_deselect() |
| 860 | { |
| 861 | if (TRACE_COMMAND) logerror("%s: DESELECT command\n", tag()); |
| 862 | set_bits(m_output1, OUT1_DRVSEL3|OUT1_DRVSEL2|OUT1_DRVSEL1|OUT1_DRVSEL0, false); |
| 863 | auxbus_out(); |
| 864 | set_command_done(TC_SUCCESS); |
| 865 | } |
| 866 | |
| 867 | /* |
| 868 | Step on / off; used by RESTORE and STEP IN/OUT |
| 869 | */ |
| 870 | void hdc9234_device::step_on(bool towards00, int next) |
| 871 | { |
| 872 | if (TRACE_ACT) logerror("%s: substate STEP_ON\n", tag()); |
| 873 | |
| 874 | // STEPDIR = 0 -> towards TRK00 |
| 875 | set_bits(m_output2, OUT2_STEPDIR, !towards00); |
| 876 | |
| 877 | // Raising edge (note that all signals must be inverted before leading them to the drive) |
| 878 | set_bits(m_output2, OUT2_STEPPULSE, true); |
| 879 | auxbus_out(); |
| 880 | wait_time(m_timer, pulse_width(), next); |
| 881 | } |
| 882 | |
| 883 | void hdc9234_device::step_off(int next) |
| 884 | { |
| 885 | if (TRACE_ACT) logerror("%s: substate STEP_OFF\n", tag()); |
| 886 | set_bits(m_output2, OUT2_STEPPULSE, false); |
| 887 | auxbus_out(); |
| 888 | wait_time(m_timer, step_time(), next); |
| 889 | } |
| 890 | |
| 891 | /* |
| 892 | // RESTORE DRIVE |
| 893 | // bit 0: |
| 894 | // 0 -> command ends after last seek pulse, |
| 895 | // 1 -> command ends when the drive asserts the seek complete pin |
| 896 | */ |
| 897 | void hdc9234_device::restore_drive() |
| 898 | { |
| 899 | int cont = CONTINUE; |
| 900 | |
| 901 | // The substate is set to UNDEF when the command is started; |
| 902 | // when we return here after a pause, the substate is set to some other value |
| 903 | // In wd_fdc this is solved using two methods <command>_start and <command>_continue |
| 904 | if (m_substate == UNDEF) |
| 905 | { |
| 906 | if (TRACE_COMMAND) logerror("%s: RESTORE command %02x\n", tag(), current_command()); |
| 907 | m_seek_count = 0; |
| 908 | m_substate = RESTORE_CHECK1; |
| 909 | } |
| 910 | |
| 911 | while (cont==CONTINUE) |
| 912 | { |
| 913 | switch (m_substate) |
| 914 | { |
| 915 | case RESTORE_CHECK1: |
| 916 | if (TRACE_ACT) logerror("%s: substate RESTORE_CHECK; seek count = %d\n", tag(), m_seek_count); |
| 917 | // If the drive is on track 0 or not ready (no drive), terminate the command |
| 918 | if (on_track00()) |
| 919 | { |
| 920 | if (TRACE_ACT) logerror("%s: restore command TRK00 reached\n", tag()); |
| 921 | if (current_command() & 1) |
912 | 922 | { |
913 | | set_command_done(TC_SUCCESS); |
914 | | return; |
| 923 | // Buffered seek; wait for SEEK_COMPLETE |
| 924 | wait_line(SEEK_COMPLETE); |
| 925 | cont = WAIT; |
915 | 926 | } |
| 927 | else |
| 928 | { |
| 929 | cont = SUCCESS; |
| 930 | } |
| 931 | break; |
916 | 932 | } |
| 933 | m_substate = RESTORE_CHECK2; |
917 | 934 | break; |
918 | 935 | |
| 936 | case RESTORE_CHECK2: |
| 937 | // Track 0 has not been reached yet |
| 938 | if ((m_register_r[DRIVE_STATUS] & HDC_DS_READY)==0) |
| 939 | { |
| 940 | if (TRACE_COMMAND) logerror("%s: restore command: drive not ready\n", tag()); |
| 941 | // Does not look like a success, but this takes into account |
| 942 | // that if a drive is not connected we do not want an error message |
| 943 | cont = SUCCESS; |
| 944 | break; |
| 945 | } |
| 946 | |
| 947 | // Increase step count |
| 948 | m_seek_count++; |
| 949 | if (m_seek_count>=4096) |
| 950 | { |
| 951 | logerror("%s: restore command: failed to reach track 00\n", tag()); |
| 952 | set_command_done(TC_VRFYERR); |
| 953 | cont = ERROR; |
| 954 | break; |
| 955 | } |
| 956 | |
| 957 | step_on(true, STEP_OFF); |
| 958 | cont = WAIT; |
| 959 | break; |
| 960 | |
| 961 | case STEP_OFF: |
| 962 | step_off(RESTORE_CHECK1); |
| 963 | cont = WAIT; |
| 964 | break; |
| 965 | |
| 966 | case SEEK_COMPLETE: |
| 967 | cont = SUCCESS; |
| 968 | break; |
| 969 | } |
| 970 | } |
| 971 | if (cont==SUCCESS) set_command_done(TC_SUCCESS); |
| 972 | } |
| 973 | |
| 974 | /* |
| 975 | STEP IN / OUT 1 CYLINDER |
| 976 | */ |
| 977 | void hdc9234_device::step_drive() |
| 978 | { |
| 979 | int cont = CONTINUE; |
| 980 | |
| 981 | if (m_substate == UNDEF) |
| 982 | { |
| 983 | if (TRACE_COMMAND) logerror("%s: STEP IN/OUT command %02x\n", tag(), current_command()); |
| 984 | m_substate = STEP_ON; |
| 985 | } |
| 986 | |
| 987 | while (cont==CONTINUE) |
| 988 | { |
| 989 | switch (m_substate) |
| 990 | { |
| 991 | case STEP_ON: |
| 992 | step_on((current_command() & 0x02)!=0, STEP_OFF); |
| 993 | cont = WAIT; |
| 994 | break; |
| 995 | case STEP_OFF: |
| 996 | step_off(DONE); |
| 997 | cont = WAIT; |
| 998 | break; |
| 999 | case DONE: |
| 1000 | cont = SUCCESS; |
| 1001 | break; |
| 1002 | } |
| 1003 | } |
| 1004 | if (cont==SUCCESS) set_command_done(TC_SUCCESS); |
| 1005 | } |
| 1006 | |
| 1007 | /* |
| 1008 | DRIVE SELECT |
| 1009 | |
| 1010 | Command word |
| 1011 | |
| 1012 | 7 6 5 4 3 2 1 0 |
| 1013 | +-----+-----+-----+-----+-----+-----+-----+-----+ |
| 1014 | | 0 | 0 | 1 |Delay| Type | Drive | |
| 1015 | +-----+-----+-----+-----+-----+-----+-----+-----+ |
| 1016 | |
| 1017 | [1] p.5: lower 4 bits of RETRY COUNT register (user programmable output) is put on OUTPUT1 |
| 1018 | |
| 1019 | The HFDC controller board uses the user programmable output to |
| 1020 | select one of four floppy disk drives with Drive set to 00. |
| 1021 | Drive codes 01, 10, and 11 remain for three hard disk drives. |
| 1022 | */ |
| 1023 | |
| 1024 | void hdc9234_device::drive_select() |
| 1025 | { |
| 1026 | int driveparm = current_command() & 0x1f; |
| 1027 | |
| 1028 | m_output1 = (0x10 << (driveparm & 0x03)) | (m_register_w[RETRY_COUNT]&0x0f); |
| 1029 | |
| 1030 | // The drive type is used to configure DMA burst mode ([1], p.12) |
| 1031 | // and to select the timing parameters |
| 1032 | m_selected_drive_type = (driveparm>>2) & 0x03; |
| 1033 | m_head_load_delay_enable = (driveparm>>4)&0x01; |
| 1034 | |
| 1035 | if (TRACE_COMMAND) logerror("%s: DRIVE SELECT command (%02x): head load delay=%d, type=%d, drive=%d, pout=%02x\n", tag(), current_command(), m_head_load_delay_enable, m_selected_drive_type, driveparm&3, m_register_w[RETRY_COUNT]&0x0f); |
| 1036 | |
| 1037 | if (m_substate != UNDEF) |
| 1038 | { |
| 1039 | logerror("%s: substate = %d\n", tag(), m_substate); |
| 1040 | } |
| 1041 | |
| 1042 | // Copy the DMA registers to registers CURRENT_HEAD, CURRENT_CYLINDER, |
| 1043 | // and CURRENT_IDENT. This is required during formatting ([1], p. 14) |
| 1044 | // as the format command reuses the registers for formatting parameters. |
| 1045 | m_register_r[CURRENT_HEAD] = m_register_r[DMA7_0]; |
| 1046 | m_register_r[CURRENT_CYLINDER] = m_register_r[DMA15_8]; |
| 1047 | m_register_r[CURRENT_IDENT] = m_register_r[DMA23_16]; |
| 1048 | |
| 1049 | // Copy the selected drive number to the chip status register |
| 1050 | m_register_r[CHIP_STATUS] = (m_register_r[CHIP_STATUS] & 0xfc) | (driveparm & 0x03); |
| 1051 | |
| 1052 | auxbus_out(); |
| 1053 | set_command_done(TC_SUCCESS); |
| 1054 | } |
| 1055 | |
| 1056 | /* |
| 1057 | SET REGISTER POINTER |
| 1058 | |
| 1059 | Sets the pointer to the read and write registers. On read or write accesses, |
| 1060 | the pointer is increased until it reaches the DATA register. |
| 1061 | */ |
| 1062 | void hdc9234_device::set_register_pointer() |
| 1063 | { |
| 1064 | m_register_pointer = current_command() & 0xf; |
| 1065 | if (TRACE_SETREG) logerror("%s: SET REGISTER POINTER command; start reg=%d\n", tag(), m_register_pointer); |
| 1066 | // The specification does not say anything about the effect of setting an |
| 1067 | // invalid value (only "care should be taken") |
| 1068 | if (m_register_pointer > 10) |
| 1069 | { |
| 1070 | logerror("%s: set register pointer: Invalid register number: %d. Setting to 10.\n", tag(), m_register_pointer); |
| 1071 | m_register_pointer = 10; |
| 1072 | } |
| 1073 | set_command_done(TC_SUCCESS); |
| 1074 | } |
| 1075 | |
| 1076 | /* |
| 1077 | READ SECTORS PHYSICAL / LOGICAL |
| 1078 | Read the desired sectors, maximum count being specified in SECTOR_COUNT |
| 1079 | |
| 1080 | Physical: |
| 1081 | For multiple sectors, read the sectors in the order as they appear on the track. |
| 1082 | The command terminates with the next index pulse or when all sectors have been read before. |
| 1083 | Implied seek (locate the correct track) is always true. |
| 1084 | Opcodes: |
| 1085 | 58 = transfer disabled |
| 1086 | 59 = transfer enabled |
| 1087 | |
| 1088 | Logical: |
| 1089 | For multiple sectors, read the sectors in ascending order of their sector field (sector n, n+1, n+2 ...). |
| 1090 | Opcodes: |
| 1091 | 5c = implied seek / transfer disabled |
| 1092 | 5d = implied seek / transfer enabled |
| 1093 | 5e = no implied seek / transfer disabled |
| 1094 | 5f = no implied seek / transfer enabled |
| 1095 | */ |
| 1096 | void hdc9234_device::read_sectors() |
| 1097 | { |
| 1098 | bool logical = (current_command() & 0xfc)==0x5c; |
| 1099 | |
| 1100 | if (m_substate == UNDEF) |
| 1101 | { |
| 1102 | // Command init |
| 1103 | if (TRACE_COMMAND) logerror("%s: READ SECTORS %s command %02x, CHS=(%d,%d,%d)\n", tag(), logical? "LOGICAL": "PHYSICAL", current_command(), desired_cylinder(), desired_head(), desired_sector()); |
| 1104 | m_retry_save = m_register_w[RETRY_COUNT]; |
| 1105 | m_multi_sector = (m_register_w[SECTOR_COUNT] != 1); |
| 1106 | |
| 1107 | m_substate = READ_ID; |
| 1108 | } |
| 1109 | |
| 1110 | int cont = NEXT; |
| 1111 | bool implied_seek = !logical || (current_command() & 0x02)==0; |
| 1112 | m_transfer_enabled = (current_command()&0x01)!=0; |
| 1113 | |
| 1114 | while (cont == NEXT) |
| 1115 | { |
| 1116 | switch (m_substate & 0xf0) |
| 1117 | { |
| 1118 | case READ_ID: |
| 1119 | read_id(cont, implied_seek); |
| 1120 | break; |
| 1121 | case VERIFY: |
| 1122 | verify(cont, logical); // for physical, only verify the first sector |
| 1123 | break; |
| 1124 | case DATA_TRANSFER: |
| 1125 | m_write = false; |
| 1126 | data_transfer(cont); |
| 1127 | break; |
919 | 1128 | default: |
920 | | if (TRACE_ACT) logerror("%s: unknown substate %d in read_sector\n", tag(), m_substate); |
| 1129 | logerror("%s: unknown substate %d in read_sectors\n", tag(), m_substate); |
| 1130 | cont = ERROR; |
921 | 1131 | } |
922 | 1132 | } |
923 | 1133 | } |
924 | 1134 | |
925 | | void hdc9234_device::general_continue() |
| 1135 | /* |
| 1136 | Write the desired sector. For multiple sectors, write the sectors in |
| 1137 | ascending order (sector n, n+1, n+2 ...). |
| 1138 | Opcodes: A0 - BF, E0 - FF |
| 1139 | |
| 1140 | [ 1 ] [ ImplSeek ] [ 1 ] [ NormalData ] [ ReducedWC ] [ PreC2 ] [ PreC1 ] [ PreC0 ] |
| 1141 | */ |
| 1142 | void hdc9234_device::write_sector_logical() |
926 | 1143 | { |
| 1144 | if (m_substate == UNDEF) |
| 1145 | { |
| 1146 | if (TRACE_COMMAND) logerror("%s: write sectors logical command %02x, CHS=(%d,%d,%d)\n", tag(), current_command(), desired_cylinder(), desired_head(), desired_sector()); |
| 1147 | m_multi_sector = (m_register_w[SECTOR_COUNT] != 1); |
| 1148 | m_substate = READ_ID; |
| 1149 | } |
| 1150 | |
| 1151 | int cont = NEXT; |
| 1152 | |
| 1153 | m_write = true; |
| 1154 | m_transfer_enabled = true; |
| 1155 | |
| 1156 | m_deleted = (current_command() & 0x10)==0; |
| 1157 | m_precompensation = (current_command() & 0x07); |
| 1158 | m_reduced_write_current = (current_command() & 0x08)!=0; |
| 1159 | |
| 1160 | while (cont == NEXT) |
| 1161 | { |
| 1162 | // We're dispatching by substate value range |
| 1163 | switch (m_substate & 0xf0) |
| 1164 | { |
| 1165 | case READ_ID: |
| 1166 | read_id(cont, (current_command() & 0x02)==0); |
| 1167 | break; |
| 1168 | case VERIFY: |
| 1169 | verify(cont, true); |
| 1170 | break; |
| 1171 | case DATA_TRANSFER: |
| 1172 | data_transfer(cont); |
| 1173 | break; |
| 1174 | default: |
| 1175 | logerror("%s: unknown substate %d in write_sector_logical\n", tag(), m_substate); |
| 1176 | cont = ERROR; |
| 1177 | } |
| 1178 | } |
| 1179 | } |
| 1180 | |
| 1181 | void hdc9234_device::reenter_command_processing() |
| 1182 | { |
927 | 1183 | // Do we have a live run on the track? |
928 | 1184 | if (m_live_state.state != IDLE) |
929 | 1185 | { |
r32111 | r32112 | |
934 | 1190 | |
935 | 1191 | // We're here when there is no live_run anymore |
936 | 1192 | // Where were we last time? |
937 | | switch (m_main_state) |
938 | | { |
939 | | case IDLE: |
940 | | break; |
941 | | case RESTORE: |
942 | | case STEP: |
943 | | step_drive_continue(); |
944 | | break; |
945 | | case SELECT: |
946 | | // During drive_select there is no need to continue |
947 | | break; |
948 | | case READSECL: |
949 | | read_sector_continue(); |
950 | | break; |
951 | | default: |
952 | | logerror("%s: [%s] general_continue on unknown main_state %d\n", tag(), ttsn().cstr(), m_main_state); |
953 | | break; |
954 | | } |
| 1193 | // Take care not to restart commands because of the index callback |
| 1194 | if (m_executing && m_substate != UNDEF) (this->*m_command)(); |
955 | 1195 | } |
956 | 1196 | |
957 | 1197 | // =========================================================================== |
r32111 | r32112 | |
959 | 1199 | /* |
960 | 1200 | Delivers the step time (in microseconds) minus the pulse width |
961 | 1201 | */ |
962 | | int hdc9234_device::get_step_time() |
| 1202 | int hdc9234_device::step_time() |
963 | 1203 | { |
964 | 1204 | int time = 0; |
965 | 1205 | int index = m_register_w[MODE] & MO_STEPRATE; |
r32111 | r32112 | |
998 | 1238 | /* |
999 | 1239 | Delivers the sector size |
1000 | 1240 | */ |
1001 | | int hdc9234_device::get_sector_size() |
| 1241 | int hdc9234_device::calc_sector_size() |
1002 | 1242 | { |
1003 | 1243 | return 128 << (m_register_r[CURRENT_SIZE] & 3); |
1004 | 1244 | } |
r32111 | r32112 | |
1047 | 1287 | m_live_state.shift_reg = 0; |
1048 | 1288 | m_live_state.crc = 0xffff; |
1049 | 1289 | m_live_state.bit_counter = 0; |
| 1290 | m_live_state.byte_counter = 0; |
1050 | 1291 | m_live_state.data_separator_phase = false; |
1051 | 1292 | m_live_state.data_reg = 0; |
1052 | 1293 | |
r32111 | r32112 | |
1200 | 1441 | } |
1201 | 1442 | |
1202 | 1443 | // Repeat until we have collected 16 bits |
1203 | | if(m_live_state.bit_counter & 15) break; |
| 1444 | if (m_live_state.bit_counter & 15) break; |
1204 | 1445 | |
1205 | 1446 | // So we now got 16 bits. Fill this value into the next slot. We expect two more A1 values. |
1206 | 1447 | slot = m_live_state.bit_counter >> 4; |
r32111 | r32112 | |
1218 | 1459 | } |
1219 | 1460 | |
1220 | 1461 | if (TRACE_LIVE) logerror("%s: [%s] Found data value %02X\n", tag(),tts(m_live_state.time).cstr(), m_live_state.data_reg); |
1221 | | if (m_live_state.data_reg != 0xfe) |
| 1462 | |
| 1463 | // Check for ident field (fe, ff, fd, fc) |
| 1464 | if ((m_live_state.data_reg & 0xfc) != 0xfc) |
1222 | 1465 | { |
1223 | 1466 | // This may happen when we accidentally locked onto the DAM. Look for the next IDAM. |
1224 | | if (TRACE_LIVE) logerror("%s: Missing FE data after A1A1A1\n", tag()); |
| 1467 | if (TRACE_LIVE) logerror("%s: Missing ident data after A1A1A1\n", tag()); |
1225 | 1468 | m_live_state.state = SEARCH_IDAM; |
1226 | 1469 | break; |
1227 | 1470 | } |
1228 | 1471 | |
| 1472 | m_register_r[CURRENT_IDENT] = m_live_state.data_reg; |
| 1473 | |
1229 | 1474 | // We're here after we got the three A1 and FE |
1230 | 1475 | m_live_state.bit_counter = 0; |
1231 | 1476 | m_live_state.state = READ_ID_FIELDS_INTO_REGS; |
r32111 | r32112 | |
1261 | 1506 | } |
1262 | 1507 | break; |
1263 | 1508 | |
| 1509 | // ================================================== |
| 1510 | // Live states for sector read operations |
| 1511 | // ================================================== |
| 1512 | |
1264 | 1513 | case SEARCH_DAM: |
1265 | 1514 | if (TRACE_LIVE && m_last_live_state != SEARCH_DAM) |
1266 | 1515 | logerror("%s: [%s] SEARCH_DAM\n", tag(),tts(m_live_state.time).cstr()); |
r32111 | r32112 | |
1384 | 1633 | break; |
1385 | 1634 | } |
1386 | 1635 | case SEARCH_DAM_FAILED: |
1387 | | if (TRACE_LIVE) logerror("%s: SEARCH_DAM failed\n", tag()); |
| 1636 | logerror("%s: SEARCH_DAM failed\n", tag()); |
1388 | 1637 | m_live_state.state = IDLE; |
1389 | 1638 | return; |
1390 | 1639 | |
r32111 | r32112 | |
1398 | 1647 | return; |
1399 | 1648 | |
1400 | 1649 | // Request bus release at the first bit of each byte (floppy; [1], fig 5 and 6) |
1401 | | if ((m_command & 0x01)!=0) // transfer enabled |
| 1650 | if (m_transfer_enabled) |
1402 | 1651 | { |
1403 | 1652 | if ((m_live_state.bit_counter & 15)== 1) |
1404 | 1653 | { |
r32111 | r32112 | |
1413 | 1662 | if (TRACE_LIVE) logerror("%s: [%s] Found data value %02X, CRC=%04x\n", tag(),tts(m_live_state.time).cstr(), m_live_state.data_reg, m_live_state.crc); |
1414 | 1663 | int slot = (m_live_state.bit_counter >> 4)-1; |
1415 | 1664 | |
1416 | | if (slot < get_sector_size()) |
| 1665 | if (slot < calc_sector_size()) |
1417 | 1666 | { |
1418 | 1667 | // Sector data |
1419 | 1668 | wait_for_realtime(READ_SECTOR_DATA1); |
1420 | 1669 | return; |
1421 | 1670 | } |
1422 | | else if (slot < get_sector_size()+2) |
| 1671 | else if (slot < calc_sector_size()+2) |
1423 | 1672 | { |
1424 | 1673 | // CRC |
1425 | | if (slot == get_sector_size()+1) |
| 1674 | if (slot == calc_sector_size()+1) |
1426 | 1675 | { |
1427 | 1676 | if (TRACE_LIVE) logerror("%s: [%s] Sector read completed\n", tag(),tts(m_live_state.time).cstr()); |
1428 | 1677 | wait_for_realtime(IDLE); |
r32111 | r32112 | |
1446 | 1695 | return; |
1447 | 1696 | } |
1448 | 1697 | |
1449 | | if ((m_command & 0x01)!=0) // transfer enabled |
| 1698 | if (m_transfer_enabled) |
1450 | 1699 | { |
1451 | 1700 | m_out_dip(ASSERT_LINE); |
1452 | 1701 | m_out_dma(0, m_live_state.data_reg, 0xff); |
r32111 | r32112 | |
1459 | 1708 | checkpoint(); |
1460 | 1709 | break; |
1461 | 1710 | |
| 1711 | // ================================================== |
| 1712 | // Live states for sector write operations |
| 1713 | // ================================================== |
| 1714 | |
| 1715 | case WRITE_DAM_AND_SECTOR: |
| 1716 | // 1. Wait for 22*16 cells (MFM) or 11*16 cells (FM) [704 usec, Gap 2] |
| 1717 | // 2. Write 12 (MFM) or 6 (FM) zeros |
| 1718 | // 3. Write 3*A1 sync plus the ident byte (MFM) or FB (FM) or F8 (deleted) |
| 1719 | // 4. Write the sector content and calculate the CRC on the fly |
| 1720 | // 5. Write the CRC bytes |
| 1721 | |
| 1722 | if (TRACE_LIVE && m_last_live_state != WRITE_DAM_AND_SECTOR) |
| 1723 | logerror("%s: [%s] WRITE_DAM_AND_SECTOR\n", tag(), tts(m_live_state.time).cstr()); |
| 1724 | m_last_live_state = m_live_state.state; |
| 1725 | m_live_state.state = WRITE_SEC_SKIP_GAP2; |
| 1726 | break; |
| 1727 | |
| 1728 | case WRITE_SEC_SKIP_GAP2: |
| 1729 | // The pause is implemented by doing dummy reads on the floppy |
| 1730 | if (read_one_bit(limit)) |
| 1731 | return; |
| 1732 | |
| 1733 | // Repeat until we have collected 16 bits |
| 1734 | if (m_live_state.bit_counter & 15) break; |
| 1735 | |
| 1736 | wait_for_realtime(WRITE_SEC_SKIP_GAP2_LOOP); |
| 1737 | return; |
| 1738 | |
| 1739 | case WRITE_SEC_SKIP_GAP2_LOOP: |
| 1740 | m_live_state.state = WRITE_SEC_SKIP_GAP2; |
| 1741 | m_live_state.byte_counter++; |
| 1742 | m_live_state.bit_counter = 0; |
| 1743 | if (TRACE_LIVE) logerror("%s: [%s] %d bytes skipped\n", tag(), tts(m_live_state.time).cstr(), m_live_state.byte_counter); |
| 1744 | |
| 1745 | if (m_live_state.byte_counter == (fm_mode()? 11 : 22)) |
| 1746 | { |
| 1747 | if (TRACE_LIVE) logerror("%s: [%s] Skipped over gap2\n", tag(), tts(m_live_state.time).cstr()); |
| 1748 | if (TRACE_WRITE) logerror("%s: [%s] Write 00\n", tag(), tts(m_live_state.time).cstr()); |
| 1749 | // Start writing 0x00 |
| 1750 | m_live_state.state = WRITE_SEC_BYTE; |
| 1751 | m_live_state.bit_counter = 16; |
| 1752 | m_live_state.byte_counter = 0; |
| 1753 | // The bit context is actually not used in FM |
| 1754 | m_live_state.last_data_bit = m_live_state.data_reg & 1; |
| 1755 | m_pll.start_writing(m_live_state.time); |
| 1756 | encode_byte(0x00); |
| 1757 | |
| 1758 | // Clear the overrun/underrun flag |
| 1759 | set_bits(m_register_r[INT_STATUS], ST_OVRUN, false); |
| 1760 | } |
| 1761 | break; |
| 1762 | |
| 1763 | case WRITE_SEC_BYTE: |
| 1764 | if (write_one_bit(limit)) |
| 1765 | return; |
| 1766 | |
| 1767 | if (m_live_state.bit_counter == 0) |
| 1768 | { |
| 1769 | // All bits written; get the next byte into the shift register |
| 1770 | wait_for_realtime(WRITE_SEC_NEXT_BYTE); |
| 1771 | return; |
| 1772 | } |
| 1773 | break; |
| 1774 | |
| 1775 | case WRITE_SEC_NEXT_BYTE: |
| 1776 | { |
| 1777 | if ((m_register_r[INT_STATUS] & ST_OVRUN)!=0) |
| 1778 | { |
| 1779 | if (TRACE_LIVE) logerror("%s: No DMA ACK - buffer underrun\n", tag()); |
| 1780 | set_bits(m_register_r[INT_STATUS], TC_DATAERR, true); |
| 1781 | m_pll.stop_writing(m_floppy, m_live_state.time); |
| 1782 | m_live_state.state = IDLE; |
| 1783 | return; |
| 1784 | } |
| 1785 | |
| 1786 | int sector_start = fm_mode()? 7 : 16; |
| 1787 | int sync0_length = fm_mode()? 6 : 12; |
| 1788 | int sector_end = sector_start + calc_sector_size(); |
| 1789 | |
| 1790 | m_live_state.state = WRITE_SEC_BYTE; |
| 1791 | m_live_state.bit_counter = 16; |
| 1792 | m_live_state.byte_counter++; |
| 1793 | |
| 1794 | // Write all sync zeros |
| 1795 | if (m_live_state.byte_counter < sync0_length) |
| 1796 | { |
| 1797 | if (TRACE_WRITE) logerror("%s: [%s] Write 00\n", tag(), tts(m_live_state.time).cstr()); |
| 1798 | encode_byte(0x00); |
| 1799 | checkpoint(); |
| 1800 | break; |
| 1801 | } |
| 1802 | |
| 1803 | // Write the DAM (MFM) |
| 1804 | if (m_live_state.byte_counter >= sync0_length && m_live_state.byte_counter < sector_start-1) |
| 1805 | { |
| 1806 | if (TRACE_WRITE) logerror("%s: [%s] Write A1\n", tag(), tts(m_live_state.time).cstr()); |
| 1807 | // only applies for MFM since sector_start-1 = 6 = sync0_length |
| 1808 | encode_raw(0x4489); |
| 1809 | checkpoint(); |
| 1810 | break; |
| 1811 | } |
| 1812 | |
| 1813 | // Ident byte (and DAM for FM) |
| 1814 | if (m_live_state.byte_counter == sector_start-1) |
| 1815 | { |
| 1816 | if (TRACE_WRITE) logerror("%s: [%s] Write ident\n", tag(), tts(m_live_state.time).cstr()); |
| 1817 | if (fm_mode()) |
| 1818 | { |
| 1819 | // Init the CRC for the DAM and sector |
| 1820 | m_live_state.crc = 0xffff; |
| 1821 | |
| 1822 | // 1111 0101 0110 1010 = F8 deleted |
| 1823 | // 1111 0101 0110 1111 = FB normal |
| 1824 | encode_raw(m_deleted? 0xf56a : 0xf56f); |
| 1825 | } |
| 1826 | else |
| 1827 | { |
| 1828 | // Init the CRC for the ident byte and sector |
| 1829 | m_live_state.crc = 0xcdb4; // value for 3*A1 |
| 1830 | encode_byte(m_deleted? 0xf8 : 0xfb); |
| 1831 | } |
| 1832 | |
| 1833 | // Set the over/underrun flag and hope that it will be cleared before we return here |
| 1834 | set_bits(m_register_r[INT_STATUS], ST_OVRUN, true); |
| 1835 | m_out_dmarq(ASSERT_LINE); |
| 1836 | |
| 1837 | checkpoint(); |
| 1838 | break; |
| 1839 | } |
| 1840 | |
| 1841 | // Write the sector contents |
| 1842 | if (m_live_state.byte_counter >= sector_start && m_live_state.byte_counter < sector_end) |
| 1843 | { |
| 1844 | // Read byte via DMA |
| 1845 | m_out_dip(ASSERT_LINE); |
| 1846 | UINT8 data = m_in_dma(0, 0xff); |
| 1847 | if (TRACE_WRITE) logerror("%s: [%s] Write %02x\n", tag(), tts(m_live_state.time).cstr(), data); |
| 1848 | encode_byte(data); |
| 1849 | m_out_dip(CLEAR_LINE); |
| 1850 | m_out_dmarq(CLEAR_LINE); |
| 1851 | |
| 1852 | if (m_live_state.byte_counter < sector_end - 1) |
| 1853 | { |
| 1854 | // Set the underrun flag and hope that it will be cleared before we return here |
| 1855 | set_bits(m_register_r[INT_STATUS], ST_OVRUN, true); |
| 1856 | m_out_dmarq(ASSERT_LINE); |
| 1857 | } |
| 1858 | checkpoint(); |
| 1859 | break; |
| 1860 | } |
| 1861 | |
| 1862 | // CRC (two passes) |
| 1863 | // N.B.: when we write the first CRC byte, the value of the CRC will |
| 1864 | // change to the previous second byte, so we can write the first |
| 1865 | // byte in two iterations to get both |
| 1866 | if (m_live_state.byte_counter >= sector_end && m_live_state.byte_counter < sector_end + 2) |
| 1867 | { |
| 1868 | if (TRACE_WRITE) logerror("%s: [%s] Write CRC\n", tag(), tts(m_live_state.time).cstr()); |
| 1869 | encode_byte(m_live_state.crc >> 8); |
| 1870 | checkpoint(); |
| 1871 | break; |
| 1872 | } |
| 1873 | |
| 1874 | // Write a FF behind |
| 1875 | if (m_live_state.byte_counter == sector_end + 2) |
| 1876 | { |
| 1877 | encode_byte(0xff); |
| 1878 | checkpoint(); |
| 1879 | break; |
| 1880 | } |
| 1881 | |
| 1882 | // Done |
| 1883 | if (m_live_state.byte_counter > sector_end + 2) |
| 1884 | { |
| 1885 | if (TRACE_LIVE) logerror("%s: [%s] Write sector complete\n", tag(), tts(m_live_state.time).cstr()); |
| 1886 | m_pll.stop_writing(m_floppy, m_live_state.time); |
| 1887 | m_live_state.state = IDLE; |
| 1888 | return; |
| 1889 | } |
| 1890 | } |
| 1891 | |
1462 | 1892 | default: |
1463 | 1893 | logerror("%s: Unknown live state: %02x\n", tag(), m_live_state.state); |
1464 | 1894 | m_last_live_state = m_live_state.state; |
r32111 | r32112 | |
1482 | 1912 | if(m_live_state.time > machine().time()) |
1483 | 1913 | { |
1484 | 1914 | // If so, we must roll back to the last checkpoint |
1485 | | if (TRACE_SYNC) logerror("%s: [%s] Rolling back and replaying (%s)\n", tag(), ttsn().cstr(), tts(m_live_state.time).cstr()); |
| 1915 | if (TRACE_LIVE) logerror("%s: [%s] Rolling back and replaying (%s)\n", tag(), ttsn().cstr(), tts(m_live_state.time).cstr()); |
1486 | 1916 | rollback(); |
1487 | 1917 | // and replay until we reach the machine time |
1488 | 1918 | live_run_until(machine().time()); |
r32111 | r32112 | |
1493 | 1923 | { |
1494 | 1924 | // We are behind machine time, so we will never get back to that |
1495 | 1925 | // time, thus we can commit that position |
1496 | | if (TRACE_SYNC) logerror("%s: [%s] Committing (%s)\n", tag(), ttsn().cstr(), tts(m_live_state.time).cstr()); |
| 1926 | if (TRACE_LIVE) logerror("%s: [%s] Committing (%s)\n", tag(), ttsn().cstr(), tts(m_live_state.time).cstr()); |
1497 | 1927 | m_pll.commit(m_floppy, m_live_state.time); |
1498 | 1928 | |
1499 | 1929 | if (m_live_state.next_state != -1) |
r32111 | r32112 | |
1576 | 2006 | return false; |
1577 | 2007 | } |
1578 | 2008 | |
| 2009 | bool hdc9234_device::write_one_bit(const attotime &limit) |
| 2010 | { |
| 2011 | bool bit = (m_live_state.shift_reg & 0x8000)!=0; |
| 2012 | |
| 2013 | bool over_limit = m_pll.write_next_bit(bit, m_live_state.time, m_floppy, limit); |
| 2014 | if (over_limit) return true; |
| 2015 | |
| 2016 | // Calculate the CRC from the data bits on the odd positions |
| 2017 | if (m_live_state.bit_counter & 1) |
| 2018 | { |
| 2019 | if ((m_live_state.crc ^ (bit ? 0x8000 : 0x0000)) & 0x8000) |
| 2020 | m_live_state.crc = (m_live_state.crc << 1) ^ 0x1021; |
| 2021 | else |
| 2022 | m_live_state.crc = m_live_state.crc << 1; |
| 2023 | } |
| 2024 | m_live_state.shift_reg = m_live_state.shift_reg << 1; |
| 2025 | m_live_state.bit_counter--; |
| 2026 | return false; |
| 2027 | } |
| 2028 | |
| 2029 | /* |
| 2030 | Encode a byte for FM or MFM recording. Result is returned in the |
| 2031 | shift register of m_live_state. |
| 2032 | */ |
| 2033 | void hdc9234_device::encode_byte(UINT8 byte) |
| 2034 | { |
| 2035 | UINT16 raw; |
| 2036 | UINT8 check_pos; |
| 2037 | bool last_bit_set; |
| 2038 | check_pos = 0x80; |
| 2039 | |
| 2040 | if (fm_mode()) |
| 2041 | { |
| 2042 | // Set all clock bits |
| 2043 | raw = 0xaaaa; |
| 2044 | |
| 2045 | // FM: data bit = 1 -> encode as 11 |
| 2046 | // data bit = 0 -> encode as 10 |
| 2047 | for (int i=0; i<8; i++) |
| 2048 | { |
| 2049 | if (byte & check_pos) raw |= 0x4000 >> (2*i); |
| 2050 | check_pos >>= 1; |
| 2051 | } |
| 2052 | last_bit_set = ((byte & 1)!=0); |
| 2053 | } |
| 2054 | else |
| 2055 | { |
| 2056 | last_bit_set = m_live_state.last_data_bit; |
| 2057 | raw = 0; |
| 2058 | for (int i=0; i<8; i++) |
| 2059 | { |
| 2060 | bool bit_set = ((byte & check_pos)!=0); |
| 2061 | |
| 2062 | // MFM: data bit = 1 -> encode as 01 |
| 2063 | // data bit = 0 -> encode as x0 (x = !last_bit) |
| 2064 | if (bit_set) |
| 2065 | raw |= 0x4000 >> (2*i); |
| 2066 | else |
| 2067 | raw |= (last_bit_set? 0x0000 : 0x8000) >> (2*i); |
| 2068 | |
| 2069 | last_bit_set = bit_set; |
| 2070 | check_pos >>= 1; |
| 2071 | } |
| 2072 | } |
| 2073 | m_live_state.last_data_bit = last_bit_set; |
| 2074 | m_live_state.shift_reg = raw; |
| 2075 | m_live_state.data_reg = byte; |
| 2076 | } |
| 2077 | |
| 2078 | void hdc9234_device::encode_raw(UINT16 raw) |
| 2079 | { |
| 2080 | m_live_state.shift_reg = raw; |
| 2081 | m_live_state.last_data_bit = raw & 1; |
| 2082 | } |
| 2083 | |
1579 | 2084 | void hdc9234_device::pll_reset(const attotime &when) |
1580 | 2085 | { |
1581 | 2086 | m_pll.reset(when); |
1582 | | // In FM mode, cells are 4 ??s long; in MFM they are 2 ??s long. |
| 2087 | // In FM mode, cells are 4 usec long; in MFM they are 2 usec long. |
1583 | 2088 | m_pll.set_clock(attotime::from_usec(fm_mode()? 4 : 2)); |
1584 | 2089 | } |
1585 | 2090 | |
r32111 | r32112 | |
1647 | 2152 | |
1648 | 2153 | if ((offset & 1) == 0) |
1649 | 2154 | { |
1650 | | wait_time(m_cmd_timer, attotime::from_nsec(REGISTER_COMMIT), 0); |
| 2155 | wait_time(m_cmd_timer, attotime::from_nsec(REGISTER_COMMIT), REGISTER_ACCESS); |
1651 | 2156 | } |
1652 | 2157 | else |
1653 | 2158 | { |
1654 | | if (m_command != NOCMD) |
| 2159 | if (m_executing) |
1655 | 2160 | { |
1656 | | logerror("%s: [%s] Error - previous command %02x not completed; new command %02x ignored\n", tag(), ttsn().cstr(), m_command, m_data); |
| 2161 | logerror("%s: [%s] Error - previous command %02x not completed; new command %02x ignored\n", tag(), ttsn().cstr(), current_command(), m_data); |
1657 | 2162 | } |
1658 | 2163 | else |
1659 | 2164 | { |
1660 | | wait_time(m_cmd_timer, attotime::from_nsec(COMMAND_COMMIT), 1); |
| 2165 | wait_time(m_cmd_timer, attotime::from_nsec(COMMAND_COMMIT), COMMAND_INIT); |
1661 | 2166 | } |
1662 | 2167 | } |
1663 | 2168 | } |
1664 | 2169 | |
1665 | 2170 | /* |
1666 | | When the commit period has passed, process the command. |
| 2171 | When the commit period has passed, process the command or register access |
1667 | 2172 | */ |
1668 | | void hdc9234_device::command_continue() |
| 2173 | void hdc9234_device::process_command() |
1669 | 2174 | { |
1670 | | // Reset DONE and BAD_SECTOR [1], p.7 |
1671 | | set_bits(m_register_r[INT_STATUS], ST_DONE | ST_BADSECT, false); |
| 2175 | if (m_substate == REGISTER_ACCESS) |
| 2176 | { |
| 2177 | // Writing data to registers |
| 2178 | // Data register |
| 2179 | if (TRACE_REG) |
| 2180 | { |
| 2181 | if (m_register_pointer == INT_COMM_TERM) |
| 2182 | logerror("%s: Setting interrupt trigger DONE=%d READY=%d\n", tag(), (m_data & TC_INTDONE)? 1:0, (m_data & TC_INTRDCH)? 1:0); |
| 2183 | else |
| 2184 | logerror("%s: register[%d] <- %02x\n", tag(), m_register_pointer, m_data); |
| 2185 | } |
| 2186 | m_register_w[m_register_pointer] = m_data; |
1672 | 2187 | |
1673 | | // Reset interrupt line (not explicitly mentioned in spec, but seems reasonable |
1674 | | set_interrupt(CLEAR_LINE); |
| 2188 | // Changes to these registers must be output via the auxbus |
| 2189 | if (m_register_pointer == DESIRED_HEAD || m_register_pointer == RETRY_COUNT) |
| 2190 | auxbus_out(); |
1675 | 2191 | |
1676 | | // Clear Interrupt Pending and Ready Change |
1677 | | set_bits(m_register_r[INT_STATUS], ST_INTPEND | ST_RDYCHNG, false); |
| 2192 | // The DMA registers and the sector register for read and |
| 2193 | // write are identical, so in that case we copy the contents |
| 2194 | if (m_register_pointer < DESIRED_HEAD) m_register_r[m_register_pointer] = m_data; |
1678 | 2195 | |
1679 | | m_command = m_data; |
1680 | | m_stop_after_index = false; |
1681 | | m_wait_for_index = false; |
1682 | | |
1683 | | int index = 0; |
1684 | | m_main_state = UNDEF; |
1685 | | while (s_command[index].mask!=0 && m_main_state == UNDEF) |
1686 | | { |
1687 | | if ((m_command & s_command[index].mask) == s_command[index].baseval) |
1688 | | { |
1689 | | // Invoke command |
1690 | | m_main_state = s_command[index].state; |
1691 | | (this->*s_command[index].command)(); |
1692 | | } |
1693 | | index++; |
| 2196 | // Autoincrement until DATA is reached. |
| 2197 | if (m_register_pointer < DATA) m_register_pointer++; |
1694 | 2198 | } |
1695 | | if (m_main_state==UNDEF) |
| 2199 | else |
1696 | 2200 | { |
1697 | | logerror("%s: Command %02x not defined\n", tag(), m_command); |
1698 | | } |
1699 | | } |
| 2201 | // Reset DONE and BAD_SECTOR [1], p.7 |
| 2202 | set_bits(m_register_r[INT_STATUS], ST_DONE | ST_BADSECT, false); |
1700 | 2203 | |
1701 | | /* |
1702 | | When the commit period has passed, process the register write operation. |
1703 | | */ |
1704 | | void hdc9234_device::register_write_continue() |
1705 | | { |
1706 | | // Writing data to registers |
1707 | | // Data register |
1708 | | if (TRACE_REG) |
1709 | | { |
1710 | | if (m_register_pointer == INT_COMM_TERM) |
1711 | | logerror("%s: Setting interrupt trigger DONE=%d READY=%d\n", tag(), (m_data & TC_INTDONE)? 1:0, (m_data & TC_INTRDCH)? 1:0); |
1712 | | else |
1713 | | logerror("%s: register[%d] <- %02x\n", tag(), m_register_pointer, m_data); |
1714 | | } |
1715 | | m_register_w[m_register_pointer] = m_data; |
| 2204 | // Reset interrupt line (not explicitly mentioned in spec, but seems reasonable |
| 2205 | set_interrupt(CLEAR_LINE); |
1716 | 2206 | |
1717 | | // The DMA registers and the sector register for read and |
1718 | | // write are identical, so in that case we copy the contents |
1719 | | if (m_register_pointer < DESIRED_HEAD) m_register_r[m_register_pointer] = m_data; |
| 2207 | // Clear Interrupt Pending and Ready Change |
| 2208 | set_bits(m_register_r[INT_STATUS], ST_INTPEND | ST_RDYCHNG, false); |
1720 | 2209 | |
1721 | | // Autoincrement until DATA is reached. |
1722 | | if (m_register_pointer < DATA) m_register_pointer++; |
| 2210 | // Store command |
| 2211 | UINT8 command = m_data; |
| 2212 | m_register_w[COMMAND] = command; |
| 2213 | m_stop_after_index = false; |
| 2214 | m_wait_for_index = false; |
| 2215 | |
| 2216 | int index = 0; |
| 2217 | bool found = false; |
| 2218 | |
| 2219 | while (s_command[index].mask!=0 && !found) |
| 2220 | { |
| 2221 | if ((command & s_command[index].mask) == s_command[index].baseval) |
| 2222 | { |
| 2223 | // Invoke command |
| 2224 | m_substate = UNDEF; |
| 2225 | found = true; |
| 2226 | m_executing = true; |
| 2227 | m_command = s_command[index].command; |
| 2228 | (this->*m_command)(); |
| 2229 | } |
| 2230 | else index++; |
| 2231 | } |
| 2232 | if (!found) |
| 2233 | { |
| 2234 | logerror("%s: Command %02x not defined\n", tag(), command); |
| 2235 | } |
| 2236 | } |
1723 | 2237 | } |
1724 | 2238 | |
1725 | 2239 | /* |
r32111 | r32112 | |
1762 | 2276 | +------+------+------+------+------+------+------+------+ |
1763 | 2277 | | ECC |Index | SeekC| Tr00 | User | WrPrt| Ready|Fault | |
1764 | 2278 | +------+------+------+------+------+------+------+------+ |
1765 | | |
1766 | | |
1767 | | OUTPUT1 register contents |
1768 | | S0 = 0, S1 = 1 |
1769 | | +------+------+------+------+------+------+------+------+ |
1770 | | | Drv3 | Drv2 | Drv1 | Drv0 | PO3 | PO2 | PO1 | PO0 | |
1771 | | +------+------+------+------+------+------+------+------+ |
1772 | | |
1773 | | DrvX = select Drive X (only one bit allowed) |
1774 | | POX = Programmable output X (contents from low 4 bits of register RETRY_COUNT) |
1775 | | |
1776 | | |
1777 | | OUTPUT2 register contents |
1778 | | S0 = 1, S1 = 1 |
1779 | | +------+------+------+------+------+------+------+------+ |
1780 | | | Drv3*| WCur | Dir | Step | Head | |
1781 | | +------+------+------+------+------+------+------+------+ |
1782 | | |
1783 | | Drv3* = inverted Drv3 signal of OUTPUT1 |
1784 | | WCur = Reduced write current |
1785 | | Dir = Step direction (0 = towards track 0) |
1786 | | Step = Step pulse |
1787 | | Head = desired head |
1788 | 2279 | */ |
1789 | 2280 | |
1790 | 2281 | /* |
r32111 | r32112 | |
1797 | 2288 | if (!m_initialized) |
1798 | 2289 | return; |
1799 | 2290 | |
1800 | | if (TRACE_ACT) logerror("%s: Got value %02x via auxbus: ecc=%d index=%d seek_comp=%d tr00=%d user=%d writeprot=%d ready=%d fault=%d\n", |
| 2291 | if (TRACE_AUXBUS) logerror("%s: Got value %02x via auxbus: ecc=%d index=%d seek_comp=%d tr00=%d user=%d writeprot=%d ready=%d fault=%d\n", |
1801 | 2292 | tag(), data, |
1802 | 2293 | (data&HDC_DS_ECCERR)? 1:0, (data&HDC_DS_INDEX)? 1:0, |
1803 | 2294 | (data&HDC_DS_SKCOM)? 1:0, (data&HDC_DS_TRK00)? 1:0, |
r32111 | r32112 | |
1827 | 2318 | |
1828 | 2319 | void hdc9234_device::index_callback(int level) |
1829 | 2320 | { |
1830 | | if (TRACE_ACT) logerror("%s: [%s] Index callback level=%d\n", tag(), ttsn().cstr(), level); |
| 2321 | if (TRACE_LINES) logerror("%s: [%s] Index callback level=%d\n", tag(), ttsn().cstr(), level); |
1831 | 2322 | |
1832 | 2323 | // Synchronize our position on the track |
1833 | 2324 | live_sync(); |
1834 | 2325 | |
1835 | | if (level==CLEAR_LINE) { |
1836 | | general_continue(); |
1837 | | return; |
1838 | | } |
1839 | | else |
| 2326 | if (level==ASSERT_LINE) |
1840 | 2327 | { |
1841 | | // ... |
| 2328 | if (TRACE_INDEX) logerror("%s: Index pulse\n", tag()); |
1842 | 2329 | if (m_wait_for_index) m_stop_after_index = true; |
1843 | | general_continue(); |
1844 | 2330 | } |
| 2331 | |
| 2332 | reenter_command_processing(); |
1845 | 2333 | } |
1846 | 2334 | |
1847 | 2335 | void hdc9234_device::ready_callback(int level) |
1848 | 2336 | { |
1849 | | if (TRACE_ACT) logerror("%s: [%s] Ready callback level=%d\n", tag(), ttsn().cstr(), level); |
| 2337 | if (TRACE_LINES) logerror("%s: [%s] Ready callback level=%d\n", tag(), ttsn().cstr(), level); |
1850 | 2338 | |
1851 | 2339 | // Set the interrupt status flag |
1852 | 2340 | set_bits(m_register_r[INT_STATUS], ST_RDYCHNG, true); |
r32111 | r32112 | |
1857 | 2345 | // Raise an interrupt if desired |
1858 | 2346 | if (m_register_w[INT_COMM_TERM] & TC_INTRDCH) |
1859 | 2347 | { |
1860 | | if (TRACE_ACT) logerror("%s: Raise interrupt READY change\n", tag()); |
| 2348 | if (TRACE_INT) logerror("%s: Raise interrupt READY change\n", tag()); |
1861 | 2349 | set_interrupt(ASSERT_LINE); |
1862 | 2350 | } |
| 2351 | |
| 2352 | // reenter_command_processing(); |
1863 | 2353 | } |
1864 | 2354 | |
1865 | 2355 | void hdc9234_device::seek_complete_callback(int level) |
1866 | 2356 | { |
1867 | | if (TRACE_ACT) logerror("%s: [%s] Seek complete callback level=%d\n", tag(), ttsn().cstr(), level); |
| 2357 | if (TRACE_LINES) logerror("%s: [%s] Seek complete callback level=%d\n", tag(), ttsn().cstr(), level); |
1868 | 2358 | |
1869 | 2359 | // Synchronize our position on the track |
1870 | 2360 | live_sync(); |
1871 | 2361 | |
1872 | | if (level==ASSERT_LINE && m_next_state != UNDEF) |
| 2362 | if (level==ASSERT_LINE && m_state_after_line != UNDEF) |
1873 | 2363 | { |
1874 | | m_substate = m_next_state; |
1875 | | general_continue(); |
| 2364 | m_substate = m_state_after_line; |
| 2365 | m_state_after_line = UNDEF; |
| 2366 | reenter_command_processing(); |
1876 | 2367 | } |
1877 | 2368 | } |
1878 | 2369 | |
1879 | 2370 | void hdc9234_device::wait_line(int substate) |
1880 | 2371 | { |
1881 | | m_next_state = substate; |
| 2372 | m_state_after_line = substate; |
1882 | 2373 | } |
1883 | 2374 | |
1884 | 2375 | bool hdc9234_device::on_track00() |
r32111 | r32112 | |
1889 | 2380 | /* |
1890 | 2381 | Push the output registers over the auxiliary bus. It is expected that |
1891 | 2382 | the PCB contains latches to store the values. |
| 2383 | |
| 2384 | OUTPUT1 register contents |
| 2385 | S0 = 0, S1 = 1 |
| 2386 | +------+------+------+------+------+------+------+------+ |
| 2387 | | Drv3 | Drv2 | Drv1 | Drv0 | PO3 | PO2 | PO1 | PO0 | |
| 2388 | +------+------+------+------+------+------+------+------+ |
| 2389 | |
| 2390 | DrvX = select Drive X (only one bit allowed) |
| 2391 | POX = Programmable output X (contents from low 4 bits of register RETRY_COUNT) |
| 2392 | |
| 2393 | |
| 2394 | OUTPUT2 register contents |
| 2395 | S0 = 1, S1 = 1 |
| 2396 | +------+------+------+------+------+------+------+------+ |
| 2397 | | Drv3*| WCur | Dir | Step | Head | |
| 2398 | +------+------+------+------+------+------+------+------+ |
| 2399 | |
| 2400 | Drv3* = inverted Drv3 signal of OUTPUT1 |
| 2401 | WCur = Reduced write current |
| 2402 | Dir = Step direction (0 = towards track 0) |
| 2403 | Step = Step pulse |
| 2404 | Head = desired head |
1892 | 2405 | */ |
1893 | | void hdc9234_device::sync_latches_out() |
| 2406 | void hdc9234_device::auxbus_out() |
1894 | 2407 | { |
1895 | | if (TRACE_ACT) logerror("%s: Setting OUTPUT1 to %02x\n", tag(), m_output1); |
| 2408 | if (TRACE_AUXBUS) logerror("%s: Setting OUTPUT1 to %02x\n", tag(), m_output1); |
1896 | 2409 | m_out_auxbus((offs_t)HDC_OUTPUT_1, m_output1); |
1897 | | set_bits(m_output2, OUT2_DRVSEL3I, (m_output1 & 0x80)==0); |
1898 | | if (TRACE_ACT) logerror("%s: Setting OUTPUT2 to %02x\n", tag(), m_output2); |
| 2410 | |
| 2411 | // prepare output2 |
| 2412 | set_bits(m_output2, OUT2_DRVSEL3I, (m_output1 & OUT1_DRVSEL3)==0); |
| 2413 | |
| 2414 | m_output2 = (m_output2 & 0xb0) | desired_head(); |
| 2415 | if (m_reduced_write_current) m_output2 |= OUT2_REDWRT; |
| 2416 | |
| 2417 | if (TRACE_AUXBUS) logerror("%s: Setting OUTPUT2 to %02x\n", tag(), m_output2); |
1899 | 2418 | m_out_auxbus((offs_t)HDC_OUTPUT_2, m_output2); |
1900 | 2419 | } |
1901 | 2420 | |
r32111 | r32112 | |
1912 | 2431 | */ |
1913 | 2432 | void hdc9234_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) |
1914 | 2433 | { |
1915 | | if (TRACE_ACT) logerror("%s: [%s] Timer id=%d expired\n", tag(), ttsn().cstr(), id); |
1916 | 2434 | live_sync(); |
1917 | 2435 | |
1918 | 2436 | switch (id) |
1919 | 2437 | { |
1920 | 2438 | case GEN_TIMER: |
1921 | | general_continue(); |
| 2439 | reenter_command_processing(); |
1922 | 2440 | break; |
1923 | 2441 | case COM_TIMER: |
1924 | | if (m_substate==1) command_continue(); |
1925 | | else register_write_continue(); |
| 2442 | process_command(); |
1926 | 2443 | break; |
1927 | 2444 | case LIVE_TIMER: |
1928 | 2445 | live_run(); |
r32111 | r32112 | |
1937 | 2454 | { |
1938 | 2455 | if (state==ASSERT_LINE) |
1939 | 2456 | { |
1940 | | if (TRACE_ACT) logerror("%s: [%s] DMA acknowledged\n", tag(), ttsn().cstr()); |
| 2457 | if (TRACE_LINES) logerror("%s: [%s] DMA acknowledged\n", tag(), ttsn().cstr()); |
1941 | 2458 | set_bits(m_register_r[INT_STATUS], ST_OVRUN, false); |
1942 | 2459 | } |
1943 | 2460 | } |
r32111 | r32112 | |
1978 | 2495 | |
1979 | 2496 | m_selected_drive_type = 0; |
1980 | 2497 | m_head_load_delay_enable = false; |
| 2498 | |
1981 | 2499 | m_register_pointer = 0; |
| 2500 | |
1982 | 2501 | m_output1 = 0; |
1983 | 2502 | m_output2 = 0x80; |
1984 | 2503 | |
r32111 | r32112 | |
1989 | 2508 | for (int i=0; i<=11; i++) |
1990 | 2509 | m_register_r[i] = m_register_w[i] = 0; |
1991 | 2510 | |
1992 | | m_step_direction = 0; |
1993 | | |
1994 | | m_next_state = IDLE; |
| 2511 | m_state_after_line = UNDEF; |
1995 | 2512 | m_seek_count = 0; |
1996 | 2513 | |
1997 | 2514 | m_live_state.time = attotime::never; |
1998 | 2515 | m_live_state.state = IDLE; |
1999 | | m_initialized = true; |
2000 | 2516 | |
2001 | 2517 | m_track_delta = 0; |
2002 | 2518 | |
2003 | 2519 | m_multi_sector = false; |
2004 | 2520 | m_retry_save = 0; |
2005 | 2521 | |
2006 | | m_substate = IDLE; |
2007 | | m_main_state = IDLE; |
2008 | | m_command = NOCMD; |
| 2522 | m_substate = UNDEF; |
2009 | 2523 | |
| 2524 | m_executing = false; |
| 2525 | |
2010 | 2526 | m_stop_after_index = false; |
2011 | 2527 | m_wait_for_index = false; |
2012 | 2528 | |
| 2529 | m_transfer_enabled = true; |
| 2530 | m_write = false; |
| 2531 | m_deleted = false; |
| 2532 | |
2013 | 2533 | m_data = 0; |
| 2534 | m_precompensation = 0; |
| 2535 | m_reduced_write_current = false; |
| 2536 | |
| 2537 | m_initialized = true; |
2014 | 2538 | } |
2015 | 2539 | |
2016 | 2540 | const device_type HDC9234 = &device_creator<hdc9234_device>; |