trunk/src/mess/machine/ncr5380n.c
| r25514 | r25515 | |
| 3 | 3 | ncr5380n.c |
| 4 | 4 | |
| 5 | 5 | Implementation of the NCR 5380, aka the Zilog Z5380 |
| 6 | | |
| 6 | |
| 7 | 7 | TODO: |
| 8 | | - IRQs (Apple doesn't use 'em) |
| 8 | - IRQs |
| 9 | 9 | - Target mode |
| 10 | | |
| 10 | |
| 11 | 40801766 - IIx ROM waiting point for "next read fails" |
| 12 | |
| 11 | 13 | *********************************************************************/ |
| 12 | 14 | |
| 13 | 15 | #include "emu.h" |
| r25514 | r25515 | |
| 76 | 78 | void ncr5380n_device::reset_soft() |
| 77 | 79 | { |
| 78 | 80 | state = IDLE; |
| 79 | | scsi_bus->ctrl_w(scsi_refid, 0, S_ALL); // clear any signals we're driving |
| 81 | scsi_bus->ctrl_w(scsi_refid, 0, S_ALL); // clear any signals we're driving |
| 80 | 82 | scsi_bus->ctrl_wait(scsi_refid, S_ALL, S_ALL); |
| 81 | 83 | status = 0; |
| 82 | 84 | drq = false; |
| r25514 | r25515 | |
| 95 | 97 | { |
| 96 | 98 | UINT32 ctrl = scsi_bus->ctrl_r(); |
| 97 | 99 | |
| 98 | | // printf("scsi_ctrl_changed: lines now %x\n", ctrl); |
| 100 | // printf("scsi_ctrl_changed: lines now %x\n", ctrl); |
| 99 | 101 | |
| 100 | | /* if ((ctrl & (S_PHASE_MASK|S_SEL|S_BSY)) != last_phase) |
| 101 | | { |
| 102 | | printf("phase now %d, SEL %x BSY %x\n", ctrl & S_PHASE_MASK, ctrl & S_SEL, ctrl & S_BSY); |
| 103 | | last_phase = (S_PHASE_MASK|S_SEL|S_BSY); |
| 104 | | }*/ |
| 102 | /* if ((ctrl & (S_PHASE_MASK|S_SEL|S_BSY)) != last_phase) |
| 103 | { |
| 104 | printf("phase now %d, REQ %x SEL %x BSY %x\n", ctrl & S_PHASE_MASK, ctrl & S_REQ, ctrl & S_SEL, ctrl & S_BSY); |
| 105 | last_phase = (S_PHASE_MASK|S_SEL|S_BSY); |
| 106 | }*/ |
| 105 | 107 | |
| 106 | 108 | // recalculate phase match |
| 107 | 109 | m_busstatus &= ~BAS_PHASEMATCH; |
| r25514 | r25515 | |
| 115 | 117 | // if BSY drops or the phase goes mismatch, that terminates the DMA |
| 116 | 118 | if ((!(ctrl & S_BSY)) || !(m_busstatus & BAS_PHASEMATCH)) |
| 117 | 119 | { |
| 118 | | // printf("BSY dropped or phase mismatch during DMA, ending DMA\n"); |
| 120 | // printf("BSY dropped or phase mismatch during DMA, ending DMA\n"); |
| 119 | 121 | m_mode &= ~MODE_DMA; |
| 120 | 122 | m_busstatus |= BAS_ENDOFDMA; |
| 121 | 123 | drq_clear(); |
| r25514 | r25515 | |
| 160 | 162 | |
| 161 | 163 | int win; |
| 162 | 164 | for(win=7; win>=0 && !(data & (1<<win)); win--); |
| 163 | | // printf("data %02x win %02x scsi_id %02x\n", data, win, scsi_id); |
| 165 | // printf("arb complete: data %02x win %02x scsi_id %02x\n", data, win, scsi_id); |
| 164 | 166 | if(win != scsi_id) { |
| 165 | 167 | scsi_bus->data_w(scsi_refid, 0); |
| 166 | 168 | scsi_bus->ctrl_w(scsi_refid, 0, S_ALL); |
| r25514 | r25515 | |
| 168 | 170 | break; |
| 169 | 171 | } |
| 170 | 172 | |
| 171 | | // arbitration no longer in progress |
| 172 | | m_icommand &= ~IC_ARBITRATION; |
| 173 | | |
| 174 | 173 | state &= STATE_MASK; |
| 175 | 174 | step(true); |
| 176 | 175 | break; |
| r25514 | r25515 | |
| 212 | 211 | break; |
| 213 | 212 | |
| 214 | 213 | m_dmalatch = scsi_bus->data_r(); |
| 215 | | drq_set(); |
| 216 | 214 | scsi_bus->ctrl_w(scsi_refid, S_ACK, S_ACK); |
| 217 | 215 | state = (state & STATE_MASK) | (RECV_WAIT_REQ_0 << SUB_SHIFT); |
| 218 | 216 | step(false); |
| r25514 | r25515 | |
| 223 | 221 | break; |
| 224 | 222 | state = state & STATE_MASK; |
| 225 | 223 | step(false); |
| 224 | |
| 225 | drq_set(); // raise DRQ now that we've completed |
| 226 | 226 | break; |
| 227 | 227 | |
| 228 | 228 | default: |
| r25514 | r25515 | |
| 252 | 252 | void ncr5380n_device::function_bus_complete() |
| 253 | 253 | { |
| 254 | 254 | state = IDLE; |
| 255 | | // istatus |= I_FUNCTION|I_BUS; |
| 255 | // istatus |= I_FUNCTION|I_BUS; |
| 256 | 256 | check_irq(); |
| 257 | 257 | } |
| 258 | 258 | |
| 259 | 259 | void ncr5380n_device::function_complete() |
| 260 | 260 | { |
| 261 | 261 | state = IDLE; |
| 262 | | // istatus |= I_FUNCTION; |
| 262 | // istatus |= I_FUNCTION; |
| 263 | 263 | check_irq(); |
| 264 | 264 | } |
| 265 | 265 | |
| 266 | 266 | void ncr5380n_device::bus_complete() |
| 267 | 267 | { |
| 268 | 268 | state = IDLE; |
| 269 | | // istatus |= I_BUS; |
| 269 | // istatus |= I_BUS; |
| 270 | 270 | check_irq(); |
| 271 | 271 | } |
| 272 | 272 | |
| r25514 | r25515 | |
| 309 | 309 | // asserting to drive the data bus? |
| 310 | 310 | if ((data & IC_DBUS) && !(m_icommand & IC_DBUS)) |
| 311 | 311 | { |
| 312 | | // printf("%s: driving data bus with %02x\n", tag(), m_outdata); |
| 312 | // printf("%s: driving data bus with %02x\n", tag(), m_outdata); |
| 313 | 313 | scsi_bus->data_w(scsi_refid, m_outdata); |
| 314 | 314 | delay(2); |
| 315 | 315 | } |
| r25514 | r25515 | |
| 327 | 327 | (data & IC_SEL ? S_SEL : 0) | |
| 328 | 328 | (data & IC_ATN ? S_ATN : 0); |
| 329 | 329 | |
| 330 | | // printf("%s: changing control lines %04x\n", tag(), newdata); |
| 330 | // printf("%s: changing control lines %04x\n", tag(), newdata); |
| 331 | 331 | scsi_bus->ctrl_w(scsi_refid, newdata, S_RST|S_ACK|S_BSY|S_SEL|S_ATN); |
| 332 | 332 | } |
| 333 | 333 | |
| r25514 | r25515 | |
| 342 | 342 | |
| 343 | 343 | WRITE8_MEMBER(ncr5380n_device::mode_w) |
| 344 | 344 | { |
| 345 | | // printf("%s: mode_w %02x (%08x)\n", tag(), data, space.device().safe_pc()); |
| 345 | // printf("%s: mode_w %02x (%08x)\n", tag(), data, space.device().safe_pc()); |
| 346 | 346 | // arbitration bit being set? |
| 347 | 347 | if ((data & MODE_ARBITRATE) && !(m_mode & MODE_ARBITRATE)) |
| 348 | 348 | { |
| 349 | | // if SEL is selected and the assert SEL bit in the initiator |
| 349 | // if SEL is selected and the assert SEL bit in the initiator |
| 350 | 350 | // command register is clear, fail |
| 351 | 351 | if ((scsi_bus->ctrl_r() & S_SEL) && !(m_icommand & IC_SEL)) |
| 352 | 352 | { |
| 353 | | // printf("arbitration lost, ctrl = %x, m_icommand&IC_SEL = %x\n", scsi_bus->ctrl_r(), m_icommand & IC_SEL); |
| 354 | | m_icommand &= ~IC_ARBITRATION; |
| 355 | 353 | m_icommand |= IC_ARBLOST; |
| 356 | 354 | } |
| 357 | 355 | else |
| 358 | 356 | { |
| 359 | 357 | seq = 0; |
| 360 | | // state = DISC_SEL_ARBITRATION; |
| 358 | // state = DISC_SEL_ARBITRATION; |
| 361 | 359 | arbitrate(); |
| 362 | 360 | } |
| 363 | 361 | } |
| 364 | | |
| 362 | else if (!(data & MODE_ARBITRATE) && (m_mode & MODE_ARBITRATE)) |
| 363 | { |
| 364 | // arbitration in progress bit ONLY clears when the host disables arbitration. (thanks, Zilog Z8530 manual!) |
| 365 | // the Apple II High Speed SCSI Card boot code explicitly requires this. |
| 366 | m_icommand &= ~ IC_ARBITRATION; |
| 367 | } |
| 365 | 368 | m_mode = data; |
| 366 | 369 | } |
| 367 | 370 | |
| 368 | 371 | READ8_MEMBER(ncr5380n_device::command_r) |
| 369 | 372 | { |
| 370 | | // logerror("%s: command_r %02x (%08x)\n", tag(), m_tcommand, space.device().safe_pc()); |
| 373 | // logerror("%s: command_r %02x (%08x)\n", tag(), m_tcommand, space.device().safe_pc()); |
| 371 | 374 | return m_tcommand; |
| 372 | 375 | } |
| 373 | 376 | |
| 374 | 377 | WRITE8_MEMBER(ncr5380n_device::command_w) |
| 375 | 378 | { |
| 376 | | // printf("%s: command_w %02x (%08x)\n", tag(), data, space.device().safe_pc()); |
| 379 | // printf("%s: command_w %02x (%08x)\n", tag(), data, space.device().safe_pc()); |
| 377 | 380 | m_tcommand = data; |
| 378 | 381 | |
| 379 | 382 | // recalculate phase match |
| r25514 | r25515 | |
| 387 | 390 | void ncr5380n_device::arbitrate() |
| 388 | 391 | { |
| 389 | 392 | m_icommand &= ~IC_ARBLOST; |
| 390 | | m_icommand |= IC_ARBITRATION; |
| 393 | m_icommand |= IC_ARBITRATION; // set in progress flag |
| 391 | 394 | state = (state & STATE_MASK) | (ARB_COMPLETE << SUB_SHIFT); |
| 392 | 395 | scsi_bus->data_w(scsi_refid, m_outdata); |
| 393 | 396 | scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY); |
| r25514 | r25515 | |
| 407 | 410 | READ8_MEMBER(ncr5380n_device::status_r) |
| 408 | 411 | { |
| 409 | 412 | UINT32 ctrl = scsi_bus->ctrl_r(); |
| 410 | | UINT8 res = status | |
| 413 | UINT8 res = status | |
| 411 | 414 | (ctrl & S_RST ? ST_RST : 0) | |
| 412 | 415 | (ctrl & S_BSY ? ST_BSY : 0) | |
| 413 | 416 | (ctrl & S_REQ ? ST_REQ : 0) | |
| r25514 | r25515 | |
| 416 | 419 | (ctrl & S_INP ? ST_IO : 0) | |
| 417 | 420 | (ctrl & S_SEL ? ST_SEL : 0); |
| 418 | 421 | |
| 419 | | // printf("%s: status_r %02x (%08x)\n", tag(), res, space.device().safe_pc()); |
| 422 | // printf("%s: status_r %02x (%08x)\n", tag(), res, space.device().safe_pc()); |
| 420 | 423 | return res; |
| 421 | 424 | } |
| 422 | 425 | |
| r25514 | r25515 | |
| 431 | 434 | (ctrl & S_ATN ? BAS_ATN : 0) | |
| 432 | 435 | (ctrl & S_ACK ? BAS_ACK : 0); |
| 433 | 436 | |
| 434 | | // printf("%s: busandstatus_r %02x (%08x)\n", tag(), res, space.device().safe_pc()); |
| 437 | // printf("%s: busandstatus_r %02x (%08x)\n", tag(), res, space.device().safe_pc()); |
| 435 | 438 | |
| 436 | 439 | return res; |
| 437 | 440 | } |
| r25514 | r25515 | |
| 444 | 447 | |
| 445 | 448 | READ8_MEMBER(ncr5380n_device::indata_r) |
| 446 | 449 | { |
| 447 | | return 0; |
| 450 | return dma_r(); |
| 448 | 451 | } |
| 449 | 452 | |
| 450 | 453 | WRITE8_MEMBER(ncr5380n_device::startdmatargetrx_w) |
| r25514 | r25515 | |
| 459 | 462 | |
| 460 | 463 | WRITE8_MEMBER(ncr5380n_device::startdmainitrx_w) |
| 461 | 464 | { |
| 462 | | // printf("%02x to start dma initiator Rx\n", data); |
| 465 | // printf("%02x to start dma initiator Rx\n", data); |
| 463 | 466 | recv_byte(); |
| 464 | 467 | } |
| 465 | 468 | |
| r25514 | r25515 | |
| 491 | 494 | |
| 492 | 495 | void ncr5380n_device::drq_set() |
| 493 | 496 | { |
| 494 | | if(!drq) |
| 497 | if(!drq) |
| 495 | 498 | { |
| 496 | 499 | drq = true; |
| 497 | 500 | m_busstatus |= BAS_DMAREQUEST; |
| r25514 | r25515 | |
| 501 | 504 | |
| 502 | 505 | void ncr5380n_device::drq_clear() |
| 503 | 506 | { |
| 504 | | if(drq) |
| 507 | if(drq) |
| 505 | 508 | { |
| 506 | 509 | drq = false; |
| 507 | 510 | m_busstatus &= ~BAS_DMAREQUEST; |
| r25514 | r25515 | |
| 543 | 546 | |
| 544 | 547 | WRITE8_MEMBER(ncr5380n_device::write) |
| 545 | 548 | { |
| 549 | // printf("%x to 5380 @ %x\n", data, offset); |
| 546 | 550 | switch (offset & 7) |
| 547 | 551 | { |
| 548 | 552 | case 0: |
| r25514 | r25515 | |
| 578 | 582 | break; |
| 579 | 583 | } |
| 580 | 584 | } |
| 585 | |