OSDN Git Service

* public snapshot of sid simulator
[pf3gnuchains/pf3gnuchains3x.git] / sid / component / uart / Uart.cxx
1 // Uart.cxx - NS16550 UART component.  -*- C++ -*-
2
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.
6
7 #include "Uart.h"
8
9 #include <sidpinattrutil.h>
10 #include <sidso.h>
11
12 using sid::component_library;
13 using sid::COMPONENT_LIBRARY_MAGIC;
14
15 enum reg_mnemonics {
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
28 };
29
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
35 };
36
37 enum intr_id_bitpos {
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)
41 };
42
43 #define IIR_ID_MASK     0xf1
44
45 enum intr_id {
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
51 };
52
53 enum intr_pend_mask {   // The bits for the INTR pending mask
54   PEND_RX_ERR   = 0x1,
55   PEND_RX_RDY   = 0x2,
56   PEND_RX_TO    = 0x4,
57   PEND_TX_RDY   = 0x8,
58   PEND_MODEM    = 0x10
59 };
60
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
69 };
70
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
80 };
81
82 enum fcn_ctl_bitpos {
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)
88 };
89
90 enum modem_ctl_bitpos {
91   MCR_DTR       = 0,    // Data Tx ready
92   MCR_RTS       = 1,    // Request to send
93   MCR_OUT1      = 2,
94   MCR_OUT2      = 3,
95   MCR_LOOPBACK  = 4     // loopback mode
96 };
97
98 enum modem_status_bitpos {
99   MSR_DCTS      = 0,    // The first four are "delta" flags
100   MSR_DDSR      = 1,
101   MSR_TERI      = 2,
102   MSR_DDCD      = 3,
103   MSR_CCTS      = 4,    // The next four are "complement" flags
104   MSR_CDSR      = 5,
105   MSR_CRI       = 6,
106   MSR_CDCD      = 7
107 };
108
109 const int FIFO_TOP = 0;
110
111 inline void
112 bit_set( unsigned char& val, int pos ) {
113   val |= (1 << pos);            // set bit at position pos
114 }
115
116 inline void
117 bit_clear( unsigned char& val, int pos ) {
118   val &= ~(1 << pos);           // clear bit at position pos
119 }
120
121 inline int
122 bit_test( unsigned char val, int pos ) {
123   return (val & (1 << pos));    // return non-zero if bit at pos is 1
124 }
125
126 inline int
127 bit_value( unsigned char val, int pos ) {
128   return ((val >> pos) & 1);    // return bit at pos as its own int
129 }
130
131
132 // streaming operators for Uart::regs type
133
134 class attribute_coder_uart_reg: public attribute_coder_base
135 {
136   typedef host_int_1 Value;
137   Value* ptr;
138
139 public:
140   attribute_coder_uart_reg(Value* p): ptr(p) {}
141
142   std::string
143   make_attribute() const
144     { 
145       int r = *ptr;
146       
147 #if HAVE_SSTREAM
148       // I haven't actually tested this
149       std::ostringstream stream;
150       stream << std::hex << std::setw(2) << std::setfill('0') << r;
151       return stream.str();
152 #else
153 #if HAVE_STRSTREAM_H
154       ostrstream stream;
155       stream << std::hex << std::setw(2) << std::setfill('0') << r;
156       std::string result(stream.str(), stream.pcount());
157       stream.freeze();
158       return result;
159 #else
160 #error "need <sstream> or <strstream.h>!"
161 #endif
162 #endif
163     }
164   
165
166   sid::component::status
167   parse_attribute(const std::string& str)
168     {
169       int r;
170 #if HAVE_SSTREAM
171       std::istringstream stream (str);
172       stream >> std::hex >> r;
173 #else
174 #if HAVE_STRSTREAM_H
175       istrstream stream (str.data(), str.length());
176       stream >> std::hex >> r;
177 #else
178 #error "need <sstream> or <strstream.h>!"
179 #endif
180 #endif
181       if( stream.good() ) {
182         *ptr = r;
183         return component::ok;
184       }
185       else {
186         cerr << "UART register set failed :-(" << endl;
187         return component::bad_value;
188       }
189     }
190 };
191
192
193 Uart :: Uart()
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 )
200 {
201   in_cnt = 0;
202   out_cnt = 0;
203   pending = 0;
204   sio_framing_p = true;
205
206   in_fifo_length = out_fifo_length = 16; // Defaults for 16550
207   update_fifo_lengths ();
208
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,
212                         "setting" );
213   add_attribute_notify( "out-fifo-length", &out_fifo_length, 
214                         this, &Uart::update_fifo_lengths,
215                         "setting" );
216
217   add_bus( "Bus", &busif );
218
219   add_pin( "Sin", &sin );
220   add_pin( "Sout", &sout );
221   add_attribute_ro_value( "tk tty", string("hw-visual-tty"), "gui");
222
223   add_pin( "INTR", &intr );
224   intr.set_active_high();
225   intr.off ();
226
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 );
233
234   add_pin( "CTS", &cts );
235   cts.init( this, &Uart::ctsHandler );
236
237   add_pin( "DSR", &dsr );
238   dsr.init( this, &Uart::dsrHandler );
239
240   add_pin( "DCD", &dcd );
241   dcd.init( this, &Uart::dcdHandler );
242
243   add_pin( "RI", &ri );
244   ri.init( this, &Uart::riHandler );
245
246   add_pin( "Reset", &reset_pin );
247
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.
251   */
252   timeout_incr = 10;
253   add_attribute( "timeout", &timeout_incr );
254
255   Uart_ctor_0();
256   Uart_ctor_1();
257   Uart_ctor_2();
258   Uart_ctor_3();
259   Uart_ctor_4();
260   add_attribute_virtual ("state-snapshot", this,
261                          &Uart::save_state,
262                          &Uart::restore_state );
263
264 }
265
266 // The following functions contain what used to be within Uart::Uart().
267
268 void
269 Uart :: Uart_ctor_0()
270 {
271
272   add_attribute_coder("RBR", new attribute_coder_uart_reg(& this->regs[RBR]),
273                                                                    "register");
274   triggerpoint_manager.add_watchable_value ("RBR", & this->regs[RBR]);
275   categorize ("RBR", "watchable");
276
277   add_attribute_coder("IER", new attribute_coder_uart_reg(& this->regs[IER]),
278                                                                    "register");
279   triggerpoint_manager.add_watchable_value ("IER", & this->regs[IER]);
280   categorize ("IER", "watchable");
281
282   add_attribute_coder("IIR", new attribute_coder_uart_reg(& this->regs[IIR]),
283                                                                    "register");
284   triggerpoint_manager.add_watchable_value ("IIR", & this->regs[IIR]);
285   categorize ("IIR", "watchable");
286
287   add_attribute_coder("LCR", new attribute_coder_uart_reg(& this->regs[LCR]), 
288                                                                    "register");
289   triggerpoint_manager.add_watchable_value ("LCR", & this->regs[LCR]);
290   categorize ("LCR", "watchable");
291
292   add_attribute_coder("MCR", new attribute_coder_uart_reg(& this->regs[MCR]),
293                                                                    "register");
294   triggerpoint_manager.add_watchable_value ("MCR", & this->regs[MCR]);
295   categorize ("MCR", "watchable");
296
297 }
298
299
300 void
301 Uart :: Uart_ctor_1()
302 {
303   add_attribute_coder("LSR", new attribute_coder_uart_reg(& this->regs[LSR]),
304                                                                    "register");
305   triggerpoint_manager.add_watchable_value ("LSR", & this->regs[LSR]);
306   categorize ("LSR", "watchable");
307
308   add_attribute_coder("MSR", new attribute_coder_uart_reg(& this->regs[MSR]),
309                                                                    "register");
310   triggerpoint_manager.add_watchable_value ("MSR", & this->regs[MSR]);
311   categorize ("MSR", "watchable");
312
313   add_attribute_coder("SCR", new attribute_coder_uart_reg(& this->regs[SCR]), 
314                                                                    "register");
315   triggerpoint_manager.add_watchable_value ("SCR", & this->regs[SCR]);
316   categorize ("SCR", "watchable");
317
318   add_attribute_coder("DLL", new attribute_coder_uart_reg(& this->regs[DLL]), 
319                                                                    "register");
320   triggerpoint_manager.add_watchable_value ("DLL", & this->regs[DLL]);
321   categorize ("DLL", "watchable");
322
323   add_attribute_coder("DLM", new attribute_coder_uart_reg(& this->regs[DLM]), 
324                                                                    "register");
325   triggerpoint_manager.add_watchable_value ("DLM", & this->regs[DLM]);
326   categorize ("DLM", "watchable");
327 }
328
329
330 void
331 Uart :: Uart_ctor_2()
332 {
333   add_attribute_coder("THR", new attribute_coder_uart_reg(& this->regs[THR]), 
334                                                                    "register");
335   triggerpoint_manager.add_watchable_value ("THR", & this->regs[THR]);
336   categorize ("THR", "watchable");
337
338   add_attribute_coder("FCR", new attribute_coder_uart_reg(& this->regs[FCR]), 
339                                                                    "register");
340   triggerpoint_manager.add_watchable_value ("FCR", & this->regs[FCR]);
341   categorize ("FCR", "watchable");
342
343   add_attribute( "Sin", &sin, "pin" );
344   triggerpoint_manager.add_watchable_attribute ("Sin");
345   categorize ("Sin", "watchable");
346
347   add_attribute( "Sout", &sout, "pin" );
348   triggerpoint_manager.add_watchable_attribute ("Sout");
349   categorize ("Sout", "watchable");
350
351   add_attribute( "Reset", &reset_pin, "pin" );
352   triggerpoint_manager.add_watchable_attribute ("Reset");
353   categorize ("Reset", "watchable");
354
355   add_attribute( "INTR", &intr, "pin" );
356   triggerpoint_manager.add_watchable_attribute ("INTR");
357   categorize ("INTR", "watchable");
358 }
359
360
361 void
362 Uart :: Uart_ctor_3()
363 {
364   add_attribute( "TxRDY", &txrdy, "pin" );
365   triggerpoint_manager.add_watchable_attribute ("TxRDY");
366   categorize ("TxRDY", "watchable");
367
368   add_attribute( "RxRDY", &rxrdy, "pin" );
369   triggerpoint_manager.add_watchable_attribute ("RxRDY");
370   categorize ("RxRDY", "watchable");
371
372   add_attribute( "RTS", &rts, "pin" );
373   triggerpoint_manager.add_watchable_attribute ("RTS");
374   categorize ("RTS", "watchable");
375
376   add_attribute( "DTR", &dtr, "pin" );
377   triggerpoint_manager.add_watchable_attribute ("DTR");
378   categorize ("DTR", "watchable");
379
380   add_attribute( "OUT1", &out1, "pin" );
381   triggerpoint_manager.add_watchable_attribute ("OUT1");
382   categorize ("OUT1", "watchable");
383 }
384
385
386 void
387 Uart :: Uart_ctor_4()
388 {
389
390   add_attribute( "OUT2", &out2, "pin" );
391   triggerpoint_manager.add_watchable_attribute ("OUT2");
392   categorize ("OUT2", "watchable");
393
394   add_attribute( "CTS", (binary_input_pin *) &cts, "pin" );
395   triggerpoint_manager.add_watchable_attribute ("CTS");
396   categorize ("CTS", "watchable");
397
398   add_attribute( "DSR", (binary_input_pin *) &dsr, "pin" );
399   triggerpoint_manager.add_watchable_attribute ("DSR");
400   categorize ("DSR", "watchable");
401
402   add_attribute( "RI", (binary_input_pin *) &ri, "pin" );
403   triggerpoint_manager.add_watchable_attribute ("RI");
404   categorize ("RI", "watchable");
405
406   add_attribute( "DCD", (binary_input_pin *) &dcd, "pin" );
407   triggerpoint_manager.add_watchable_attribute ("DCD");
408   categorize ("DCD", "watchable");
409 }
410
411
412 // The in_fifo_length and/or out_fifo_length members have been changed.
413 // Resize the fifo vectors to match.
414 void
415 Uart :: update_fifo_lengths() {
416   // Clamp values 
417   if (in_fifo_length < 1)
418     in_fifo_length = 1;
419   if (out_fifo_length < 1)
420     out_fifo_length = 1;
421
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 );
426
427   // There were some pending bytes in there ...
428   if (in_cnt > in_fifo_length)
429     {
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 );
434     }
435 }
436
437
438 void
439 Uart :: reset( host_int_4 ) {
440   // RBR and THR are not affected by reset
441   regs[IER] = 0;
442   regs[IIR] = 1;        // no pending interrupt yet
443   regs[FCR] = 0;
444   regs[LCR] = 0;
445   regs[LSR] = 0x60;     // Tx side is empty
446   regs[MCR] = 0;
447   setModemStatusReg();  // set MSR
448   regs[SCR] = 0;
449   // DLL and DLM are not affected by reset
450
451   intr.off();
452   out1.off();
453   out2.off();
454   rts.off();
455   dtr.off();
456
457   pending |= PEND_TX_RDY;
458   txrdy.on();           // ready to get a char
459   rxrdy.off();
460
461   rx_timeout.cancel();
462   tx_timeout.cancel();
463 }
464
465 sid::bus::status
466 Uart::busReadHandler( host_int_4 index, host_int_1& p ) {
467   unsigned char val;
468
469   switch( index ) {
470   case 0:
471     if( bit_test( regs[LCR], LCR_DLAB ) )
472       val = regs[DLL];
473     else
474       val = receive();
475     break;
476
477   case 1:
478     if( bit_test( regs[LCR], LCR_DLAB ) )
479       val = regs[DLM];
480     else
481       val = regs[IER];
482     break;
483
484   case 2:
485     val = regs[IIR];
486     break;
487
488   case LCR:
489   case MCR:
490   case SCR:
491     val = regs[index];
492     break;
493
494   case LSR:
495     val = regs[LSR];
496
497     regs[LSR] &= 0xe1;                  // Clear per char status bits
498     pending &= ~(PEND_RX_ERR);          // Clear pending status if error
499
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 );
506           intr.off();
507         }
508       }
509     }
510     break;
511
512   case MSR:
513     val = setModemStatusReg();
514
515     regs[MSR] &= 0xf0;                  // Clear delta bits
516     pending &= ~(PEND_MODEM);           // Modem has no pending IRQ
517
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 );
522         intr.off();
523       }
524     }
525     break;
526
527   default:
528     return sid::bus::unmapped;                  // illegal index
529   }
530
531   p = val;
532
533   // check for triggerpoints
534   triggerpoint_manager.check_and_dispatch ();
535
536   return sid::bus::ok;
537 }
538
539 sid::bus::status
540 Uart :: busWriteHandler( host_int_4 index, host_int_1 val ) {
541   switch( index ) {
542   case 0:
543     if( bit_test( regs[LCR], LCR_DLAB ) )
544       regs[DLL] = val;
545     else
546       xmit( val );
547     break;
548
549   case 1:
550     if( bit_test( regs[LCR], LCR_DLAB ) )
551       regs[DLM] = val;
552     else {
553       regs[IER] = val & 0x0f;
554
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 );
558           intr.on();
559         }
560       }
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.
565         */
566         if( !(bit_test( regs[IIR], IIR_NPEND)) ) {
567           bit_set( regs[IIR], IIR_NPEND );
568           intr.off();
569         }
570       }
571     }
572     break;
573
574   case 2: // FCR (write-only)
575     setFunctionReg( val );
576     break;
577
578   case LCR:
579   case SCR:
580     regs[index] = val;
581     break;
582
583   case MCR:
584     setModemControlReg( val );
585     break;
586
587   case MSR:
588   case LSR:
589     // What does it mean to write these registers?
590     break;
591
592   default:
593     return sid::bus::unmapped; // illegal index
594   }
595
596   // check for triggerpoints
597   triggerpoint_manager.check_and_dispatch ();
598
599   return sid::bus::ok;
600 }
601
602 void
603 Uart :: setFunctionReg( unsigned char val ) {
604   int i;
605
606   if( bit_test( regs[FCR], FCR_FE ) && !(bit_test( val, FCR_FE )) ) {
607     // clearing FCR_FE disables and resets the FIFOs
608     in_cnt = 0;
609     out_cnt = 0;
610
611     for( i=0; i<in_fifo_length; i++ ) {
612       in_fifo[i] = 0;
613       in_errs[i] = 0;
614     }
615
616     for( i=0; i<out_fifo_length; i++ )
617       out_fifo[i] = 0;
618
619     regs[IIR] &= 0x3f;                  // Clear FIFO enable bits in IIR
620   }
621
622   if( !(bit_test( val, FCR_FE )) ) {
623     regs[FCR] = 0;
624     return;
625   }
626
627   if( bit_test( val, FCR_RFR ) ) {      // reset input FIFO
628     in_cnt = 0;
629
630     for( i=0; i<in_fifo_length; i++ ) {
631       in_fifo[i] = 0;
632       in_errs[i] = 0;
633     }
634   }
635
636   if( bit_test( val, FCR_TFR ) ) {      // reset output FIFO
637     out_cnt = 0;
638
639     for( i=0; i<out_fifo_length ; i++ )
640       out_fifo[i] = 0;
641   }
642
643   regs[FCR] = val;
644   regs[IIR] |= 0xc0;                    // Set FIFO enable bits in IIR
645 }
646
647 /* Check the interrupt sources in order to determine if an interrupt is
648  * warranted. Returns TRUE if an interrupt is required.
649  */
650 int
651 Uart :: setInterruptId() {
652   if( pending ) {
653     regs[IIR] &= IIR_ID_MASK;           // Clear current id
654
655     if( pending & PEND_RX_ERR ) {       // Rx Error
656       if( bit_test( regs[IER], IER_ELSI ) ) {
657         regs[IIR] |= IIR_RLS_ID;
658         return 1;
659       }
660     }
661
662     if( pending & PEND_RX_RDY ) {       // Rx ready
663       if( bit_test( regs[IER], IER_ERBFI ) ) {
664         regs[IIR] |= IIR_RDA_ID;
665         return 1;
666       }
667     }
668
669     if( pending & PEND_RX_TO ) {        // Input timeout
670       regs[IIR] |= IIR_CTI_ID;          // Not enabled via IER
671       return 1;
672     }
673
674     if( pending & PEND_TX_RDY ) {       // Tx ready
675       if( bit_test( regs[IER], IER_ETBEI ) ) {
676         regs[IIR] |= IIR_TBE_ID;
677         return 1;
678       }
679     }
680
681     if( pending & PEND_MODEM ) {        // Modem status
682       if( bit_test( regs[IER], IER_EDSSI ) ) {
683         regs[IIR] |= IIR_DSS_ID;
684         return 1;
685       }
686     }
687   }
688
689   return 0;
690 }
691
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.
695  */
696 unsigned
697 Uart :: genParity( unsigned val, int nbits, enum parity p ) const {
698   int i, ones_count = 0;
699   unsigned copy = val;
700
701   for( i=0; i<nbits; i++ ) {
702     if( copy & 1 )
703       ++ones_count;
704
705     copy >>= 1;
706   }
707
708   if( p==EVEN_PARITY && (ones_count & 1) )
709     return val | (1 << nbits);
710   
711   if( p==ODD_PARITY && !(ones_count & 1) )
712     return val | (1 << nbits);
713
714   return val;
715 }
716
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.
720  */
721 int 
722 Uart :: checkParity( unsigned val, int nbits, enum parity p ) const {
723   int i, ones_count = 0;
724
725   for( i=0; i<(nbits+1); i++ ) {
726     if( val & 1 )
727       ++ones_count;
728
729     val >>= 1;
730   }
731
732   if( p==EVEN_PARITY && (ones_count & 1) )
733     return 0;
734   
735   if( p==ODD_PARITY && !(ones_count & 1) )
736     return 0;
737
738   return 1;
739 }
740
741 // Number of data bits - indexed by bottom 2 bits of LCR
742 static int num_bits[4] = { 5, 6, 7, 8 };
743
744 void
745 Uart :: xmit( unsigned val ) {
746   int i, data_mask = 0;
747   int nbits = num_bits[regs[LCR] & 0x3];
748   unsigned oval = val;
749
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.
753     */
754     txrdy.off();
755   }
756
757   tx_timeout.cancel();
758
759   for( i=0; i<nbits; i++ )              // build a mask for the data
760     data_mask |= (1 << i);
761
762   val &= data_mask;
763
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 )) )
768         val |= (1 << nbits);
769     }
770     else                                // no stick parity
771       val = genParity( val,nbits, (enum parity) bit_test(regs[LCR], LCR_PSEL) );
772   }
773
774   // XXX: Hey, what about out_fifo[] ?
775   regs[THR] = val;
776   if (sio_framing_p)
777     sout.drive( val );                  // send it
778   else
779     sout.drive( oval );                 // send it without framing
780
781   regs[THR] = 0;                        // always empty because always sent
782   bit_set( regs[LSR], LSR_THRE );
783   bit_set( regs[LSR], LSR_TEMT );
784
785   if( bit_test( regs[FCR], FCR_FE ) && !bit_test( regs[FCR], FCR_DMA ) ) {
786     // Single char DMA mode - turn on TxRDY
787     txrdy.on();
788   }
789
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 :-)
793   */
794   tx_timeout.schedule_irregular( timeout_incr );
795
796   pending &= ~(PEND_TX_RDY);            // the watchdog will set this
797 }
798
799 static int trigger_vals[4] = { 1, 4, 8, 14 };   // from FCR bits 6-7
800
801 void
802 Uart :: sinHandler( host_int_4 v ) {
803   int i, data_mask = 0;
804   int nbits = num_bits[regs[LCR] & 0x3];
805   unsigned val = v;
806
807   if( in_cnt == in_fifo_length ) {      // FIFO full
808     in_errs[in_cnt-1] = LSR_OE;
809     bit_set( regs[LSR], LSR_ERF );
810
811     // check for triggerpoints
812     triggerpoint_manager.check_and_dispatch ();
813
814     return;                             // drop the char
815   }
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
819
820     in_cnt = 0;                         // always at the top of the FIFO
821   }
822
823   if( sio_framing_p ) // framing?
824     {
825       if( bit_test( regs[LCR], LCR_PE ) ) {     // parity is enabled
826         if( bit_test( regs[LCR], LCR_STICK ) ) {
827           
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 );
832           }
833         }
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 );
837       }
838
839       for( i=0; i<nbits; i++ )          // build a mask for the data
840         data_mask |= (1 << i);
841       
842       val &= data_mask;
843     }
844   else
845     {
846       // treat val as raw data value
847     }
848
849   in_fifo[in_cnt] = val;
850
851   if( in_cnt == 0 ) {
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.
854     */
855     regs[LSR] &= 0x61;                  // set error bits
856     regs[LSR] |= in_errs[FIFO_TOP];
857
858     if( in_errs[FIFO_TOP] )
859       pending |= PEND_RX_ERR;
860
861     in_errs[FIFO_TOP] = 0;              // done with them now
862   }
863
864   ++in_cnt;
865
866   bit_set( regs[LSR], LSR_DR ); // Data now available
867
868   if( !bit_test( regs[FCR], FCR_FE ) ) {        // Not in FIFO mode
869     pending |= PEND_RX_RDY;
870
871     rxrdy.on();                         // Set the DMA line (mode 0)
872   }
873   else {                                // FIFO mode
874     int trigger = trigger_vals[(regs[FCR] & 0xc0) >> 6];
875
876     rx_timeout.cancel();
877
878     if( in_cnt>1 && in_errs[in_cnt-1] ) // did we just get an error?
879       bit_set( regs[LSR], LSR_ERF );
880
881     if( in_cnt >= trigger ) {
882       if( bit_test( regs[FCR], FCR_DMA ) )
883         rxrdy.on();                     // Set the DMA line (mode 1)
884
885       pending |= PEND_RX_RDY;
886     }
887     else {                              // not at trigger point yet
888       if( !bit_test( regs[FCR], FCR_DMA ) )
889         rxrdy.on();                     // Set the DMA line (mode 0)
890
891       // set up a callback in case no more chars come.
892       rx_timeout.schedule_irregular( timeout_incr );
893     }
894   }
895
896   if( setInterruptId() ) {              // IRQ if enabled
897     bit_clear( regs[IIR], IIR_NPEND );
898     intr.on();
899   }
900
901   // check for triggerpoints
902   triggerpoint_manager.check_and_dispatch ();
903 }
904
905 host_int_1
906 Uart :: receive() {
907   int i;
908
909   regs[RBR] = in_fifo[FIFO_TOP];        // get the char at the top of the FIFO
910
911   --in_cnt;                             // one less in FIFO
912
913   if( in_cnt <= 0 ) {                   // emptied the FIFO
914     bit_clear( regs[LSR], LSR_DR );
915
916     pending &= ~(PEND_RX_RDY);          // clear pending IRQ source
917
918     rxrdy.off();
919
920     in_cnt = 0;                         // guard against multiple reads
921   }
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.
927     */
928     for( i=0; i<in_cnt; i++ ) {
929       in_fifo[i] = in_fifo[i+1];
930       in_errs[i] = in_errs[i+1];
931     }
932
933     bit_set( regs[LSR], LSR_DR );       
934
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
938
939     if( in_errs[FIFO_TOP] )
940       pending |= PEND_RX_ERR;
941
942     in_errs[FIFO_TOP] = 0;              // done with these errors
943
944     for( i=1; i<in_cnt; i++ ) {
945       if( in_errs[i] )
946         bit_set( regs[LSR], LSR_ERF );  // error still to come
947     }
948
949     int trigger = trigger_vals[(regs[FCR] & 0xc0) >> 6];
950
951     if( in_cnt < trigger )              // dropped below trigger point
952       pending &= ~PEND_RX_RDY;
953   }
954
955   rx_timeout.cancel();
956
957   if( setInterruptId() ) {              // possibly new Rx errors
958     bit_clear( regs[IIR], IIR_NPEND );  // assert interrupt
959     intr.on();
960   }
961   else {                                // possibly out of data
962     bit_set( regs[IIR], IIR_NPEND );    // deassert interrupt
963     intr.off();
964   }
965
966   return regs[RBR];
967 }
968
969 /* rxWatchdog is a scheduler callback function. It is triggered from FIFO
970  * mode when no input characters have arrived during the specified timeout.
971  *
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.
976  */
977 void 
978 Uart :: rxWatchdog() {
979   pending |= PEND_RX_TO;                // timed out on receive
980
981   if( setInterruptId() ) {
982     bit_clear( regs[IIR], IIR_NPEND );  // assert interrupt
983     intr.on();
984
985     // check for triggerpoints
986     triggerpoint_manager.check_and_dispatch ();
987   }
988 }
989
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.
993  *
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.
1000  */
1001 void 
1002 Uart :: txWatchdog() {
1003   pending |= PEND_TX_RDY;               // timed out on xmit
1004
1005   if( setInterruptId() ) {
1006     bit_clear( regs[IIR], IIR_NPEND );  // assert interrupt
1007     intr.on();
1008
1009     // check for triggerpoints
1010     triggerpoint_manager.check_and_dispatch ();
1011   }
1012 }
1013
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.
1017  *
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.
1020  */
1021 inline void
1022 Uart :: modemLineChange( int bit, int val ) {
1023   assert( (bit >= 4) && (bit <= 7) );
1024
1025   bit_set( regs[MSR], bit - 4 );
1026
1027   if( val )
1028     bit_clear( regs[MSR], bit );
1029   else
1030     bit_set( regs[MSR], bit );
1031 }
1032
1033 void
1034 Uart :: setModemControlReg( unsigned char val ) {
1035   unsigned char changed = regs[MCR] ^ val;
1036
1037   regs[MCR] = val & 0x1f;                       // Top 3 bits are always 0
1038
1039   if( bit_test( changed, MCR_LOOPBACK ) ) {
1040     if( bit_test( val, MCR_LOOPBACK ) ) {       // switch to Loopback
1041       bit_set( regs[MCR], MCR_LOOPBACK );
1042     
1043       dtr.off();        // The external lines are de-asserted
1044       rts.off();
1045       out1.off();
1046       out2.off();
1047
1048       // Note: The MSR reg flags are updated when that register is read.
1049     }
1050     else {
1051       bit_clear( regs[MCR], MCR_LOOPBACK );
1052
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 ) );
1057     }
1058
1059    /* It is unclear to me what's supposed to happen to the MSR delta bits
1060     * when we switch to/from loopback. 
1061     */
1062     return;
1063   }
1064
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
1068     */
1069     if( bit_test( changed, MCR_DTR ) )
1070       modemLineChange( MSR_CDSR, ~(bit_value( val, MCR_DTR )) );
1071
1072     if( bit_test( changed, MCR_RTS ) )
1073       modemLineChange( MSR_CCTS, ~(bit_value( val, MCR_RTS )) );
1074
1075     if( bit_test( changed, MCR_OUT1 ) )
1076       modemLineChange( MSR_CRI, ~(bit_value( val, MCR_OUT1 )) );
1077
1078     if( bit_test( changed, MCR_OUT2 ) )
1079       modemLineChange( MSR_CDCD, ~(bit_value( val, MCR_OUT2 )) );
1080
1081     if( changed & 0x0f )
1082       checkModemIRQ();
1083   }
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 ) );
1089   }
1090 }
1091
1092 host_int_1
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 );
1098
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 );
1102
1103     if( bit_test( regs[MCR], MCR_DTR ) )
1104       bit_set( regs[MSR], MSR_CDSR );
1105
1106     if( bit_test( regs[MCR], MCR_OUT1 ) )
1107       bit_set( regs[MSR], MSR_CRI );
1108
1109     if( bit_test( regs[MCR], MCR_OUT2 ) )
1110       bit_set( regs[MSR], MSR_CDCD );
1111   }
1112   else {                                        // not in loopback mode
1113     if( cts.state() == binary_pin_active )
1114       bit_set( regs[MSR], MSR_CCTS );
1115
1116     if( dsr.state() == binary_pin_active )
1117       bit_set( regs[MSR], MSR_CDSR );
1118
1119     if( ri.state() == binary_pin_active )
1120       bit_set( regs[MSR], MSR_CRI );
1121
1122     if( dcd.state() == binary_pin_active )
1123       bit_set( regs[MSR], MSR_CDCD );
1124   }
1125
1126   return regs[MSR];
1127 }
1128
1129 void
1130 Uart :: checkModemIRQ() {
1131   pending |= PEND_MODEM;
1132
1133   if( bit_test( regs[IER], IER_EDSSI ) ) {
1134     // Modem interrupts are enabled
1135
1136     if( (bit_test( regs[IIR], IIR_NPEND )) ) {
1137       // There is no IRQ currently pending - raise the interrupt
1138
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)
1141       intr.on();
1142     }
1143   }
1144 }
1145
1146 // Callback for CTS pin
1147 void
1148 Uart :: ctsHandler( int val ) {
1149   if( !(bit_test( regs[MCR], MCR_LOOPBACK )) )  // ignore if loop-back
1150     modemLineChange( MSR_CCTS, val );
1151
1152   checkModemIRQ();
1153
1154   // check for triggerpoints
1155   triggerpoint_manager.check_and_dispatch ();
1156 }
1157
1158 // Callback for DSR pin
1159 void
1160 Uart :: dsrHandler( int val ) {
1161   if( !(bit_test( regs[MCR], MCR_LOOPBACK )) )  // ignore if loop-back
1162     modemLineChange( MSR_CDSR, val );
1163
1164   checkModemIRQ();
1165
1166   // check for triggerpoints
1167   triggerpoint_manager.check_and_dispatch ();
1168 }
1169
1170 // Callback for RI pin
1171 void
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
1176
1177     if( val )
1178       bit_clear( regs[MSR], MSR_CRI );
1179     else
1180       bit_set( regs[MSR], MSR_CRI );
1181   }
1182
1183   checkModemIRQ();
1184
1185   // check for triggerpoints
1186   triggerpoint_manager.check_and_dispatch ();
1187 }
1188
1189 // Callback for DCD pin
1190 void
1191 Uart :: dcdHandler( int val ) {
1192   if( !(bit_test( regs[MCR], MCR_LOOPBACK )) )  // ignore if loop-back
1193     modemLineChange( MSR_CDCD, val );
1194
1195   checkModemIRQ();
1196
1197   // check for triggerpoints
1198   triggerpoint_manager.check_and_dispatch ();
1199 }
1200
1201
1202
1203 ostream&
1204 operator << (ostream& op, const Uart& copy_obj)
1205 {
1206   // Store Internal Registers First
1207   op << "InterRegs ";
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] << ":";
1211
1212   op << "FifoLengths " << copy_obj.in_fifo_length << " " << copy_obj.out_fifo_length << ":";
1213
1214   op << "InFCh " << copy_obj.in_cnt;
1215   if (copy_obj.in_cnt > 0)
1216     {
1217       op << "InFifo ";
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];
1221
1222       op << "InErr ";
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];
1226     }
1227   op << ":"; // Seperator.
1228
1229   op << "OutFCh " << copy_obj.out_cnt;
1230   if (copy_obj.out_cnt > 0)
1231     {
1232       op << "OutFifo ";
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];
1236     }
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;
1243
1244   return op;
1245 }
1246
1247 istream&
1248 operator >> (istream& ip, Uart& ovwrite_obj)
1249 {
1250   string coding;
1251
1252   ip >> coding;
1253   if ( coding != "InterRegs")
1254     {
1255       ip.setstate(ios::badbit);
1256       return ip;
1257     }
1258    host_int_4 reg_value;
1259    for (int reg_num = 0; reg_num < UART_NUM_REGS; ++reg_num)
1260       {
1261         ip >> reg_value;
1262         if (reg_num != MCR)
1263            ovwrite_obj.regs[reg_num] = reg_value;
1264         else
1265           ovwrite_obj.busWriteHandler(MCR, (host_int_1)reg_value); // Will drive o/p pins too
1266       }
1267
1268     if ( bit_test(ovwrite_obj.regs[IIR], IIR_NPEND) )
1269       ovwrite_obj.intr.off();
1270     else // Raise interrupt
1271       ovwrite_obj.intr.on();
1272
1273    char sep;
1274    ip.get(sep);
1275    if ( sep != ':')
1276      {
1277        ip.setstate(ios::badbit);
1278        return ip;
1279      }
1280
1281
1282    ip >> coding;
1283    if (coding != "FifoLengths")
1284      {
1285        ip.setstate(ios::badbit);
1286        return ip;
1287      }
1288    ip >> ovwrite_obj.in_fifo_length;
1289    ip >> ovwrite_obj.out_fifo_length;
1290    ip.get(sep);
1291    if ( sep != ':')
1292      {
1293        ip.setstate(ios::badbit);
1294        return ip;
1295      }
1296    ovwrite_obj.update_fifo_lengths ();
1297       
1298    ip >> coding;
1299    if (coding != "InFCh")
1300      {
1301        ip.setstate(ios::badbit);
1302        return ip;
1303      }
1304    ip >> ovwrite_obj.in_cnt;
1305    if (  ovwrite_obj.in_cnt > 0 ) 
1306      {
1307        ip >> coding;
1308        if (coding != "InFifo")
1309          {
1310            ip.setstate(ios::badbit);
1311            return ip;
1312          }
1313        for (unsigned int  i = 0; i <  ovwrite_obj.in_cnt; ++i) 
1314           ip >> ovwrite_obj.in_fifo[i];
1315
1316        ip >> coding;
1317        if (coding != "InErr")
1318          {
1319            ip.setstate(ios::badbit);
1320            return ip;
1321          }
1322
1323        host_int_4 err_val;
1324        for (unsigned int j= 0; j <  ovwrite_obj.in_cnt; ++j)
1325           {
1326             ip >> err_val;
1327             ovwrite_obj.in_errs[j] = err_val;
1328           }
1329      }
1330    ip.get(sep);
1331    if (sep != ':')
1332      {
1333        ip.setstate(ios::badbit);
1334        return ip;
1335      }
1336
1337    ip >> coding;
1338    if ( coding != "OutFCh")
1339      {
1340        ip.setstate(ios::badbit);
1341        return ip;
1342      }
1343    ip >> ovwrite_obj.out_cnt;
1344    if ( ovwrite_obj.out_cnt > 0 ) 
1345      {
1346        ip >> coding;
1347        if (coding != "OutFifo")
1348          {
1349             ip.setstate(ios::badbit);
1350             return ip;
1351          }
1352        for (unsigned int k = 0; k < ovwrite_obj.out_cnt; ++k )
1353            ip >> ovwrite_obj.out_fifo[k];
1354      }
1355    ip.get(sep);
1356    if (sep != ':')
1357      {
1358        ip.setstate(ios::badbit);
1359        return ip;
1360      }
1361
1362    ip >> coding;
1363    if ( coding != "Pend")
1364      {
1365        ip.setstate(ios::badbit);
1366        return ip;
1367      }
1368    ip >> ovwrite_obj.pending;
1369    ip.get(sep);
1370    if (sep != ':') 
1371      {
1372        ip.setstate(ios::badbit);
1373        return ip;
1374      }
1375  
1376    ip >> coding;
1377    if (coding != "Frame")
1378      {
1379        ip.setstate(ios::badbit);
1380        return ip;
1381      }
1382    ip >> ovwrite_obj.sio_framing_p;
1383    ip.get(sep);
1384    if (sep != ':')
1385      {
1386        ip.setstate(ios::badbit);
1387        return ip;
1388      }
1389
1390    host_int_4 temppin_val =0;
1391    ip >> coding;
1392    if (coding != "rxpin")
1393      {
1394        ip.setstate(ios::badbit);
1395        return ip;
1396      }
1397    ip >> temppin_val;
1398    ovwrite_obj.rxrdy.drive(temppin_val);
1399    ip.get(sep);
1400    if (sep != ':')
1401      {
1402        ip.setstate(ios::badbit);
1403        return ip;
1404      }
1405
1406    ip >> coding;
1407    if (coding != "txpin")
1408      {
1409        ip.setstate(ios::badbit);
1410        return ip;
1411      }
1412    ip >> temppin_val;
1413    ovwrite_obj.txrdy.drive(temppin_val);
1414    ip.get(sep);
1415    if (sep != ':')
1416      {
1417        ip.setstate(ios::badbit);
1418        return ip;
1419      }
1420
1421    ip >> coding;
1422    if (coding != "TOCount")
1423      {
1424        ip.setstate(ios::badbit);
1425        return ip;
1426      } 
1427    ip >> ovwrite_obj.timeout_incr;
1428
1429    return ip;
1430 }
1431
1432
1433 // Standard DLL wrapper-stuff
1434
1435 static vector<string>
1436 UartListTypes()
1437 {
1438   vector<string> types;
1439   types.push_back(string("hw-uart-ns16550"));
1440   return types;
1441 }
1442
1443 static component*
1444 UartCreate(const string& typeName)
1445 {
1446   if(typeName == "hw-uart-ns16550")
1447     return new Uart();
1448   else
1449     return 0;
1450 }
1451
1452
1453 static void
1454 UartDelete(component* c)
1455 {
1456   delete dynamic_cast<Uart*>(c);
1457 }
1458
1459
1460 // static object
1461 extern const component_library uart_component_library;
1462
1463 const component_library uart_component_library DLLEXPORT = 
1464 {
1465   COMPONENT_LIBRARY_MAGIC,
1466   & UartListTypes, 
1467   & UartCreate,
1468   & UartDelete
1469 };
1470