1 // Uart.cxx - NS16550 UART component. -*- C++ -*-
3 // Copyright (C) 1999, 2000 Red Hat.
4 // This file is part of SID and is licensed under the GPL.
5 // See the file COPYING.SID for conditions for redistribution.
9 #include <sidpinattrutil.h>
12 using sid::component_library;
13 using sid::COMPONENT_LIBRARY_MAGIC;
16 RBR = 0, // Rx Buff, Addr=0 && DLAB=0, read-only
17 IER = 1, // Interrupt Enable, Addr=1 && DLAB=0
18 IIR = 2, // Interrupt ID, read-only
19 LCR = 3, // Line Control Reg
20 MCR = 4, // Modem Control Reg
21 LSR = 5, // Line Status Reg
22 MSR = 6, // Modem Status Reg
23 SCR = 7, // Scratch Reg
24 DLL = 8, // Divisor LSB, Addr=0 && DLAB=1
25 DLM = 9, // Divisor MSB, Addr=1 && DLAB=1
26 THR = 10, // Tx Hold, Addr=0 && DLAB=0, write-only
27 FCR = 11, // FIFO Control, write-only
30 enum intr_enable_bitpos {
31 IER_ERBFI = 0, // Enable Rx buffer full
32 IER_ETBEI = 1, // Enable Tx buffer empty
33 IER_ELSI = 2, // Enable line status
34 IER_EDSSI = 3 // Enable data set status
38 IIR_NPEND = 0, // Interrupt pending - active low
39 IIR_ID = 1, // Interrupt ID (3 bits)
40 IIR_FTL = 6 // FIFO Trigger Level (2 bits)
43 #define IIR_ID_MASK 0xf1
46 IIR_RLS_ID = 0x6, // Rx Line Status
47 IIR_RDA_ID = 0x4, // Rx Data Available
48 IIR_CTI_ID = 0x0c, // Character Timeout Indicator
49 IIR_TBE_ID = 0x2, // Tx Buffer Empty
50 IIR_DSS_ID = 0x0 // Data Set Status
53 enum intr_pend_mask { // The bits for the INTR pending mask
61 enum line_ctl_bitpos {
62 LCR_BITS = 0, // # of data bits (bits 0 and 1)
63 LCR_STOP = 2, // # of stop bits
64 LCR_PE = 3, // Parity Enable
65 LCR_PSEL = 4, // Parity Select
66 LCR_STICK = 5, // Stick parity
67 LCR_BRK = 6, // Break control
68 LCR_DLAB = 7 // Divisor Latch Access Bit
71 enum line_status_bitpos {
72 LSR_DR = 0, // Data ready
73 LSR_OE = 1, // Overrun error
74 LSR_PE = 2, // Parity error
75 LSR_FE = 3, // Framing error
76 LSR_BI = 4, // Break indicator
77 LSR_THRE = 5, // Tx Holding Reg empty
78 LSR_TEMT = 6, // Tx empty
79 LSR_ERF = 7 // Error in Rx FIFO
83 FCR_FE = 0, // FIFO enable
84 FCR_RFR = 1, // Rx FIFO reset
85 FCR_TFR = 2, // Tx FIFO reset
86 FCR_DMA = 3, // DMA mode select
87 FCR_RT = 6 // Rx Trigger (2 bits)
90 enum modem_ctl_bitpos {
91 MCR_DTR = 0, // Data Tx ready
92 MCR_RTS = 1, // Request to send
95 MCR_LOOPBACK = 4 // loopback mode
98 enum modem_status_bitpos {
99 MSR_DCTS = 0, // The first four are "delta" flags
103 MSR_CCTS = 4, // The next four are "complement" flags
109 const int FIFO_TOP = 0;
112 bit_set( unsigned char& val, int pos ) {
113 val |= (1 << pos); // set bit at position pos
117 bit_clear( unsigned char& val, int pos ) {
118 val &= ~(1 << pos); // clear bit at position pos
122 bit_test( unsigned char val, int pos ) {
123 return (val & (1 << pos)); // return non-zero if bit at pos is 1
127 bit_value( unsigned char val, int pos ) {
128 return ((val >> pos) & 1); // return bit at pos as its own int
132 // streaming operators for Uart::regs type
134 class attribute_coder_uart_reg: public attribute_coder_base
136 typedef host_int_1 Value;
140 attribute_coder_uart_reg(Value* p): ptr(p) {}
143 make_attribute() const
148 // I haven't actually tested this
149 std::ostringstream stream;
150 stream << std::hex << std::setw(2) << std::setfill('0') << r;
155 stream << std::hex << std::setw(2) << std::setfill('0') << r;
156 std::string result(stream.str(), stream.pcount());
160 #error "need <sstream> or <strstream.h>!"
166 sid::component::status
167 parse_attribute(const std::string& str)
171 std::istringstream stream (str);
172 stream >> std::hex >> r;
175 istrstream stream (str.data(), str.length());
176 stream >> std::hex >> r;
178 #error "need <sstream> or <strstream.h>!"
181 if( stream.good() ) {
183 return component::ok;
186 cerr << "UART register set failed :-(" << endl;
187 return component::bad_value;
194 :triggerpoint_manager(this),
195 busif( this, &(Uart::busReadHandler), &(Uart::busWriteHandler) ),
196 sin( this, &Uart::sinHandler ),
197 reset_pin( this, &(Uart::reset) ),
198 rx_timeout( "rx-timeout", this, &Uart::rxWatchdog ),
199 tx_timeout( "tx-timeout", this, &Uart::txWatchdog )
204 sio_framing_p = true;
206 in_fifo_length = out_fifo_length = 16; // Defaults for 16550
207 update_fifo_lengths ();
209 add_attribute( "sio-framing?", &sio_framing_p, "setting" );
210 add_attribute_notify( "in-fifo-length", &in_fifo_length,
211 this, &Uart::update_fifo_lengths,
213 add_attribute_notify( "out-fifo-length", &out_fifo_length,
214 this, &Uart::update_fifo_lengths,
217 add_bus( "Bus", &busif );
219 add_pin( "Sin", &sin );
220 add_pin( "Sout", &sout );
221 add_attribute_ro_value( "tk tty", string("hw-visual-tty"), "gui");
223 add_pin( "INTR", &intr );
224 intr.set_active_high();
227 add_pin( "TxRdy", &txrdy );
228 add_pin( "RxRdy", &rxrdy );
229 add_pin( "RTS", &rts );
230 add_pin( "DTR", &dtr );
231 add_pin( "OUT1", &out1 );
232 add_pin( "OUT2", &out2 );
234 add_pin( "CTS", &cts );
235 cts.init( this, &Uart::ctsHandler );
237 add_pin( "DSR", &dsr );
238 dsr.init( this, &Uart::dsrHandler );
240 add_pin( "DCD", &dcd );
241 dcd.init( this, &Uart::dcdHandler );
243 add_pin( "RI", &ri );
244 ri.init( this, &Uart::riHandler );
246 add_pin( "Reset", &reset_pin );
248 /* Pick the timeout as 10 msec. Its supposed to be proportional to the
249 * baud rate, but since our baud rate is infinitely fast, we just pick
250 * something to make sure we get control back eventually.
253 add_attribute( "timeout", &timeout_incr );
260 add_attribute_virtual ("state-snapshot", this,
262 &Uart::restore_state );
266 // The following functions contain what used to be within Uart::Uart().
269 Uart :: Uart_ctor_0()
272 add_attribute_coder("RBR", new attribute_coder_uart_reg(& this->regs[RBR]),
274 triggerpoint_manager.add_watchable_value ("RBR", & this->regs[RBR]);
275 categorize ("RBR", "watchable");
277 add_attribute_coder("IER", new attribute_coder_uart_reg(& this->regs[IER]),
279 triggerpoint_manager.add_watchable_value ("IER", & this->regs[IER]);
280 categorize ("IER", "watchable");
282 add_attribute_coder("IIR", new attribute_coder_uart_reg(& this->regs[IIR]),
284 triggerpoint_manager.add_watchable_value ("IIR", & this->regs[IIR]);
285 categorize ("IIR", "watchable");
287 add_attribute_coder("LCR", new attribute_coder_uart_reg(& this->regs[LCR]),
289 triggerpoint_manager.add_watchable_value ("LCR", & this->regs[LCR]);
290 categorize ("LCR", "watchable");
292 add_attribute_coder("MCR", new attribute_coder_uart_reg(& this->regs[MCR]),
294 triggerpoint_manager.add_watchable_value ("MCR", & this->regs[MCR]);
295 categorize ("MCR", "watchable");
301 Uart :: Uart_ctor_1()
303 add_attribute_coder("LSR", new attribute_coder_uart_reg(& this->regs[LSR]),
305 triggerpoint_manager.add_watchable_value ("LSR", & this->regs[LSR]);
306 categorize ("LSR", "watchable");
308 add_attribute_coder("MSR", new attribute_coder_uart_reg(& this->regs[MSR]),
310 triggerpoint_manager.add_watchable_value ("MSR", & this->regs[MSR]);
311 categorize ("MSR", "watchable");
313 add_attribute_coder("SCR", new attribute_coder_uart_reg(& this->regs[SCR]),
315 triggerpoint_manager.add_watchable_value ("SCR", & this->regs[SCR]);
316 categorize ("SCR", "watchable");
318 add_attribute_coder("DLL", new attribute_coder_uart_reg(& this->regs[DLL]),
320 triggerpoint_manager.add_watchable_value ("DLL", & this->regs[DLL]);
321 categorize ("DLL", "watchable");
323 add_attribute_coder("DLM", new attribute_coder_uart_reg(& this->regs[DLM]),
325 triggerpoint_manager.add_watchable_value ("DLM", & this->regs[DLM]);
326 categorize ("DLM", "watchable");
331 Uart :: Uart_ctor_2()
333 add_attribute_coder("THR", new attribute_coder_uart_reg(& this->regs[THR]),
335 triggerpoint_manager.add_watchable_value ("THR", & this->regs[THR]);
336 categorize ("THR", "watchable");
338 add_attribute_coder("FCR", new attribute_coder_uart_reg(& this->regs[FCR]),
340 triggerpoint_manager.add_watchable_value ("FCR", & this->regs[FCR]);
341 categorize ("FCR", "watchable");
343 add_attribute( "Sin", &sin, "pin" );
344 triggerpoint_manager.add_watchable_attribute ("Sin");
345 categorize ("Sin", "watchable");
347 add_attribute( "Sout", &sout, "pin" );
348 triggerpoint_manager.add_watchable_attribute ("Sout");
349 categorize ("Sout", "watchable");
351 add_attribute( "Reset", &reset_pin, "pin" );
352 triggerpoint_manager.add_watchable_attribute ("Reset");
353 categorize ("Reset", "watchable");
355 add_attribute( "INTR", &intr, "pin" );
356 triggerpoint_manager.add_watchable_attribute ("INTR");
357 categorize ("INTR", "watchable");
362 Uart :: Uart_ctor_3()
364 add_attribute( "TxRDY", &txrdy, "pin" );
365 triggerpoint_manager.add_watchable_attribute ("TxRDY");
366 categorize ("TxRDY", "watchable");
368 add_attribute( "RxRDY", &rxrdy, "pin" );
369 triggerpoint_manager.add_watchable_attribute ("RxRDY");
370 categorize ("RxRDY", "watchable");
372 add_attribute( "RTS", &rts, "pin" );
373 triggerpoint_manager.add_watchable_attribute ("RTS");
374 categorize ("RTS", "watchable");
376 add_attribute( "DTR", &dtr, "pin" );
377 triggerpoint_manager.add_watchable_attribute ("DTR");
378 categorize ("DTR", "watchable");
380 add_attribute( "OUT1", &out1, "pin" );
381 triggerpoint_manager.add_watchable_attribute ("OUT1");
382 categorize ("OUT1", "watchable");
387 Uart :: Uart_ctor_4()
390 add_attribute( "OUT2", &out2, "pin" );
391 triggerpoint_manager.add_watchable_attribute ("OUT2");
392 categorize ("OUT2", "watchable");
394 add_attribute( "CTS", (binary_input_pin *) &cts, "pin" );
395 triggerpoint_manager.add_watchable_attribute ("CTS");
396 categorize ("CTS", "watchable");
398 add_attribute( "DSR", (binary_input_pin *) &dsr, "pin" );
399 triggerpoint_manager.add_watchable_attribute ("DSR");
400 categorize ("DSR", "watchable");
402 add_attribute( "RI", (binary_input_pin *) &ri, "pin" );
403 triggerpoint_manager.add_watchable_attribute ("RI");
404 categorize ("RI", "watchable");
406 add_attribute( "DCD", (binary_input_pin *) &dcd, "pin" );
407 triggerpoint_manager.add_watchable_attribute ("DCD");
408 categorize ("DCD", "watchable");
412 // The in_fifo_length and/or out_fifo_length members have been changed.
413 // Resize the fifo vectors to match.
415 Uart :: update_fifo_lengths() {
417 if (in_fifo_length < 1)
419 if (out_fifo_length < 1)
422 // Resize the vectors. Leftover values will be lost.
423 in_fifo.resize( in_fifo_length );
424 in_errs.resize( in_fifo_length );
425 out_fifo.resize( out_fifo_length );
427 // There were some pending bytes in there ...
428 if (in_cnt > in_fifo_length)
430 // Treat as overrun error
431 in_cnt = in_fifo_length - 1;
432 in_errs[in_cnt-1] = LSR_OE;
433 bit_set( regs[LSR], LSR_ERF );
439 Uart :: reset( host_int_4 ) {
440 // RBR and THR are not affected by reset
442 regs[IIR] = 1; // no pending interrupt yet
445 regs[LSR] = 0x60; // Tx side is empty
447 setModemStatusReg(); // set MSR
449 // DLL and DLM are not affected by reset
457 pending |= PEND_TX_RDY;
458 txrdy.on(); // ready to get a char
466 Uart::busReadHandler( host_int_4 index, host_int_1& p ) {
471 if( bit_test( regs[LCR], LCR_DLAB ) )
478 if( bit_test( regs[LCR], LCR_DLAB ) )
497 regs[LSR] &= 0xe1; // Clear per char status bits
498 pending &= ~(PEND_RX_ERR); // Clear pending status if error
500 // Deassert interrupt line if the LSR raised the interupt.
501 if( !(bit_test( regs[IIR], IIR_NPEND )) ) {
502 if( (regs[IIR] & ~(IIR_ID_MASK)) == IIR_RLS_ID ) {
503 // This one is done, but there could be more pending conditions
504 if( !setInterruptId() ) { // deassert IRQ
505 bit_set( regs[IIR], IIR_NPEND );
513 val = setModemStatusReg();
515 regs[MSR] &= 0xf0; // Clear delta bits
516 pending &= ~(PEND_MODEM); // Modem has no pending IRQ
518 // Deassert interrupt line if the modem raised the interupt.
519 if( !(bit_test( regs[IIR], IIR_NPEND )) ) {
520 if( (regs[IIR] & ~(IIR_ID_MASK)) == IIR_DSS_ID ) {
521 bit_set( regs[IIR], IIR_NPEND );
528 return sid::bus::unmapped; // illegal index
533 // check for triggerpoints
534 triggerpoint_manager.check_and_dispatch ();
540 Uart :: busWriteHandler( host_int_4 index, host_int_1 val ) {
543 if( bit_test( regs[LCR], LCR_DLAB ) )
550 if( bit_test( regs[LCR], LCR_DLAB ) )
553 regs[IER] = val & 0x0f;
555 if( setInterruptId() ) { // did we enable something that was pending?
556 if( bit_test( regs[IIR], IIR_NPEND) ) {
557 bit_clear( regs[IIR], IIR_NPEND );
561 else { // nothing enabled - turn off IRQ if on
562 /* This behavior is pointed out in the application notes, and is
563 * required because the INTR line is level oriented, but many chips
564 * are edge-sensitive to interrupt lines.
566 if( !(bit_test( regs[IIR], IIR_NPEND)) ) {
567 bit_set( regs[IIR], IIR_NPEND );
574 case 2: // FCR (write-only)
575 setFunctionReg( val );
584 setModemControlReg( val );
589 // What does it mean to write these registers?
593 return sid::bus::unmapped; // illegal index
596 // check for triggerpoints
597 triggerpoint_manager.check_and_dispatch ();
603 Uart :: setFunctionReg( unsigned char val ) {
606 if( bit_test( regs[FCR], FCR_FE ) && !(bit_test( val, FCR_FE )) ) {
607 // clearing FCR_FE disables and resets the FIFOs
611 for( i=0; i<in_fifo_length; i++ ) {
616 for( i=0; i<out_fifo_length; i++ )
619 regs[IIR] &= 0x3f; // Clear FIFO enable bits in IIR
622 if( !(bit_test( val, FCR_FE )) ) {
627 if( bit_test( val, FCR_RFR ) ) { // reset input FIFO
630 for( i=0; i<in_fifo_length; i++ ) {
636 if( bit_test( val, FCR_TFR ) ) { // reset output FIFO
639 for( i=0; i<out_fifo_length ; i++ )
644 regs[IIR] |= 0xc0; // Set FIFO enable bits in IIR
647 /* Check the interrupt sources in order to determine if an interrupt is
648 * warranted. Returns TRUE if an interrupt is required.
651 Uart :: setInterruptId() {
653 regs[IIR] &= IIR_ID_MASK; // Clear current id
655 if( pending & PEND_RX_ERR ) { // Rx Error
656 if( bit_test( regs[IER], IER_ELSI ) ) {
657 regs[IIR] |= IIR_RLS_ID;
662 if( pending & PEND_RX_RDY ) { // Rx ready
663 if( bit_test( regs[IER], IER_ERBFI ) ) {
664 regs[IIR] |= IIR_RDA_ID;
669 if( pending & PEND_RX_TO ) { // Input timeout
670 regs[IIR] |= IIR_CTI_ID; // Not enabled via IER
674 if( pending & PEND_TX_RDY ) { // Tx ready
675 if( bit_test( regs[IER], IER_ETBEI ) ) {
676 regs[IIR] |= IIR_TBE_ID;
681 if( pending & PEND_MODEM ) { // Modem status
682 if( bit_test( regs[IER], IER_EDSSI ) ) {
683 regs[IIR] |= IIR_DSS_ID;
692 /* genParity determines the parity bit for the low NBITS bits of VAL,
693 * according to the parity type specified by P. The routine returns
694 * VAL with the parity bit set in bit NBITS+1.
697 Uart :: genParity( unsigned val, int nbits, enum parity p ) const {
698 int i, ones_count = 0;
701 for( i=0; i<nbits; i++ ) {
708 if( p==EVEN_PARITY && (ones_count & 1) )
709 return val | (1 << nbits);
711 if( p==ODD_PARITY && !(ones_count & 1) )
712 return val | (1 << nbits);
717 /* checkParity checks that the parity bit in position NBITS+1 of VAL
718 * matches the parity type specified by P. The function returns zero
719 * if the parity bit is incorrect.
722 Uart :: checkParity( unsigned val, int nbits, enum parity p ) const {
723 int i, ones_count = 0;
725 for( i=0; i<(nbits+1); i++ ) {
732 if( p==EVEN_PARITY && (ones_count & 1) )
735 if( p==ODD_PARITY && !(ones_count & 1) )
741 // Number of data bits - indexed by bottom 2 bits of LCR
742 static int num_bits[4] = { 5, 6, 7, 8 };
745 Uart :: xmit( unsigned val ) {
746 int i, data_mask = 0;
747 int nbits = num_bits[regs[LCR] & 0x3];
750 if( bit_test( regs[FCR], FCR_FE ) && !bit_test( regs[FCR], FCR_DMA ) ) {
751 /* Single char DMA mode - turn off TxRDY. Note that in multi-char DMA
752 * TxRDY is always on because the Tx FIFO is never full.
759 for( i=0; i<nbits; i++ ) // build a mask for the data
760 data_mask |= (1 << i);
764 if( bit_test( regs[LCR], LCR_PE ) ) { // parity is enabled
765 if( bit_test( regs[LCR], LCR_STICK ) ) {
766 // Stick parity = 0 if EVEN, = 1 if ODD
767 if( !(bit_test( regs[LCR], LCR_PSEL )) )
770 else // no stick parity
771 val = genParity( val,nbits, (enum parity) bit_test(regs[LCR], LCR_PSEL) );
774 // XXX: Hey, what about out_fifo[] ?
777 sout.drive( val ); // send it
779 sout.drive( oval ); // send it without framing
781 regs[THR] = 0; // always empty because always sent
782 bit_set( regs[LSR], LSR_THRE );
783 bit_set( regs[LSR], LSR_TEMT );
785 if( bit_test( regs[FCR], FCR_FE ) && !bit_test( regs[FCR], FCR_DMA ) ) {
786 // Single char DMA mode - turn on TxRDY
790 /* The specs imply that the delay from write to TxRDY interrupt is just for
791 * FIFO mode, but I think it makes sense all the time. (We'll have to see
792 * what the chip does, of course :-)
794 tx_timeout.schedule_irregular( timeout_incr );
796 pending &= ~(PEND_TX_RDY); // the watchdog will set this
799 static int trigger_vals[4] = { 1, 4, 8, 14 }; // from FCR bits 6-7
802 Uart :: sinHandler( host_int_4 v ) {
803 int i, data_mask = 0;
804 int nbits = num_bits[regs[LCR] & 0x3];
807 if( in_cnt == in_fifo_length ) { // FIFO full
808 in_errs[in_cnt-1] = LSR_OE;
809 bit_set( regs[LSR], LSR_ERF );
811 // check for triggerpoints
812 triggerpoint_manager.check_and_dispatch ();
814 return; // drop the char
816 else if( !bit_test( regs[FCR], FCR_FE ) ) { // not in FIFO mode
817 if( in_cnt == 1 ) // already had a char
818 bit_set( in_errs[FIFO_TOP], LSR_OE ); // so it will be lost
820 in_cnt = 0; // always at the top of the FIFO
823 if( sio_framing_p ) // framing?
825 if( bit_test( regs[LCR], LCR_PE ) ) { // parity is enabled
826 if( bit_test( regs[LCR], LCR_STICK ) ) {
828 // Stick parity is on: 0 if EVEN parity selected; 1 otherwise
829 if( (bit_test( regs[LCR], LCR_PSEL )) ) {
830 if( bit_test( val, nbits ) )
831 bit_set( in_errs[in_cnt], LSR_PE );
834 else // regular parity
835 if( !checkParity( val, nbits, (enum parity)bit_test(regs[LCR],LCR_PSEL)) )
836 bit_set( in_errs[in_cnt], LSR_PE );
839 for( i=0; i<nbits; i++ ) // build a mask for the data
840 data_mask |= (1 << i);
846 // treat val as raw data value
849 in_fifo[in_cnt] = val;
852 /* The spec says that the errors are revealed when the char is at the
853 * top of the FIFO. If in_cnt == 0 then this char is at the top.
855 regs[LSR] &= 0x61; // set error bits
856 regs[LSR] |= in_errs[FIFO_TOP];
858 if( in_errs[FIFO_TOP] )
859 pending |= PEND_RX_ERR;
861 in_errs[FIFO_TOP] = 0; // done with them now
866 bit_set( regs[LSR], LSR_DR ); // Data now available
868 if( !bit_test( regs[FCR], FCR_FE ) ) { // Not in FIFO mode
869 pending |= PEND_RX_RDY;
871 rxrdy.on(); // Set the DMA line (mode 0)
874 int trigger = trigger_vals[(regs[FCR] & 0xc0) >> 6];
878 if( in_cnt>1 && in_errs[in_cnt-1] ) // did we just get an error?
879 bit_set( regs[LSR], LSR_ERF );
881 if( in_cnt >= trigger ) {
882 if( bit_test( regs[FCR], FCR_DMA ) )
883 rxrdy.on(); // Set the DMA line (mode 1)
885 pending |= PEND_RX_RDY;
887 else { // not at trigger point yet
888 if( !bit_test( regs[FCR], FCR_DMA ) )
889 rxrdy.on(); // Set the DMA line (mode 0)
891 // set up a callback in case no more chars come.
892 rx_timeout.schedule_irregular( timeout_incr );
896 if( setInterruptId() ) { // IRQ if enabled
897 bit_clear( regs[IIR], IIR_NPEND );
901 // check for triggerpoints
902 triggerpoint_manager.check_and_dispatch ();
909 regs[RBR] = in_fifo[FIFO_TOP]; // get the char at the top of the FIFO
911 --in_cnt; // one less in FIFO
913 if( in_cnt <= 0 ) { // emptied the FIFO
914 bit_clear( regs[LSR], LSR_DR );
916 pending &= ~(PEND_RX_RDY); // clear pending IRQ source
920 in_cnt = 0; // guard against multiple reads
922 else { // data still in FIFO
923 /* This looks inefficient, because we physically move all the characters
924 * one position up the FIFO. I originally did this with in/out pointers,
925 * but that fails for the following case: get 4 in, read 2, then get 14 in.
926 * The hardware should allow this, but its tough to get right with pointers.
928 for( i=0; i<in_cnt; i++ ) {
929 in_fifo[i] = in_fifo[i+1];
930 in_errs[i] = in_errs[i+1];
933 bit_set( regs[LSR], LSR_DR );
935 /* "Reveal" the next char's status in the LSR */
936 regs[LSR] &= 0x61; // mask out the per char errors
937 regs[LSR] |= in_errs[FIFO_TOP]; // and get the error for this char
939 if( in_errs[FIFO_TOP] )
940 pending |= PEND_RX_ERR;
942 in_errs[FIFO_TOP] = 0; // done with these errors
944 for( i=1; i<in_cnt; i++ ) {
946 bit_set( regs[LSR], LSR_ERF ); // error still to come
949 int trigger = trigger_vals[(regs[FCR] & 0xc0) >> 6];
951 if( in_cnt < trigger ) // dropped below trigger point
952 pending &= ~PEND_RX_RDY;
957 if( setInterruptId() ) { // possibly new Rx errors
958 bit_clear( regs[IIR], IIR_NPEND ); // assert interrupt
961 else { // possibly out of data
962 bit_set( regs[IIR], IIR_NPEND ); // deassert interrupt
969 /* rxWatchdog is a scheduler callback function. It is triggered from FIFO
970 * mode when no input characters have arrived during the specified timeout.
972 * This functionality is important to make sure no characters are stranded
973 * in the FIFO with interrupts enabled. For example, if the interrupt trigger
974 * point is set at 8 and the last packet only contains 6 characters, they
975 * would remain in the FIFO indefinitely unless a timeout is set.
978 Uart :: rxWatchdog() {
979 pending |= PEND_RX_TO; // timed out on receive
981 if( setInterruptId() ) {
982 bit_clear( regs[IIR], IIR_NPEND ); // assert interrupt
985 // check for triggerpoints
986 triggerpoint_manager.check_and_dispatch ();
990 /* txWatchdog is a scheduler callback function. It is triggered in FIFO mode
991 * when Tx interrupts are enabled, and a character is output but no subsequent
992 * character is output within a given timeout period.
994 * This functionality prevents back-to-back interrupts when the Transmit
995 * Holding Register is empty and there is room in the Transmit FIFO. When
996 * the Holding Register is written the character is immediately transferred
997 * to the FIFO, which would generate another Tx Ready interrupt, possibly
998 * while the CPU is still handling the current Tx Ready interrupt. The timeout
999 * is set to delay the subsequent Tx Ready interrupt.
1002 Uart :: txWatchdog() {
1003 pending |= PEND_TX_RDY; // timed out on xmit
1005 if( setInterruptId() ) {
1006 bit_clear( regs[IIR], IIR_NPEND ); // assert interrupt
1009 // check for triggerpoints
1010 triggerpoint_manager.check_and_dispatch ();
1014 /* Set the delta/complement bit for the corresponding modem input line.
1015 * BIT is the position of the complement bit; VAL is treated as the boolean
1016 * _ACTIVE_LOW_ chip input.
1018 * This routine relies on the fact that the delta bit group is in the first
1019 * 4 bits, and that the complement bit group is in the second four bits.
1022 Uart :: modemLineChange( int bit, int val ) {
1023 assert( (bit >= 4) && (bit <= 7) );
1025 bit_set( regs[MSR], bit - 4 );
1028 bit_clear( regs[MSR], bit );
1030 bit_set( regs[MSR], bit );
1034 Uart :: setModemControlReg( unsigned char val ) {
1035 unsigned char changed = regs[MCR] ^ val;
1037 regs[MCR] = val & 0x1f; // Top 3 bits are always 0
1039 if( bit_test( changed, MCR_LOOPBACK ) ) {
1040 if( bit_test( val, MCR_LOOPBACK ) ) { // switch to Loopback
1041 bit_set( regs[MCR], MCR_LOOPBACK );
1043 dtr.off(); // The external lines are de-asserted
1048 // Note: The MSR reg flags are updated when that register is read.
1051 bit_clear( regs[MCR], MCR_LOOPBACK );
1053 dtr.set( bit_value( val, MCR_DTR ) );
1054 rts.set( bit_value( val, MCR_RTS ) );
1055 out1.set( bit_value( val, MCR_OUT1 ) );
1056 out2.set( bit_value( val, MCR_OUT2 ) );
1059 /* It is unclear to me what's supposed to happen to the MSR delta bits
1060 * when we switch to/from loopback.
1065 if( bit_test( val, MCR_LOOPBACK ) ) { // in loopback mode
1066 /* Have to complement the logical bit values to get external active-low
1067 * signal values expected by modemLineChange
1069 if( bit_test( changed, MCR_DTR ) )
1070 modemLineChange( MSR_CDSR, ~(bit_value( val, MCR_DTR )) );
1072 if( bit_test( changed, MCR_RTS ) )
1073 modemLineChange( MSR_CCTS, ~(bit_value( val, MCR_RTS )) );
1075 if( bit_test( changed, MCR_OUT1 ) )
1076 modemLineChange( MSR_CRI, ~(bit_value( val, MCR_OUT1 )) );
1078 if( bit_test( changed, MCR_OUT2 ) )
1079 modemLineChange( MSR_CDCD, ~(bit_value( val, MCR_OUT2 )) );
1081 if( changed & 0x0f )
1084 else { // not in loopback mode
1085 dtr.set( bit_value( val, MCR_DTR ) );
1086 rts.set( bit_value( val, MCR_RTS ) );
1087 out1.set( bit_value( val, MCR_OUT1 ) );
1088 out2.set( bit_value( val, MCR_OUT2 ) );
1093 Uart :: setModemStatusReg() {
1094 bit_clear( regs[MSR], MSR_CCTS );
1095 bit_clear( regs[MSR], MSR_CDSR );
1096 bit_clear( regs[MSR], MSR_CRI );
1097 bit_clear( regs[MSR], MSR_CDCD );
1099 if( bit_test( regs[MCR], MCR_LOOPBACK ) ) { // in loop-back mode
1100 if( bit_test( regs[MCR], MCR_RTS ) )
1101 bit_set( regs[MSR], MSR_CCTS );
1103 if( bit_test( regs[MCR], MCR_DTR ) )
1104 bit_set( regs[MSR], MSR_CDSR );
1106 if( bit_test( regs[MCR], MCR_OUT1 ) )
1107 bit_set( regs[MSR], MSR_CRI );
1109 if( bit_test( regs[MCR], MCR_OUT2 ) )
1110 bit_set( regs[MSR], MSR_CDCD );
1112 else { // not in loopback mode
1113 if( cts.state() == binary_pin_active )
1114 bit_set( regs[MSR], MSR_CCTS );
1116 if( dsr.state() == binary_pin_active )
1117 bit_set( regs[MSR], MSR_CDSR );
1119 if( ri.state() == binary_pin_active )
1120 bit_set( regs[MSR], MSR_CRI );
1122 if( dcd.state() == binary_pin_active )
1123 bit_set( regs[MSR], MSR_CDCD );
1130 Uart :: checkModemIRQ() {
1131 pending |= PEND_MODEM;
1133 if( bit_test( regs[IER], IER_EDSSI ) ) {
1134 // Modem interrupts are enabled
1136 if( (bit_test( regs[IIR], IIR_NPEND )) ) {
1137 // There is no IRQ currently pending - raise the interrupt
1139 regs[IIR] = (regs[IIR] & IIR_ID_MASK); // Set the ID as the modem
1140 bit_clear( regs[IIR], IIR_NPEND ); // Set pending bit (low)
1146 // Callback for CTS pin
1148 Uart :: ctsHandler( int val ) {
1149 if( !(bit_test( regs[MCR], MCR_LOOPBACK )) ) // ignore if loop-back
1150 modemLineChange( MSR_CCTS, val );
1154 // check for triggerpoints
1155 triggerpoint_manager.check_and_dispatch ();
1158 // Callback for DSR pin
1160 Uart :: dsrHandler( int val ) {
1161 if( !(bit_test( regs[MCR], MCR_LOOPBACK )) ) // ignore if loop-back
1162 modemLineChange( MSR_CDSR, val );
1166 // check for triggerpoints
1167 triggerpoint_manager.check_and_dispatch ();
1170 // Callback for RI pin
1172 Uart :: riHandler( int val ) {
1173 if( !(bit_test( regs[MCR], MCR_LOOPBACK )) ) {
1174 if( bit_test( regs[MSR], MSR_CRI ) && val )
1175 bit_set( regs[MSR], MSR_TERI ); // Set on 0 to 1 transition
1178 bit_clear( regs[MSR], MSR_CRI );
1180 bit_set( regs[MSR], MSR_CRI );
1185 // check for triggerpoints
1186 triggerpoint_manager.check_and_dispatch ();
1189 // Callback for DCD pin
1191 Uart :: dcdHandler( int val ) {
1192 if( !(bit_test( regs[MCR], MCR_LOOPBACK )) ) // ignore if loop-back
1193 modemLineChange( MSR_CDCD, val );
1197 // check for triggerpoints
1198 triggerpoint_manager.check_and_dispatch ();
1204 operator << (ostream& op, const Uart& copy_obj)
1206 // Store Internal Registers First
1208 for (int reg_num = 0; reg_num < (UART_NUM_REGS - 1); ++reg_num)
1209 op << (host_int_4) copy_obj.regs[reg_num] << " ";
1210 op << (host_int_4) copy_obj.regs[UART_NUM_REGS - 1] << ":";
1212 op << "FifoLengths " << copy_obj.in_fifo_length << " " << copy_obj.out_fifo_length << ":";
1214 op << "InFCh " << copy_obj.in_cnt;
1215 if (copy_obj.in_cnt > 0)
1218 for (int in_chars = 0; in_chars < (copy_obj.in_cnt - 1); ++in_chars)
1219 op << copy_obj.in_fifo[in_chars] << " ";
1220 op << copy_obj.in_fifo[copy_obj.in_cnt - 1];
1223 for (int in_error = 0; in_error < (copy_obj.in_cnt - 1); ++in_error)
1224 op << (host_int_4) copy_obj.in_errs[in_error] << " ";
1225 op << (host_int_4) copy_obj.in_errs[copy_obj.in_cnt -1];
1227 op << ":"; // Seperator.
1229 op << "OutFCh " << copy_obj.out_cnt;
1230 if (copy_obj.out_cnt > 0)
1233 for ( int out_chars = 0; out_chars < (copy_obj.out_cnt - 1 ); ++out_chars)
1234 op << copy_obj.out_fifo[out_chars] << " ";
1235 op << copy_obj.out_fifo[copy_obj.out_cnt - 1];
1237 op << ":"; // Seperator
1238 op << "Pend " << copy_obj.pending << ":" ;
1239 op << "Frame " << copy_obj.sio_framing_p << ":";
1240 op << "rxpin " << copy_obj.rxrdy.recall() << ":";
1241 op << "txpin " << copy_obj.txrdy.recall() << ":";
1242 op << "TOCount " << copy_obj.timeout_incr;
1248 operator >> (istream& ip, Uart& ovwrite_obj)
1253 if ( coding != "InterRegs")
1255 ip.setstate(ios::badbit);
1258 host_int_4 reg_value;
1259 for (int reg_num = 0; reg_num < UART_NUM_REGS; ++reg_num)
1263 ovwrite_obj.regs[reg_num] = reg_value;
1265 ovwrite_obj.busWriteHandler(MCR, (host_int_1)reg_value); // Will drive o/p pins too
1268 if ( bit_test(ovwrite_obj.regs[IIR], IIR_NPEND) )
1269 ovwrite_obj.intr.off();
1270 else // Raise interrupt
1271 ovwrite_obj.intr.on();
1277 ip.setstate(ios::badbit);
1283 if (coding != "FifoLengths")
1285 ip.setstate(ios::badbit);
1288 ip >> ovwrite_obj.in_fifo_length;
1289 ip >> ovwrite_obj.out_fifo_length;
1293 ip.setstate(ios::badbit);
1296 ovwrite_obj.update_fifo_lengths ();
1299 if (coding != "InFCh")
1301 ip.setstate(ios::badbit);
1304 ip >> ovwrite_obj.in_cnt;
1305 if ( ovwrite_obj.in_cnt > 0 )
1308 if (coding != "InFifo")
1310 ip.setstate(ios::badbit);
1313 for (unsigned int i = 0; i < ovwrite_obj.in_cnt; ++i)
1314 ip >> ovwrite_obj.in_fifo[i];
1317 if (coding != "InErr")
1319 ip.setstate(ios::badbit);
1324 for (unsigned int j= 0; j < ovwrite_obj.in_cnt; ++j)
1327 ovwrite_obj.in_errs[j] = err_val;
1333 ip.setstate(ios::badbit);
1338 if ( coding != "OutFCh")
1340 ip.setstate(ios::badbit);
1343 ip >> ovwrite_obj.out_cnt;
1344 if ( ovwrite_obj.out_cnt > 0 )
1347 if (coding != "OutFifo")
1349 ip.setstate(ios::badbit);
1352 for (unsigned int k = 0; k < ovwrite_obj.out_cnt; ++k )
1353 ip >> ovwrite_obj.out_fifo[k];
1358 ip.setstate(ios::badbit);
1363 if ( coding != "Pend")
1365 ip.setstate(ios::badbit);
1368 ip >> ovwrite_obj.pending;
1372 ip.setstate(ios::badbit);
1377 if (coding != "Frame")
1379 ip.setstate(ios::badbit);
1382 ip >> ovwrite_obj.sio_framing_p;
1386 ip.setstate(ios::badbit);
1390 host_int_4 temppin_val =0;
1392 if (coding != "rxpin")
1394 ip.setstate(ios::badbit);
1398 ovwrite_obj.rxrdy.drive(temppin_val);
1402 ip.setstate(ios::badbit);
1407 if (coding != "txpin")
1409 ip.setstate(ios::badbit);
1413 ovwrite_obj.txrdy.drive(temppin_val);
1417 ip.setstate(ios::badbit);
1422 if (coding != "TOCount")
1424 ip.setstate(ios::badbit);
1427 ip >> ovwrite_obj.timeout_incr;
1433 // Standard DLL wrapper-stuff
1435 static vector<string>
1438 vector<string> types;
1439 types.push_back(string("hw-uart-ns16550"));
1444 UartCreate(const string& typeName)
1446 if(typeName == "hw-uart-ns16550")
1454 UartDelete(component* c)
1456 delete dynamic_cast<Uart*>(c);
1461 extern const component_library uart_component_library;
1463 const component_library uart_component_library DLLEXPORT =
1465 COMPONENT_LIBRARY_MAGIC,