branches/alto2/src/emu/cpu/alto2/a2ether.c
r26372 | r26373 | |
290 | 290 | return; |
291 | 291 | } |
292 | 292 | |
293 | | /* |
294 | | * IDR (input data ready) conditions to wakeup the Ether task (AND): |
| 293 | /** |
| 294 | * IDR (input data ready) conditions to wakeup the Ether task |
| 295 | * signal meaining |
| 296 | * -------------------------------------- |
295 | 297 | * IBUSY input busy |
296 | 298 | * BNNE buffer next nearly empty |
297 | 299 | * BNE buffer nearly empty |
298 | 300 | * ETAC ether task active |
299 | 301 | * |
300 | | * IDR' = (IBUSY & (BNNE & (BNE' & ETAC')')')' |
| 302 | ************************************************************ |
| 303 | * +----+ |
| 304 | * BNE' >----|NAND| (i1) +----+ |
| 305 | * | o-------|NAND| (i2) +----+ |
| 306 | * ETAC' >----| | | o-------|NAND| |
| 307 | * +----+ ·---| | | o-----> IDR' |
| 308 | * | +----+ ·---| | |
| 309 | * +---+ | | +----+ |
| 310 | * BNNE' >----|INVo----· | |
| 311 | * +---+ | |
| 312 | * | |
| 313 | * IBUSY >--------------------------· |
| 314 | * |
| 315 | ************************************************************ |
301 | 316 | */ |
302 | | UINT8 a49 = m_ether_a49[16 * m_eth.fifo_rd + m_eth.fifo_wr]; |
303 | | UINT8 etac = m_task == task_ether ? 0 : 1; |
304 | | UINT8 idr = GET_ETH_IBUSY(st) & ~(~BNNE(a49) & ~(BNE(a49) & etac)); |
305 | | if (idr) { |
| 317 | UINT8 a49 = m_ether_a49[16 * m_eth.fifo_wr + m_eth.fifo_rd]; |
| 318 | UINT8 ETAC = m_task == task_ether ? 0 : 1; |
| 319 | UINT8 i1 = ~(BNE(a49) & ETAC); |
| 320 | UINT8 i2 = ~(~BNNE(a49) & i1); |
| 321 | UINT8 IDR = ~(GET_ETH_IBUSY(st) & i2); |
| 322 | if (0 == IDR) { |
306 | 323 | m_task_wakeup |= 1 << task_ether; |
307 | | LOG((LOG_ETH,0,"input data ready\n")); |
| 324 | LOG((LOG_ETH,0,"IDR (input data ready)\n")); |
308 | 325 | return; |
309 | 326 | } |
310 | 327 | |
311 | | /* |
312 | | * ODR (output data ready) conditions to wakeup the Ether task: |
313 | | * WLF write latch filled(?) |
| 328 | /** |
| 329 | * ODR (output data ready) conditions to wakeup the Ether task |
| 330 | * signal meaining |
| 331 | * -------------------------------------- |
| 332 | * WLF write latch full(?) |
314 | 333 | * BF buffer (FIFO) full |
315 | 334 | * OEOT output end of transmission |
316 | 335 | * OBUSY output busy |
| 336 | ************************************************************ |
| 337 | * +----+ |
| 338 | * WLF' >----|NAND| (o1) +----+ |
| 339 | * | o---------|NAND| |
| 340 | * BF' >----| | | | |
| 341 | * +----+ ·------| o----> ODR' |
| 342 | * | | | |
| 343 | * | ·---| | |
| 344 | * OEOT' >------------· | +----+ |
| 345 | * | |
| 346 | * | |
| 347 | * OBUSY >---------------· |
317 | 348 | * |
318 | | * ODR' = (OBUSY & OEOT' & (BF' & WLF')')' |
| 349 | ************************************************************ |
319 | 350 | */ |
320 | | UINT8 odr = GET_ETH_OBUSY(st) & ~(~GET_ETH_OEOT(st) & ~(BF(a49) & ~GET_ETH_WLF(st))); |
321 | | if (odr) { |
| 351 | UINT8 o1 = ~(~GET_ETH_WLF(st) & BF(a49)); |
| 352 | UINT8 ODR = ~(GET_ETH_OBUSY(st) & ~GET_ETH_OEOT(st) & o1); |
| 353 | if (0 == ODR) { |
322 | 354 | m_task_wakeup |= 1 << task_ether; |
323 | | LOG((LOG_ETH,0,"output data ready\n")); |
| 355 | LOG((LOG_ETH,0,"ODR (output data ready)\n")); |
324 | 356 | return; |
325 | 357 | } |
326 | 358 | |
r26372 | r26373 | |
474 | 506 | m_eth.fifo[m_eth.fifo_wr] = data; |
475 | 507 | m_eth.fifo_wr = (m_eth.fifo_wr + 1) % ALTO2_ETHER_FIFO_SIZE; |
476 | 508 | |
477 | | // PUT_ETH_WLF(m_eth.status, 1); // set WLF (write latch full)? |
| 509 | PUT_ETH_IT(m_eth.status, 1); // set IT (input shift register full ...)? |
478 | 510 | |
479 | | UINT8 a49 = m_ether_a49[16 * m_eth.fifo_rd + m_eth.fifo_wr]; |
| 511 | UINT8 a49 = m_ether_a49[16 * m_eth.fifo_wr + m_eth.fifo_rd]; |
480 | 512 | if (0 == BF(a49)) |
481 | 513 | PUT_ETH_IDL(m_eth.status, 1); // fifo is overrun: set input data late flip flop |
482 | 514 | |
r26372 | r26373 | |
521 | 553 | m_eth.tx_crc = f9401_7(m_eth.tx_crc, data); |
522 | 554 | m_eth.fifo_rd = (m_eth.fifo_rd + 1) % ALTO2_ETHER_FIFO_SIZE; |
523 | 555 | |
524 | | UINT8 a49 = m_ether_a49[16 * m_eth.fifo_rd + m_eth.fifo_wr]; |
| 556 | UINT8 a49 = m_ether_a49[16 * m_eth.fifo_wr + m_eth.fifo_rd]; |
525 | 557 | if (0 == BE(a49)) { |
526 | 558 | // the FIFO is empty now: clear the OBUSY and WLF flip flops |
527 | 559 | PUT_ETH_OBUSY(m_eth.status, 0); |
r26372 | r26373 | |
583 | 615 | * @brief ethernet input look function |
584 | 616 | * |
585 | 617 | * Gates the contents of the FIFO to BUS[0-15], but does not |
586 | | * increment the read pointer; |
| 618 | * increment the read pointer |
587 | 619 | */ |
588 | 620 | void alto2_cpu_device::f1_early_eilfct() |
589 | 621 | { |
r26372 | r26373 | |
608 | 640 | */ |
609 | 641 | void alto2_cpu_device::f1_early_epfct() |
610 | 642 | { |
611 | | UINT16 r = ~X_RDBITS(m_eth.status,16,10,15) & 0177777; |
| 643 | UINT16 r = 0177777; |
| 644 | UINT16 st = m_eth.status; |
612 | 645 | m_eth.status = 0; |
613 | 646 | m_eth.tx_count = 0; |
614 | | eth_wakeup(); |
615 | 647 | |
| 648 | X_WRBITS(r,16,10,10,~GET_ETH_IDL(st)); // BUS[10] = IDL (input data late) |
| 649 | X_WRBITS(r,16,11,11,~GET_ETH_COLL(st)); // BUS[11] = COLL (collision) |
| 650 | X_WRBITS(r,16,12,12,~GET_ETH_CRC(st)); // BUS[12] = CRC (CRC error) |
| 651 | X_WRBITS(r,16,13,13,~GET_ETH_ICMD(st)); // BUS[13] = ICMD (input command) |
| 652 | X_WRBITS(r,16,14,14,~GET_ETH_OCMD(st)); // BUS[13] = OCMD (output command) |
| 653 | X_WRBITS(r,16,15,15,~GET_ETH_IT(st)); // BUS[13] = IT (input ???) |
| 654 | m_bus &= r; |
| 655 | |
616 | 656 | LOG((LOG_ETH,3, " ←EPFCT; BUS[8-15] = STATUS (%#o)\n", r)); |
617 | 657 | LOG((LOG_ETH,5, " IDL' : %u\n", GET_ETH_IDL(r))); |
618 | 658 | LOG((LOG_ETH,5, " COLL' : %u\n", GET_ETH_COLL(r))); |
r26372 | r26373 | |
620 | 660 | LOG((LOG_ETH,5, " ICMD' : %u\n", GET_ETH_ICMD(r))); |
621 | 661 | LOG((LOG_ETH,5, " OCMD' : %u\n", GET_ETH_OCMD(r))); |
622 | 662 | LOG((LOG_ETH,5, " IT' : %u\n", GET_ETH_IT(r))); |
623 | | |
624 | | m_bus &= r; |
| 663 | eth_wakeup(); |
625 | 664 | } |
626 | 665 | |
627 | 666 | /** |
r26372 | r26373 | |
674 | 713 | PUT_ETH_OBUSY(m_eth.status, 1); // set OBUSY (output busy) |
675 | 714 | eth_wakeup(); |
676 | 715 | // if the FIFO is full, stop wakeup and kick off the timer |
677 | | UINT8 a49 = m_ether_a49[16 * m_eth.fifo_rd + m_eth.fifo_wr]; |
| 716 | UINT8 a49 = m_ether_a49[16 * m_eth.fifo_wr + m_eth.fifo_rd]; |
678 | 717 | if (0 == BF(a49)) { |
679 | 718 | m_task_wakeup &= ~(1 << task_ether); |
680 | 719 | m_eth.tx_timer->adjust(attotime::from_usec(5.44), 0); |
r26372 | r26373 | |
682 | 721 | } |
683 | 722 | |
684 | 723 | /** |
685 | | * @brief f2_eosfct late: ethernet output start function |
| 724 | * @brief ethernet output start function |
686 | 725 | * |
687 | 726 | * Sets the OBUSY flip flop in the interface, starting data |
688 | 727 | * wakeups to fill the FIFO for output. When the FIFO is full, |
r26372 | r26373 | |
698 | 737 | } |
699 | 738 | |
700 | 739 | /** |
701 | | * @brief f2_erbfct late: ethernet reset branch function |
| 740 | * @brief ethernet reset branch function |
702 | 741 | * |
703 | 742 | * This command dispatch function merges the ICMD and OCMD flip flops |
704 | 743 | * into NEXT[6-7]. These flip flops are the means of communication |
r26372 | r26373 | |
737 | 776 | * @brief ethernet branch function |
738 | 777 | * |
739 | 778 | * ORs a 1 into NEXT[6] if a collision is detected. |
740 | | * ORs a 1 into NEXT[7] if an input data late is detected, |
741 | | * or a SIO with AC0[14-15] non-zero is issued, |
742 | | * or if the transmitter is gone |
743 | | * or if the receiver is gone. |
| 779 | * ORs a 1 into NEXT[7] if |
| 780 | * an input data late is detected, |
| 781 | * or a SIO with AC0[14-15] non-zero is issued (ICMD or OCMD), |
| 782 | * or if the receiver is gone (IGONE) |
| 783 | * or if the transmitter is gone (OGONE). |
744 | 784 | */ |
745 | 785 | void alto2_cpu_device::f2_late_ebfct() |
746 | 786 | { |
r26372 | r26373 | |
757 | 797 | } |
758 | 798 | |
759 | 799 | /** |
760 | | * @brief f2_ecbfct late: ethernet countdown branch function |
| 800 | * @brief ethernet countdown branch function |
761 | 801 | * |
762 | 802 | * The BE' (buffer empty) signal is output D0 of PROM a49 |
763 | 803 | * ORs a one into NEXT[7] if the FIFO is not empty. |
r26372 | r26373 | |
765 | 805 | void alto2_cpu_device::f2_late_ecbfct() |
766 | 806 | { |
767 | 807 | UINT16 r = 0; |
768 | | UINT8 a49 = m_ether_a49[16 * m_eth.fifo_rd + m_eth.fifo_wr]; |
| 808 | UINT8 a49 = m_ether_a49[16 * m_eth.fifo_wr + m_eth.fifo_rd]; |
769 | 809 | X_WRBITS(r,10,7,7,~BE(a49)); |
770 | 810 | LOG((LOG_ETH,3, " ECBFCT; NEXT[7] = FIFO %sempty (%#o | %#o)\n", r ? "not " : "is ", m_next2, r)); |
771 | 811 | m_next2 |= r; |
772 | 812 | } |
773 | 813 | |
774 | 814 | /** |
775 | | * @brief f2_eisfct late: ethernet input start function |
| 815 | * @brief ethernet input start function |
776 | 816 | * |
777 | 817 | * Sets the IBUSY flip flop in the interface, causing it to hunt |
778 | 818 | * for the beginning of a packet: silence on the Ether followed |
r26372 | r26373 | |
831 | 871 | m_eth.tx_timer->reset(); |
832 | 872 | |
833 | 873 | m_eth.rx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(alto2_cpu_device::rx_breath_of_life),this)); |
834 | | if (m_eth.breath_of_life) |
835 | | m_eth.rx_timer->adjust(attotime::from_seconds(m_eth.breath_of_life), 0); |
836 | | else |
837 | | m_eth.rx_timer->reset(); |
| 874 | m_eth.rx_timer->reset(); |
838 | 875 | } |
839 | 876 | |
840 | 877 | void alto2_cpu_device::exit_ether() |
r26372 | r26373 | |
864 | 901 | if (config) |
865 | 902 | m_eth.breath_of_life = breath_of_life_sec[(config->read() >> 4) & 7]; |
866 | 903 | logerror("Ethernet breath_of_life %d sec\n", m_eth.breath_of_life); |
| 904 | if (m_eth.breath_of_life) |
| 905 | m_eth.rx_timer->adjust(attotime::from_seconds(m_eth.breath_of_life), 0); |
867 | 906 | } |