Previous 15994 Revisions Next

r14652 Tuesday 28th February, 2012 at 08:50:08 UTC by Miodrag Milanović
Support for the 16550 fifo and hook up for the avigo to the serial port (to test the 16550). [Carl]
[src/emu/machine]ins8250.c ins8250.h
[src/mess/drivers]avigo.c
[src/mess/includes]avigo.h

src/emu/machine/ins8250.c
r14651r14652
1919the BIOS dependent on the flaws being present, so subsequent parts like the
20208250A, 16450 or 16550 could not be used in the original IBM PC or IBM PC/XT.
2121
22The original 8250 pulses the interrupt line if a higher priority interrupt is
23cleared but a lower priority one is still active.  It also clears the tsre bit
24for a moment before loading the tsr from the thr.  These may be the bugs the
25PC and XT depend on as the 8250A and up fix them.
26
2227INS8250-B
2328This is the slower speed of the INS8250 made from NMOS technology. It contains
2429the same problems as the original INS8250.
r14651r14652
4550Same as NS16450 with a 16-byte send and receive buffer but the buffer design
4651was flawed and could not be reliably be used.
4752
53The 16550 sometimes will send more then one character over the bus from the fifo
54when the rbr is read making the rx fifo useless.  It's unlikely anything depends
55on this behavior.
56
4857NS16550A
4958Same as NS16550 with the buffer flaws corrected. The 16550A and its successors
5059have become the most popular UART design in the PC industry, mainly due to
r14651r14652
108117#define COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY 0x0002
109118#define COM_INT_PENDING_RECEIVER_LINE_STATUS 0x0004
110119#define COM_INT_PENDING_MODEM_STATUS_REGISTER 0x0008
120#define COM_INT_PENDING_CHAR_TIMEOUT 0x0011
111121
112122/* ints will continue to be set for as long as there are ints pending */
113123void ins8250_uart_device::update_interrupt()
r14651r14652
121131
122132      /* set int */
123133      state = 1;
124      m_regs.iir &= ~(0x04|0x02);
134      m_regs.iir &= ~(0x08|0x04|0x02);
125135
126136      /* highest to lowest */
127137      if (m_regs.ier & m_int_pending & COM_INT_PENDING_RECEIVER_LINE_STATUS)
128138         m_regs.iir |=0x04|0x02;
129139      else if (m_regs.ier & m_int_pending & COM_INT_PENDING_RECEIVED_DATA_AVAILABLE)
140      {
130141         m_regs.iir |=0x04;
142         if ((m_int_pending & COM_INT_PENDING_CHAR_TIMEOUT) == 0x11)
143            m_regs.iir |= 0x08;
144      }
131145      else if (m_regs.ier & m_int_pending & COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY)
132146         m_regs.iir |=0x02;
133147
r14651r14652
142156      /* no ints pending */
143157      m_regs.iir |= 0x01;
144158      /* priority level */
145      m_regs.iir &= ~(0x04|0x02);
159      m_regs.iir &= ~(0x08|0x04|0x02);
146160   }
147161
148162   /* set or clear the int */
r14651r14652
202216               trigger_int(COM_INT_PENDING_RECEIVED_DATA_AVAILABLE);
203217            }
204218            else
219            {
220               if((m_device_type >= TYPE_NS16550) && (m_regs.fcr & 1))
221                  push_tx(data);
222               clear_int(COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY);
205223               if(m_regs.lsr & 0x40)
206224                  tra_complete();
225            }
207226         }
208227         break;
209228      case 1:
r14651r14652
217236            m_regs.ier = data;
218237            update_interrupt();
219238         }
220            break;
239         break;
221240      case 2:
222            break;
241         set_fcr(data);
242         break;
223243      case 3:
224244         m_regs.lcr = data;
225245         switch ((m_regs.lcr>>3) & 7)
r14651r14652
313333            data = (m_regs.dl & 0xff);
314334         else
315335         {
336            if((m_device_type >= TYPE_NS16550) && (m_regs.fcr & 1) && !(m_regs.mcr & 0x10))
337               m_regs.rbr = pop_rx();
338            else
339            {
340               clear_int(COM_INT_PENDING_RECEIVED_DATA_AVAILABLE);
341               if( m_regs.lsr & 0x01 )
342                  m_regs.lsr &= ~0x01;
343            }
316344            data = m_regs.rbr;
317            if( m_regs.lsr & 0x01 )
318               m_regs.lsr &= ~0x01;      /* clear data ready status */
319
320            clear_int(COM_INT_PENDING_RECEIVED_DATA_AVAILABLE);
321345         }
322346         break;
323347      case 1:
r14651r14652
357381         break;
358382      case 7:
359383         data = m_regs.scr;
360            break;
384         break;
361385   }
362386    return data;
363387}
364388
389void ns16550_device::rcv_complete()
390{
391   if(!(m_regs.fcr & 1))
392      return ins8250_uart_device::rcv_complete();
393   
394   receive_register_extract();
395   
396   if(m_rnum == 16)
397   {
398      m_regs.lsr |= 0x02; //overrun
399      trigger_int(COM_INT_PENDING_RECEIVER_LINE_STATUS);
400      return;
401   }
402     
403   m_regs.lsr |= 0x01;
404   m_rfifo[m_rhead] = get_received_char();
405   ++m_rhead &= 0x0f;
406   m_rnum++;
407   if(m_rnum >= m_rintlvl)
408      trigger_int(COM_INT_PENDING_RECEIVED_DATA_AVAILABLE);
409   set_timer();
410}
411
412void ns16550_device::tra_complete()
413{
414   if(!(m_regs.fcr & 1))
415      return ins8250_uart_device::tra_complete();
416
417   if(m_ttail != m_thead)
418   {
419      transmit_register_setup(m_tfifo[m_ttail]);
420      ++m_ttail &= 0x0f;
421      m_regs.lsr &= ~0x40;
422      if(m_ttail == m_thead)
423      {
424         m_regs.lsr |= 0x20;
425         trigger_int(COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY);
426      }
427   }
428   else
429      m_regs.lsr |= 0x40;
430}
431
365432void ins8250_uart_device::rcv_complete()
366433{
367434   if(m_regs.lsr & 0x01)
r14651r14652
474541      memset(&m_out_out2_cb, 0, sizeof(m_out_out2_cb));
475542   }
476543}
544
545void ns16550_device::device_reset()
546{
547   memset(&m_rfifo, '\0', sizeof(m_rfifo));
548   memset(&m_tfifo, '\0', sizeof(m_tfifo));
549   m_rhead = m_rtail = m_rnum = 0;
550   m_thead = m_ttail = 0;
551   m_timeout->adjust(attotime::never);
552   ins8250_uart_device::device_reset();
553}
554
555void ns16550_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
556{
557   trigger_int(COM_INT_PENDING_CHAR_TIMEOUT);
558   m_timeout->adjust(attotime::never);
559}
560
561void ns16550_device::push_tx(UINT8 data)
562{
563   m_tfifo[m_thead] = data;
564   ++m_thead &= 0x0f;
565}
566
567UINT8 ns16550_device::pop_rx()
568{
569   UINT8 data = m_rfifo[m_rtail];
570   clear_int(COM_INT_PENDING_CHAR_TIMEOUT & ~1); // don't clear bit 1 yet
571   
572   if(m_rnum)
573   {
574      ++m_rtail &= 0x0f;
575      m_rnum--;
576   }
577   else
578      data = 0;
579   
580   if(m_rnum < m_rintlvl)
581      clear_int(COM_INT_PENDING_RECEIVED_DATA_AVAILABLE);
582
583   if(m_rnum)
584      set_timer();
585   else
586   {
587      m_timeout->adjust(attotime::never);
588      m_regs.lsr &= ~1;
589   }
590
591   return data;
592}
593
594void ns16550_device::set_fcr(UINT8 data)
595{
596   const int bytes_per_int[] = {1, 4, 8, 14};
597   if(!(data & 1))
598   {
599      m_regs.fcr = 0;
600      m_regs.iir &= ~0xc8;
601      return;
602   }
603   if(!(m_regs.fcr & 1) && (data & 1))
604      data |= 0x06;
605   if(data & 2)
606   {
607      memset(&m_rfifo, '\0', sizeof(m_rfifo));
608      m_rhead = m_rtail = m_rnum = 0;
609   }
610   if(data & 4)
611   {
612      memset(&m_tfifo, '\0', sizeof(m_tfifo));
613      m_thead = m_ttail = 0;
614   }
615   m_rintlvl = bytes_per_int[(data>>6)&3];
616   m_regs.iir |= 0xc0;
617   m_regs.fcr = data & ~0xc9;
618   m_regs.lsr |= 0x20;
619   trigger_int(COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY);
620}
src/emu/machine/ins8250.h
r14651r14652
4545   virtual void tra_complete();
4646   virtual void tra_callback();
4747
48   virtual void set_fcr(UINT8 data) {}
49   virtual void push_tx(UINT8 data) {}
50   virtual UINT8 pop_rx() { return 0; }
51
52   void trigger_int(int flag);
53   void clear_int(int flag);
54
4855   enum {
4956         TYPE_INS8250 = 0,
5057         TYPE_INS8250A,
r14651r14652
5360         TYPE_NS16550A,
5461         TYPE_PC16550D,
5562   };
56   int   m_device_type;
57private:
63   int m_device_type;
5864   struct {
5965      UINT8 thr;  /* 0 -W transmitter holding register */
6066      UINT8 rbr;  /* 0 R- receiver buffer register */
6167      UINT8 ier;  /* 1 RW interrupt enable register */
6268      UINT16 dl;  /* 0/1 RW divisor latch (if DLAB = 1) */
6369      UINT8 iir;  /* 2 R- interrupt identification register */
70      UINT8 fcr;
6471      UINT8 lcr;  /* 3 RW line control register (bit 7: DLAB) */
6572      UINT8 mcr;  /* 4 RW modem control register */
6673      UINT8 lsr;  /* 5 R- line status register */
6774      UINT8 msr;  /* 6 R- modem status register */
6875      UINT8 scr;  /* 7 RW scratch register */
6976   } m_regs;
77private:
7078   UINT8 m_int_pending;
7179
7280   devcb_resolved_write_line   m_out_tx_func;
r14651r14652
7886
7987   void update_interrupt();
8088   void update_clock();
81   void trigger_int(int flag);
82   void clear_int(int flag);
8389   void update_msr(int bit, UINT8 state);
8490};
8591
r14651r14652
99105{
100106public:
101107   ns16550_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
108protected:
109   virtual void device_start() { m_timeout = timer_alloc(); ins8250_uart_device::device_start(); }
110   virtual void device_reset();
111   virtual void rcv_complete();
112   virtual void tra_complete();
113   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
114   virtual void set_fcr(UINT8 data);
115   virtual void push_tx(UINT8 data);
116   virtual UINT8 pop_rx();
117private:
118   void set_timer() { m_timeout->adjust(attotime::from_hz((clock()*4*8)/(m_regs.dl*16))); }
119   int m_rintlvl;
120   UINT8 m_rfifo[16];
121   UINT8 m_tfifo[16];
122   int m_rhead, m_rtail, m_rnum;
123   int m_thead, m_ttail;
124   emu_timer *m_timeout;
102125};
103126
104127extern const device_type INS8250;
src/mess/includes/avigo.h
r14651r14652
1010#include "cpu/z80/z80.h"
1111#include "machine/rp5c01.h"
1212#include "machine/ins8250.h"
13#include "machine/serial.h"
14#include "machine/null_modem.h"
1315#include "machine/intelfsh.h"
1416#include "machine/nvram.h"
1517#include "sound/speaker.h"
r14651r14652
3032      : driver_device(mconfig, type, tag),
3133        m_maincpu(*this, "maincpu"),
3234        m_ram(*this, RAM_TAG),
33        m_speaker(*this, SPEAKER_TAG)
35        m_speaker(*this, SPEAKER_TAG),
36        m_uart(*this, "ns16550"),
37        m_serport(*this, "serport")
3438      { }
3539
3640   required_device<cpu_device> m_maincpu;
3741   required_device<ram_device> m_ram;
3842   required_device<device_t> m_speaker;
43   required_device<ns16550_device> m_uart;
44   required_device<rs232_port_device> m_serport;
3945
4046   // defined in drivers/avigo.c
4147   virtual void machine_start();
src/mess/drivers/avigo.c
r14651r14652
223223   refresh_ints();
224224}
225225
226
227
228226static const ins8250_interface avigo_com_interface =
229227{
230   DEVCB_NULL,
231   DEVCB_NULL,
232   DEVCB_NULL,
228   DEVCB_DEVICE_LINE_MEMBER("serport", serial_port_device, tx),
229   DEVCB_DEVICE_LINE_MEMBER("serport", rs232_port_device, dtr_w),
230   DEVCB_DEVICE_LINE_MEMBER("serport", rs232_port_device, rts_w),
233231   DEVCB_DRIVER_LINE_MEMBER(avigo_state, com_interrupt),
234232   DEVCB_NULL,
235233   DEVCB_NULL
236234};
237235
236static const rs232_port_interface avigo_serport_config =
237{
238   DEVCB_DEVICE_LINE_MEMBER("ns16550", ins8250_uart_device, rx_w),
239   DEVCB_DEVICE_LINE_MEMBER("ns16550", ins8250_uart_device, dcd_w),
240   DEVCB_DEVICE_LINE_MEMBER("ns16550", ins8250_uart_device, dsr_w),
241   DEVCB_DEVICE_LINE_MEMBER("ns16550", ins8250_uart_device, ri_w),
242   DEVCB_DEVICE_LINE_MEMBER("ns16550", ins8250_uart_device, cts_w)
243};
238244
239245void avigo_state::machine_reset()
240246{
r14651r14652
879885   memset(base, 0x00, size);
880886}
881887
888static SLOT_INTERFACE_START( avigo_com )
889   SLOT_INTERFACE("null_modem", NULL_MODEM)
890SLOT_INTERFACE_END
891
882892static MACHINE_CONFIG_START( avigo, avigo_state )
883893   /* basic machine hardware */
884894   MCFG_CPU_ADD("maincpu", Z80, 4000000)
r14651r14652
887897   MCFG_QUANTUM_TIME(attotime::from_hz(60))
888898
889899   MCFG_NS16550_ADD( "ns16550", avigo_com_interface, XTAL_1_8432MHz )
900   MCFG_RS232_PORT_ADD( "serport", avigo_serport_config, avigo_com, NULL, NULL )
890901
891902   /* video hardware */
892903   MCFG_SCREEN_ADD("screen", LCD)

Previous 15994 Revisions Next


© 1998-2018 The MESS Team