Previous 199869 Revisions Next

r26352 Friday 22nd November, 2013 at 09:40:09 UTC by Jürgen Buchmüller
Trying to sort the ether task a49 PROM flags mess
[/branches/alto2/src/emu/cpu/alto2]a2ether.c a2ether.h

branches/alto2/src/emu/cpu/alto2/a2ether.c
r26351r26352
8383/**
8484 * @brief BPROM; P3601-1; 265x4 enet.a49 "AFIFO"
8585 *
86 * Perhaps try with the contents of the display FIFO, as it is
87 * the same type and the display FIFO has the same size.
88 *
8986 * FIFO control
9087 *
9188 * a49: P3601-1; 256x4; "AFIFO"
r26351r26352
104101 * outputs active low
105102 * ----------------------------
106103 * D0 (12) BE'    (buffer empty)
107 * D1 (11) BNE'   (buffer next empty ?)
108 * D2 (10) BNNE'  (buffer next next empty ?)
104 * D1 (11) BNE'   (buffer nearly empty)
105 * D2 (10) BNNE'  (buffer next nearly empty)
109106 * D3  (9) BF'    (buffer full)
110107 */
111108static const prom_load_t pl_enet_a49 =
r26351r26352
161158#define   GET_ETH_IT(st)         X_BIT(st,16,15)            //!< hardware status: IT flip flop & ISRFULL'
162159#define   PUT_ETH_IT(st,val)      X_WRBITS(st,16,15,15,val)
163160
164//! PROM ether.u49; buffer empty (active low)
165#define   ETHER_A49_BE   (m_ether_a49[16 * m_eth.fifo_wr + m_eth.fifo_rd] & (1 << 0))
161#define   BE(a49)   ((a49 & ether_a49_BE) ? 1 : 0)      //! buffer empty
162#define   BNE(a49)  ((a49 & ether_a49_BNE) ? 1 : 0)      //! buffer next empty
163#define   BNNE(a49) ((a49 & ether_a49_BNNE) ? 1 : 0)      //! buffer next next empty
164#define   BF(a49)   ((a49 & ether_a49_BF) ? 1 : 0)      //! buffer full
166165
167//! PROM ether.u49; buffer next(?) empty (active low)
168#define   ETHER_A49_BNE   (m_ether_a49[16 * m_eth.fifo_wr + m_eth.fifo_rd] & (1 << 1))
169
170//! PROM ether.u49; buffer next next(?) empty (active low)
171#define   ETHER_A49_BNNE   (m_ether_a49[16 * m_eth.fifo_wr + m_eth.fifo_rd] & (1 << 2))
172
173//! PROM ether.u49; buffer full (active low)
174#define   ETHER_A49_BF   (m_ether_a49[16 * m_eth.fifo_wr + m_eth.fifo_rd] & (1 << 3))
175
176166#define   BREATHLEN   ALTO2_ETHER_PACKET_SIZE   //!< ethernet packet length
177167#define   BREATHADDR   0177400               //!< destination and source
178168#define   BREATHTYPE   0000602               //!< ethernet packet type
r26351r26352
258248 */
259249void alto2_cpu_device::eth_wakeup()
260250{
261   register int etac = m_task == task_ether;
262
263   LOG((LOG_ETH,0,"eth_wakeup: ibusy=%d obusy=%d ", GET_ETH_IBUSY(m_eth.status), GET_ETH_OBUSY(m_eth.status)));
264   register int busy = GET_ETH_IBUSY(m_eth.status) | GET_ETH_OBUSY(m_eth.status);
251   register int st = m_eth.status;
252   LOG((LOG_ETH,0,"IBUSY=%d OBUSY=%d ", GET_ETH_IBUSY(st), GET_ETH_OBUSY(st)));
253   UINT8 busy = GET_ETH_IBUSY(st) | GET_ETH_OBUSY(st);
265254   if (0 == busy) {
266255      // if not busy, reset the FIFO read and write counters
267256      m_eth.fifo_rd = 0;
r26351r26352
276265    *   output gone
277266    *   input gone
278267    */
279   if (GET_ETH_IDL(m_eth.status)) {
280      LOG((LOG_ETH,0,"post (input data late)\n"));
268   if (GET_ETH_IDL(st)) {
269      LOG((LOG_ETH,0,"POST (input data late)\n"));
281270      m_task_wakeup |= 1 << task_ether;
282271      return;
283272   }
284   if (GET_ETH_OCMD(m_eth.status)) {
285      LOG((LOG_ETH,0,"post (output command)\n"));
273   if (GET_ETH_OCMD(st)) {
274      LOG((LOG_ETH,0,"POST (output command)\n"));
286275      m_task_wakeup |= 1 << task_ether;
287276      return;
288277   }
289   if (GET_ETH_ICMD(m_eth.status)) {
290      LOG((LOG_ETH,0,"post (input command)\n"));
278   if (GET_ETH_ICMD(st)) {
279      LOG((LOG_ETH,0,"POST (input command)\n"));
291280      m_task_wakeup |= 1 << task_ether;
292281      return;
293282   }
294   if (GET_ETH_OGONE(m_eth.status)) {
295      LOG((LOG_ETH,0,"post (output gone)\n"));
283   if (GET_ETH_OGONE(st)) {
284      LOG((LOG_ETH,0,"POST (output gone)\n"));
296285      m_task_wakeup |= 1 << task_ether;
297286      return;
298287   }
299   if (GET_ETH_IGONE(m_eth.status)) {
300      LOG((LOG_ETH,0,"post (input gone)\n"));
288   if (GET_ETH_IGONE(st)) {
289      LOG((LOG_ETH,0,"POST (input gone)\n"));
301290      m_task_wakeup |= 1 << task_ether;
302291      return;
303292   }
r26351r26352
305294   /*
306295    * IDR (input data ready) conditions to wakeup the Ether task (AND):
307296    *   IBUSY   input busy
308    *   BNNE    buffer next next empty
309    *   BNE     buffer next empty
297    *   BNNE    buffer next nearly empty
298    *   BNE     buffer nearly empty
310299    *   ETAC    ether task active
311300    *
312301    * IDR' = (IBUSY & (BNNE & (BNE' & ETAC')')')'
313302    */
314   register int idr = GET_ETH_IBUSY(m_eth.status) && (ETHER_A49_BNNE || (ETHER_A49_BNE == 0 && etac));
303   UINT8 a49 = m_ether_a49[16 * m_eth.fifo_rd + m_eth.fifo_wr];
304   UINT8 etac = m_task == task_ether ? 0 : 1;
305   UINT8 idr = GET_ETH_IBUSY(st) & ~(~BNNE(a49) & ~(BNE(a49) & etac));
315306   if (idr) {
316307      m_task_wakeup |= 1 << task_ether;
317308      LOG((LOG_ETH,0,"input data ready\n"));
r26351r26352
327318    *
328319    * ODR'   = (OBUSY & OEOT' & (BF' & WLF')')'
329320    */
330   register int odr = GET_ETH_OBUSY(m_eth.status) && (GET_ETH_OEOT(m_eth.status) || (GET_ETH_WLF(m_eth.status) && ETHER_A49_BF == 0));
321   UINT8 odr = GET_ETH_OBUSY(st) & ~(~GET_ETH_OEOT(st) & ~(BF(a49) & ~GET_ETH_WLF(st)));
331322   if (odr) {
332323      m_task_wakeup |= 1 << task_ether;
333324      LOG((LOG_ETH,0,"output data ready\n"));
r26351r26352
342333    */
343334   if (m_ewfct) {
344335      m_task_wakeup |= 1 << task_ether;
345      LOG((LOG_ETH,0,"ether wake function\n"));
336      LOG((LOG_ETH,0,"EWFCT (ether wake function)\n"));
346337      return;
347338   }
348339
349340   // otherwise no more wakeups for the ether task
350   LOG((LOG_ETH,0,"-/-\n"));
341   LOG((LOG_ETH,0,"stop wake\n"));
351342   m_task_wakeup &= ~(1 << task_ether);
352343}
353344
r26351r26352
449440 */
450441UINT32 f9401_7(UINT32 crc, UINT32 data)
451442{
452   int i;
453   for (i = 0; i < 16; i++) {
454      crc <<= 1;
455      if (data & (1 << 15))
456         crc ^= (1 << 10) | (1 << 3) | (1 << 0);
457      data <<= 1;
458   }
443   static const UINT32 XOR = (1 << 10) | (1 << 3) | (1 << 0);
444   crc ^= data;
445   for (int i = 0; i < 16; i++)
446      crc = (crc >> 1) ^ ((crc & 1) ? XOR : 0);
459447   return crc & 0177777;
460448}
461449
r26351r26352
470458   UINT32 data;
471459
472460   if (arg == 0) {
473      // first word: set the IBUSY flip flop
461      // on the first word set the IBUSY flip flop
474462      PUT_ETH_IBUSY(m_eth.status, 1);
475463      m_eth.rx_count = 0;
476464   }
477465
478   data = duckbreath_data[arg++];
466   if (arg >= BREATHLEN) {
467      // CRC after the data
468      data = m_eth.rx_crc;
469      arg++;
470   } else {
471      // next data word
472      data = duckbreath_data[arg++];
473   }
479474   m_eth.rx_crc = f9401_7(m_eth.rx_crc, data);
480
481475   m_eth.fifo[m_eth.fifo_wr] = data;
482476   m_eth.fifo_wr = (m_eth.fifo_wr + 1) % ALTO2_ETHER_FIFO_SIZE;
483477
484   if (m_eth.rx_count < ALTO2_ETHER_PACKET_SIZE)
485      m_eth.rx_packet[m_eth.rx_count] = data;
486   m_eth.rx_count++;
478//   PUT_ETH_WLF(m_eth.status, 1);   // set WLF (write latch full)?
487479
488   PUT_ETH_WLF(m_eth.status, 1);
489   if (ETHER_A49_BF == 0) {
490      /* fifo is overrun: set input data late flip flop */
491      PUT_ETH_IDL(m_eth.status, 1);
492   }
480   UINT8 a49 = m_ether_a49[16 * m_eth.fifo_rd + m_eth.fifo_wr];
481   if (0 == BF(a49))
482      PUT_ETH_IDL(m_eth.status, 1);   // fifo is overrun: set input data late flip flop
493483
494   if (arg == BREATHLEN) {
484   if (arg > BREATHLEN) {
495485      /*
496       * last word: reset the receiver CRC
497       *
498486       * TODO: if data comes from some other source,
499487       * compare our CRC with the next word received
500488       * and set the CRC error flag if they differ.
501489       */
502490      m_eth.rx_crc = 0;
503
504      // set the IGONE flip flop
505      PUT_ETH_IGONE(m_eth.status, 1);
506#if   DEBUG_PACKETS
507      dump_packet(m_eth.rx_packet, 0, m_eth.rx_count);
508#endif
491      PUT_ETH_IGONE(m_eth.status, 1);      // set the IGONE flip flop
509492      m_eth.rx_timer->adjust(attotime::from_seconds(m_duckbreath_sec), 0);
510493   } else {
511494      // receive at a rate of 5.44us per word
r26351r26352
517500/**
518501 * @brief transmit data from the FIFO to <nirvana for now>
519502 *
520 * @param id timer id
503 * @param ptr unused pointer
521504 * @param arg word count if >= 0, -1 if CRC is to be transmitted (last word)
522505 */
523506void alto2_cpu_device::tx_packet(void* ptr, INT32 arg)
r26351r26352
528511   if (-1 == arg) {
529512      m_eth.tx_timer->reset();
530513      LOG((LOG_ETH,0," CRC:%06o\n", m_eth.tx_crc));
531#if   DEBUG_PACKETS
532      dump_packet(m_eth.tx_packet, 0, m_eth.tx_count);
533#endif
534514      // TODO: send the CRC as final word of the packet
535515      m_eth.tx_crc = 0;
536516      PUT_ETH_OGONE(m_eth.status, 1);      // set the OGONE flip flop
r26351r26352
542522   m_eth.tx_crc = f9401_7(m_eth.tx_crc, data);
543523   m_eth.fifo_rd = (m_eth.fifo_rd + 1) % ALTO2_ETHER_FIFO_SIZE;
544524
545   if (m_eth.tx_count < ALTO2_ETHER_PACKET_SIZE)
546      m_eth.tx_packet[m_eth.tx_count] = data;
547   m_eth.tx_count++;
548
549   // is the FIFO empty now?
550   if (ETHER_A49_BE) {
551      /* clear the OBUSY and WLF flip flops */
525   UINT8 a49 = m_ether_a49[16 * m_eth.fifo_rd + m_eth.fifo_wr];
526   if (0 == BE(a49)) {
527      // the FIFO is empty now: clear the OBUSY and WLF flip flops
552528      PUT_ETH_OBUSY(m_eth.status, 0);
553529      PUT_ETH_WLF(m_eth.status, 0);
554530      m_eth.tx_timer->adjust(attotime::from_usec(5.44), -1);
555      eth_wakeup();
556      return;
531   } else {
532      // transmit teh next word after 5.44µs
533      m_eth.tx_timer->adjust(attotime::from_usec(5.44), arg + 1);
557534   }
558
559   /* transmit teh next word after 5.44µs */
560   m_eth.tx_timer->adjust(attotime::from_usec(5.44), arg + 1);
561535   eth_wakeup();
562536}
563537
r26351r26352
568542{
569543   PUT_ETH_ICMD(m_eth.status, X_BIT(m_bus,16,14));
570544   PUT_ETH_OCMD(m_eth.status, X_BIT(m_bus,16,15));
571   if (GET_ETH_ICMD(m_eth.status) || GET_ETH_OCMD(m_eth.status))
572      m_task_wakeup |= 1 << task_ether;
545   LOG((LOG_ETH,3, "   STARTF; ICMD=%u OCMD=%u\n", GET_ETH_ICMD(m_eth.status), GET_ETH_ICMD(m_eth.status)));
546   eth_wakeup();
573547}
574548
575549/**
r26351r26352
581555void alto2_cpu_device::bs_early_eidfct()
582556{
583557   UINT16 r = m_eth.fifo[m_eth.fifo_rd];
584
585558   LOG((LOG_ETH,3, "   ←EIDFCT; pull %06o from FIFO[%02o]\n", r, m_eth.fifo_rd));
586559   m_eth.fifo_rd = (m_eth.fifo_rd + 1) % ALTO2_ETHER_FIFO_SIZE;
587560   m_bus &= r;
561
562#if   DEBUG_PACKETS
563   if (m_eth.rx_count < ALTO2_ETHER_PACKET_SIZE)
564      m_eth.rx_packet[m_eth.rx_count] = r;
565   m_eth.rx_count++;
566   if (ALTO2_ETHER_PACKET_SIZE == m_eth.rx_count) {
567      dump_packet(m_eth.rx_packet, 0, m_eth.rx_count);
568      m_eth.rx_count = 0;
569   }
570#endif
588571   eth_wakeup();
589572}
590573
r26351r26352
627610void alto2_cpu_device::f1_early_epfct()
628611{
629612   UINT16 r = ~X_RDBITS(m_eth.status,16,10,15) & 0177777;
613   m_eth.status = 0;
614   m_eth.tx_count = 0;
615   eth_wakeup();
630616
631617   LOG((LOG_ETH,3, "   ←EPFCT; BUS[8-15] = STATUS (%#o)\n", r));
632   LOG((LOG_ETH,5, "      IDL     : %u\n", GET_ETH_IDL(m_eth.status)));
633   LOG((LOG_ETH,5, "      COLL    : %u\n", GET_ETH_COLL(m_eth.status)));
634   LOG((LOG_ETH,5, "      CRC     : %u\n", GET_ETH_CRC(m_eth.status)));
635   LOG((LOG_ETH,5, "      ICMD    : %u\n", GET_ETH_ICMD(m_eth.status)));
636   LOG((LOG_ETH,5, "      OCMD    : %u\n", GET_ETH_OCMD(m_eth.status)));
637   LOG((LOG_ETH,5, "      IT      : %u\n", GET_ETH_IT(m_eth.status)));
618   LOG((LOG_ETH,5, "      IDL'    : %u\n", GET_ETH_IDL(r)));
619   LOG((LOG_ETH,5, "      COLL'   : %u\n", GET_ETH_COLL(r)));
620   LOG((LOG_ETH,5, "      CRC'    : %u\n", GET_ETH_CRC(r)));
621   LOG((LOG_ETH,5, "      ICMD'   : %u\n", GET_ETH_ICMD(r)));
622   LOG((LOG_ETH,5, "      OCMD'   : %u\n", GET_ETH_OCMD(r)));
623   LOG((LOG_ETH,5, "      IT'     : %u\n", GET_ETH_IT(r)));
638624
639625   m_bus &= r;
640
641   m_eth.status = 0;
642   m_eth.tx_count = 0;
643   eth_wakeup();
644626}
645627
646628/**
r26351r26352
665647 *
666648 * Loads the FIFO from BUS[0-15], then increments the write
667649 * pointer at the end of the cycle.
650 *
651 * Comment from the micro code:
652 *<PRE>
653 * Ether Output Data Function - EODFCT.  Copy the bus into the
654 * interface data buffer, increment the write pointer, clears wakeup
655 * request if the buffer is now nearly full (one slot available).
656 *</PRE>
668657 */
669658void alto2_cpu_device::f2_late_eodfct()
670659{
671660   LOG((LOG_ETH,3, "   EODFCT←; push %06o into FIFO[%02o]\n", m_bus, m_eth.fifo_wr));
672
673661   m_eth.fifo[m_eth.fifo_wr] = m_bus;
674662   m_eth.fifo_wr = (m_eth.fifo_wr + 1) % ALTO2_ETHER_FIFO_SIZE;
675663
676   PUT_ETH_WLF(m_eth.status, 1);
677   PUT_ETH_OBUSY(m_eth.status, 1);
678   // if the FIFO is full, kick off the timer
679   if (0 == ETHER_A49_BF)
664#if   DEBUG_PACKETS
665   if (m_eth.tx_count < ALTO2_ETHER_PACKET_SIZE)
666      m_eth.tx_packet[m_eth.tx_count] = m_bus;
667   m_eth.tx_count++;
668   if (ALTO2_ETHER_PACKET_SIZE == m_eth.tx_count) {
669      dump_packet(m_eth.tx_packet, 0, m_eth.tx_count);
670      m_eth.tx_count = 0;
671   }
672#endif
673
674   PUT_ETH_WLF(m_eth.status, 1);         // set WLF (write latch full)
675   PUT_ETH_OBUSY(m_eth.status, 1);         // set OBUSY (output busy)
676   eth_wakeup();
677   // if the FIFO is full, stop wakeup and kick off the timer
678   UINT8 a49 = m_ether_a49[16 * m_eth.fifo_rd + m_eth.fifo_wr];
679   if (0 == BF(a49)) {
680      m_task_wakeup &= ~(1 << task_ether);
680681      m_eth.tx_timer->adjust(attotime::from_usec(5.44), 0);
681   eth_wakeup();
682   }
682683}
683684
684685/**
r26351r26352
692693void alto2_cpu_device::f2_late_eosfct()
693694{
694695   LOG((LOG_ETH,3, "   EOSFCT\n"));
695   PUT_ETH_WLF(m_eth.status, 0);
696   PUT_ETH_OBUSY(m_eth.status, 0);
696   PUT_ETH_WLF(m_eth.status, 1);
697   PUT_ETH_OBUSY(m_eth.status, 1);
697698   eth_wakeup();
698699}
699700
r26351r26352
746747{
747748   UINT16 r = 0;
748749   X_WRBITS(r,10,6,6, GET_ETH_COLL(m_eth.status));
749   X_WRBITS(r,10,7,7, GET_ETH_IDL(m_eth.status) |
750      GET_ETH_ICMD(m_eth.status) |
751      GET_ETH_OCMD(m_eth.status) |
752      GET_ETH_IGONE(m_eth.status) |
753      GET_ETH_OGONE(m_eth.status));
750   X_WRBITS(r,10,7,7,
751          GET_ETH_IDL(m_eth.status) |
752          GET_ETH_ICMD(m_eth.status) |
753          GET_ETH_OCMD(m_eth.status) |
754          GET_ETH_IGONE(m_eth.status) |
755          GET_ETH_OGONE(m_eth.status));
754756   LOG((LOG_ETH,3, "   EBFCT; NEXT ... (%#o | %#o)\n", m_next2, r));
755757   m_next2 |= r;
756758}
r26351r26352
758760/**
759761 * @brief f2_ecbfct late: ethernet countdown branch function
760762 *
763 * The BE' (buffer empty) signal is output D0 of PROM a49
761764 * ORs a one into NEXT[7] if the FIFO is not empty.
762765 */
763766void alto2_cpu_device::f2_late_ecbfct()
764767{
765768   UINT16 r = 0;
766   /* TODO: the BE' (buffer empty) signal is output D0 of PROM a49 */
767   X_WRBITS(r,10,7,7,ETHER_A49_BE);
769   UINT8 a49 = m_ether_a49[16 * m_eth.fifo_rd + m_eth.fifo_wr];
770   X_WRBITS(r,10,7,7,~BE(a49));
768771   LOG((LOG_ETH,3, "   ECBFCT; NEXT[7] = FIFO %sempty (%#o | %#o)\n", r ? "not " : "is ", m_next2, r));
769772   m_next2 |= r;
770773}
r26351r26352
780783void alto2_cpu_device::f2_late_eisfct()
781784{
782785   LOG((LOG_ETH,3, "   EISFCT\n"));
783   PUT_ETH_IBUSY(m_eth.status, 0);
786   PUT_ETH_IBUSY(m_eth.status, 1);
784787   eth_wakeup();
785788}
786789
branches/alto2/src/emu/cpu/alto2/a2ether.h
r26351r26352
4242UINT8* m_ether_a41;                        //!< BPROM; P3601-1; 256x4; enet.a41 "PE1"
4343UINT8* m_ether_a42;                        //!< BPROM; P3601-1; 256x4; enet.a42 "PE2"
4444UINT8* m_ether_a49;                        //!< BPROM; P3601-1; 265x4 enet.a49 "AFIFO"
45enum {
46   ether_a49_BE   = (1 << 0),               //!< buffer empty
47   ether_a49_BNE   = (1 << 1),               //!< buffer next empty
48   ether_a49_BNNE   = (1 << 2),               //!< buffer next next empty
49   ether_a49_BF   = (1 << 3)               //!< buffer full
50};
4551
4652static const int m_duckbreath_sec = 15;         //!< send duckbreath every 15 seconds
4753

Previous 199869 Revisions Next


© 1997-2024 The MAME Team