trunk/src/emu/machine/ncr539x.c
| r29449 | r29450 | |
| 104 | 104 | return 6; |
| 105 | 105 | } |
| 106 | 106 | |
| 107 | | //------------------------------------------------- |
| 108 | | // device_config_complete - perform any |
| 109 | | // operations now that the configuration is |
| 110 | | // complete |
| 111 | | //------------------------------------------------- |
| 112 | | |
| 113 | | void ncr539x_device::device_config_complete() |
| 114 | | { |
| 115 | | // inherit a copy of the static data |
| 116 | | const NCR539Xinterface *intf = reinterpret_cast<const NCR539Xinterface *>(static_config()); |
| 117 | | if (intf != NULL) |
| 118 | | { |
| 119 | | *static_cast<NCR539Xinterface *>(this) = *intf; |
| 120 | | } |
| 121 | | |
| 122 | | // or initialize to defaults if none provided |
| 123 | | else |
| 124 | | { |
| 125 | | memset(&m_out_irq_cb, 0, sizeof(m_out_irq_cb)); |
| 126 | | memset(&m_out_drq_cb, 0, sizeof(m_out_drq_cb)); |
| 127 | | } |
| 128 | | } |
| 129 | | |
| 130 | 107 | //************************************************************************** |
| 131 | 108 | // LIVE DEVICE |
| 132 | 109 | //************************************************************************** |
| r29449 | r29450 | |
| 138 | 115 | //------------------------------------------------- |
| 139 | 116 | |
| 140 | 117 | ncr539x_device::ncr539x_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 141 | | : device_t(mconfig, NCR539X, "539x SCSI", tag, owner, clock, "ncr539x", __FILE__) |
| 118 | : device_t(mconfig, NCR539X, "539x SCSI", tag, owner, clock, "ncr539x", __FILE__), |
| 119 | m_out_irq_cb(*this), |
| 120 | m_out_drq_cb(*this) |
| 142 | 121 | { |
| 143 | 122 | } |
| 144 | 123 | |
| r29449 | r29450 | |
| 151 | 130 | memset(m_scsi_devices, 0, sizeof(m_scsi_devices)); |
| 152 | 131 | |
| 153 | 132 | // resolve line callbacks |
| 154 | | m_out_irq_func.resolve(m_out_irq_cb, *this); |
| 155 | | m_out_drq_func.resolve(m_out_drq_cb, *this); |
| 133 | m_out_irq_cb.resolve_safe(); |
| 134 | m_out_drq_cb.resolve_safe(); |
| 156 | 135 | |
| 157 | 136 | // try to open the devices |
| 158 | 137 | for( device_t *device = owner()->first_subdevice(); device != NULL; device = device->next() ) |
| r29449 | r29450 | |
| 189 | 168 | m_chipid_available = false; |
| 190 | 169 | m_chipid_lock = false; |
| 191 | 170 | |
| 192 | | m_out_irq_func(CLEAR_LINE); |
| 193 | | m_out_drq_func(CLEAR_LINE); |
| 171 | m_out_irq_cb(CLEAR_LINE); |
| 172 | m_out_drq_cb(CLEAR_LINE); |
| 194 | 173 | } |
| 195 | 174 | |
| 196 | 175 | void ncr539x_device::dma_read_data(int bytes, UINT8 *pData) |
| r29449 | r29450 | |
| 233 | 212 | // if this is a DMA command, raise DRQ now |
| 234 | 213 | if (m_command & 0x80) |
| 235 | 214 | { |
| 236 | | m_out_drq_func(ASSERT_LINE); |
| 215 | m_out_drq_cb(ASSERT_LINE); |
| 237 | 216 | } |
| 238 | 217 | |
| 239 | 218 | switch (m_command & 0x7f) |
| r29449 | r29450 | |
| 267 | 246 | m_status |= MAIN_STATUS_INTERRUPT; |
| 268 | 247 | m_irq_status |= IRQ_STATUS_DISCONNECTED; |
| 269 | 248 | } |
| 270 | | m_out_irq_func(ASSERT_LINE); |
| 249 | m_out_irq_cb(ASSERT_LINE); |
| 271 | 250 | break; |
| 272 | 251 | |
| 273 | 252 | case 0x42: // Select with ATN steps |
| r29449 | r29450 | |
| 298 | 277 | m_status |= MAIN_STATUS_INTERRUPT; |
| 299 | 278 | m_irq_status |= IRQ_STATUS_DISCONNECTED; |
| 300 | 279 | } |
| 301 | | m_out_irq_func(ASSERT_LINE); |
| 280 | m_out_irq_cb(ASSERT_LINE); |
| 302 | 281 | break; |
| 303 | 282 | |
| 304 | 283 | case 0x11: // initiator command complete |
| r29449 | r29450 | |
| 308 | 287 | m_irq_status = IRQ_STATUS_SERVICE_REQUEST; |
| 309 | 288 | m_status &= ~7; // clear phase bits |
| 310 | 289 | m_status |= MAIN_STATUS_INTERRUPT | SCSI_PHASE_DATAIN; // go to data in phase (?) |
| 311 | | m_out_irq_func(ASSERT_LINE); |
| 290 | m_out_irq_cb(ASSERT_LINE); |
| 312 | 291 | |
| 313 | 292 | // this puts status and message bytes into the FIFO (todo: what are these?) |
| 314 | 293 | m_fifo_ptr = 0; |
| r29449 | r29450 | |
| 326 | 305 | #endif |
| 327 | 306 | m_irq_status = IRQ_STATUS_SERVICE_REQUEST; |
| 328 | 307 | m_status |= MAIN_STATUS_INTERRUPT; |
| 329 | | m_out_irq_func(ASSERT_LINE); |
| 308 | m_out_irq_cb(ASSERT_LINE); |
| 330 | 309 | break; |
| 331 | 310 | |
| 332 | 311 | default: |
| r29449 | r29450 | |
| 407 | 386 | m_irq_status = IRQ_STATUS_SERVICE_REQUEST; |
| 408 | 387 | m_status &= 0x7; // clear everything but the phase bits |
| 409 | 388 | m_status |= MAIN_STATUS_INTERRUPT | MAIN_STATUS_COUNT_TO_ZERO; |
| 410 | | m_out_irq_func(ASSERT_LINE); |
| 389 | m_out_irq_cb(ASSERT_LINE); |
| 411 | 390 | |
| 412 | 391 | // if no data at all, drop the phase |
| 413 | 392 | if ((m_buffer_remaining + m_total_data) == 0) |
| r29449 | r29450 | |
| 436 | 415 | rv = m_irq_status; |
| 437 | 416 | // clear the interrupt state |
| 438 | 417 | m_status &= ~MAIN_STATUS_INTERRUPT; |
| 439 | | m_out_irq_func(CLEAR_LINE); |
| 418 | m_out_irq_cb(CLEAR_LINE); |
| 440 | 419 | break; |
| 441 | 420 | |
| 442 | 421 | case 6: |
| r29449 | r29450 | |
| 515 | 494 | case 0x00: // NOP |
| 516 | 495 | m_irq_status = IRQ_STATUS_SUCCESS; |
| 517 | 496 | m_status |= MAIN_STATUS_INTERRUPT; |
| 518 | | m_out_irq_func(ASSERT_LINE); |
| 497 | m_out_irq_cb(ASSERT_LINE); |
| 519 | 498 | |
| 520 | 499 | // DMA NOP? allow chip ID |
| 521 | 500 | if ((m_command == 0x80) && (!m_chipid_lock)) |
| r29449 | r29450 | |
| 529 | 508 | update_fifo_internal_state(0); |
| 530 | 509 | m_irq_status = IRQ_STATUS_SUCCESS; |
| 531 | 510 | m_status |= MAIN_STATUS_INTERRUPT; |
| 532 | | m_out_irq_func(ASSERT_LINE); |
| 511 | m_out_irq_cb(ASSERT_LINE); |
| 533 | 512 | break; |
| 534 | 513 | |
| 535 | 514 | case 0x02: // Reset device |
| r29449 | r29450 | |
| 537 | 516 | |
| 538 | 517 | m_irq_status = IRQ_STATUS_SUCCESS; |
| 539 | 518 | m_status |= MAIN_STATUS_INTERRUPT; |
| 540 | | m_out_irq_func(ASSERT_LINE); |
| 519 | m_out_irq_cb(ASSERT_LINE); |
| 541 | 520 | break; |
| 542 | 521 | |
| 543 | 522 | case 0x03: // Reset SCSI bus |
| 544 | 523 | m_status = 0; |
| 545 | 524 | m_irq_status = IRQ_STATUS_SUCCESS; |
| 546 | 525 | m_status |= MAIN_STATUS_INTERRUPT; |
| 547 | | m_out_irq_func(ASSERT_LINE); |
| 526 | m_out_irq_cb(ASSERT_LINE); |
| 548 | 527 | break; |
| 549 | 528 | |
| 550 | 529 | case 0x10: // information transfer (must happen immediately) |
| r29449 | r29450 | |
| 611 | 590 | m_xfer_count = m_dma_size; |
| 612 | 591 | m_fifo_ptr = 0; |
| 613 | 592 | update_fifo_internal_state(fifo_fill_size); |
| 614 | | m_out_drq_func(ASSERT_LINE); |
| 593 | m_out_drq_cb(ASSERT_LINE); |
| 615 | 594 | } |
| 616 | 595 | |
| 617 | 596 | m_status |= MAIN_STATUS_COUNT_TO_ZERO; |
| r29449 | r29450 | |
| 635 | 614 | m_buffer_offset = 0; |
| 636 | 615 | m_buffer_remaining = 0; |
| 637 | 616 | } |
| 638 | | m_out_irq_func(ASSERT_LINE); |
| 617 | m_out_irq_cb(ASSERT_LINE); |
| 639 | 618 | break; |
| 640 | 619 | |
| 641 | 620 | case 0x24: // Terminate steps |
| r29449 | r29450 | |
| 644 | 623 | #endif |
| 645 | 624 | m_irq_status = IRQ_STATUS_SUCCESS | IRQ_STATUS_DISCONNECTED; |
| 646 | 625 | m_status |= MAIN_STATUS_INTERRUPT; |
| 647 | | m_out_irq_func(ASSERT_LINE); |
| 626 | m_out_irq_cb(ASSERT_LINE); |
| 648 | 627 | m_fifo_ptr = 0; |
| 649 | 628 | update_fifo_internal_state(0); |
| 650 | 629 | break; |
| r29449 | r29450 | |
| 655 | 634 | #endif |
| 656 | 635 | m_irq_status = IRQ_STATUS_SUCCESS; |
| 657 | 636 | m_status |= MAIN_STATUS_INTERRUPT; |
| 658 | | m_out_irq_func(ASSERT_LINE); |
| 637 | m_out_irq_cb(ASSERT_LINE); |
| 659 | 638 | break; |
| 660 | 639 | |
| 661 | 640 | case 0x44: // Enable selection/reselection |
| r29449 | r29450 | |
| 664 | 643 | #endif |
| 665 | 644 | m_irq_status = IRQ_STATUS_SUCCESS; |
| 666 | 645 | m_status |= MAIN_STATUS_INTERRUPT; |
| 667 | | m_out_irq_func(ASSERT_LINE); |
| 646 | m_out_irq_cb(ASSERT_LINE); |
| 668 | 647 | break; |
| 669 | 648 | |
| 670 | 649 | case 0x47: // Reselect with ATN3 steps |
| r29449 | r29450 | |
| 695 | 674 | m_status |= MAIN_STATUS_INTERRUPT; |
| 696 | 675 | m_irq_status |= IRQ_STATUS_DISCONNECTED; |
| 697 | 676 | } |
| 698 | | m_out_irq_func(ASSERT_LINE); |
| 677 | m_out_irq_cb(ASSERT_LINE); |
| 699 | 678 | break; |
| 700 | 679 | |
| 701 | 680 | default: // other commands are not instantaneous |
| r29449 | r29450 | |
| 846 | 825 | m_irq_status = IRQ_STATUS_SERVICE_REQUEST; |
| 847 | 826 | m_status &= 7; |
| 848 | 827 | m_status |= MAIN_STATUS_INTERRUPT; |
| 849 | | m_out_irq_func(ASSERT_LINE); |
| 828 | m_out_irq_cb(ASSERT_LINE); |
| 850 | 829 | } |
| 851 | 830 | |
| 852 | 831 | if ((m_xfer_count == 0) && (m_total_data == 0)) |
| r29449 | r29450 | |
| 858 | 837 | m_buffer_offset = 0; |
| 859 | 838 | m_irq_status = IRQ_STATUS_SERVICE_REQUEST; |
| 860 | 839 | m_status = MAIN_STATUS_INTERRUPT | SCSI_PHASE_STATUS; |
| 861 | | m_out_irq_func(ASSERT_LINE); |
| 840 | m_out_irq_cb(ASSERT_LINE); |
| 862 | 841 | } |
| 863 | 842 | } |
| 864 | 843 | } |
trunk/src/emu/machine/ncr539x.h
| r29449 | r29450 | |
| 8 | 8 | |
| 9 | 9 | #include "machine/scsihle.h" |
| 10 | 10 | |
| 11 | | struct NCR539Xinterface |
| 12 | | { |
| 13 | | devcb_write_line m_out_irq_cb; /* IRQ line */ |
| 14 | | devcb_write_line m_out_drq_cb; /* DRQ line */ |
| 15 | | }; |
| 16 | | |
| 17 | 11 | //// 539x registers |
| 18 | 12 | //enum |
| 19 | 13 | //{ |
| 20 | 14 | //}; |
| 21 | 15 | |
| 22 | 16 | // device stuff |
| 23 | | #define MCFG_NCR539X_ADD(_tag, _clock, _intrf) \ |
| 24 | | MCFG_DEVICE_ADD(_tag, NCR539X, _clock) \ |
| 25 | | MCFG_DEVICE_CONFIG(_intrf) |
| 26 | 17 | |
| 27 | | class ncr539x_device : public device_t, |
| 28 | | public NCR539Xinterface |
| 18 | #define MCFG_NCR539X_OUT_IRQ_CB(_devcb) \ |
| 19 | devcb = &ncr539x_device::set_out_irq_callback(*device, DEVCB2_##_devcb); |
| 20 | |
| 21 | #define MCFG_NCR539X_OUT_DRQ_CB(_devcb) \ |
| 22 | devcb = &ncr539x_device::set_out_drq_callback(*device, DEVCB2_##_devcb); |
| 23 | |
| 24 | |
| 25 | class ncr539x_device : public device_t |
| 29 | 26 | { |
| 30 | 27 | public: |
| 31 | 28 | // construction/destruction |
| 32 | 29 | ncr539x_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 30 | |
| 31 | template<class _Object> static devcb2_base &set_out_irq_callback(device_t &device, _Object object) { return downcast<ncr539x_device &>(device).m_out_irq_cb.set_callback(object); } |
| 32 | template<class _Object> static devcb2_base &set_out_drq_callback(device_t &device, _Object object) { return downcast<ncr539x_device &>(device).m_out_drq_cb.set_callback(object); } |
| 33 | 33 | |
| 34 | 34 | // our API |
| 35 | 35 | DECLARE_READ8_MEMBER(read); |
| r29449 | r29450 | |
| 42 | 42 | // device-level overrides |
| 43 | 43 | virtual void device_start(); |
| 44 | 44 | virtual void device_reset(); |
| 45 | | virtual void device_config_complete(); |
| 46 | 45 | virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); |
| 47 | 46 | |
| 48 | 47 | private: |
| r29449 | r29450 | |
| 83 | 82 | |
| 84 | 83 | emu_timer *m_operation_timer; |
| 85 | 84 | |
| 86 | | devcb_resolved_write_line m_out_irq_func; |
| 87 | | devcb_resolved_write_line m_out_drq_func; |
| 85 | devcb2_write_line m_out_irq_cb; /* IRQ line */ |
| 86 | devcb2_write_line m_out_drq_cb; /* DRQ line */ |
| 88 | 87 | }; |
| 89 | 88 | |
| 90 | 89 | // device type definition |