1 INTERFACE [16550-{ia32,amd64}]:
20 * 16550 implementation of the UART interface.
27 * Start this serial port for I/O.
28 * @param port the I/O port base address.
29 * @param irq the IRQ assigned to this port, -1 if none.
31 bool startup(Address port, int irq);
44 MODE_8N1 = PAR_NONE | DAT_8 | STOP_1,
45 MODE_7E1 = PAR_EVEN | DAT_7 | STOP_1,
47 // these two values are to leave either mode
48 // or baud rate unchanged on a call to change_mode
56 TRB = 0, // Transmit/Receive Buffer (read/write)
57 BRD_LOW = 0, // Baud Rate Divisor LSB if bit 7 of LCR is set (read/write)
58 IER = 1, // Interrupt Enable Register (read/write)
59 BRD_HIGH = 1, // Baud Rate Divisor MSB if bit 7 of LCR is set (read/write)
60 IIR = 2, // Interrupt Identification Register (read only)
61 FCR = 2, // 16550 FIFO Control Register (write only)
62 LCR = 3, // Line Control Register (read/write)
63 MCR = 4, // Modem Control Register (read/write)
64 LSR = 5, // Line Status Register (read only)
65 MSR = 6, // Modem Status Register (read only)
66 SPR = 7, // Scratch Pad Register (read/write)
74 IMPLEMENTATION[16550]:
77 #include "processor.h"
81 Uart::Uart() : port(~0U), _irq(-1)
89 PRIVATE inline NEEDS["io.h"]
90 void Uart::outb( Unsigned8 b, Registers reg )
92 Io::out8(b, port + (reg << Access_shift));
95 PRIVATE inline NEEDS["io.h"]
96 Unsigned8 Uart::inb( Registers reg ) const
98 return Io::in8(port + (reg << Access_shift));
102 PRIVATE inline NEEDS[Uart::outb]
103 void Uart::mcr(Unsigned8 b)
108 PRIVATE inline NEEDS[Uart::inb]
109 Unsigned8 Uart::mcr() const
114 PRIVATE inline NEEDS[Uart::outb]
115 void Uart::fcr(Unsigned8 b)
120 PRIVATE inline NEEDS[Uart::outb]
121 void Uart::lcr(Unsigned8 b)
126 PRIVATE inline NEEDS[Uart::inb]
127 Unsigned8 Uart::lcr() const
132 PRIVATE inline NEEDS[Uart::outb]
133 void Uart::ier(Unsigned8 b)
138 PRIVATE inline NEEDS[Uart::inb]
139 Unsigned8 Uart::ier() const
144 PRIVATE inline NEEDS[Uart::inb]
145 Unsigned8 Uart::iir() const
150 PRIVATE inline NEEDS[Uart::inb]
151 Unsigned8 Uart::msr() const
156 PRIVATE inline NEEDS[Uart::inb]
157 Unsigned8 Uart::lsr() const
162 PRIVATE inline NEEDS[Uart::outb]
163 void Uart::trb(Unsigned8 b)
168 PRIVATE inline NEEDS[Uart::inb]
169 Unsigned8 Uart::trb() const
177 Unsigned8 scratch, scratch2, scratch3;
191 return (scratch2 == 0x00 && scratch3 == 0x0f);
195 bool Uart::startup(Address _port, int __irq)
200 Proc::Status o = Proc::cli_save();
204 Proc::sti_restore(o);
209 ier(Base_ier_bits);/* disable all rs-232 interrupts */
210 mcr(0x0b); /* out2, rts, and dtr enabled */
211 fcr(1); /* enable fifo */
212 fcr(0x07); /* clear rcv xmit fifo */
213 fcr(1); /* enable fifo */
214 lcr(0); /* clear line control register */
216 /* clearall interrupts */
217 /*read*/ msr(); /* IRQID 0*/
218 /*read*/ iir(); /* IRQID 1*/
219 /*read*/ trb(); /* IRQID 2*/
220 /*read*/ lsr(); /* IRQID 3*/
222 while(lsr() & 1/*DATA READY*/) /*read*/ trb();
223 Proc::sti_restore(o);
229 void Uart::shutdown()
231 Proc::Status o = Proc::cli_save();
236 Proc::sti_restore(o);
240 bool Uart::change_mode(TransferMode m, BaudRate r)
242 Proc::Status o = Proc::cli_save();
243 Unsigned8 old_lcr = lcr();
245 lcr(old_lcr | 0x80/*DLAB*/);
246 Unsigned16 divisor = Base_rate/r;
247 trb( divisor & 0x0ff ); /* BRD_LOW */
248 ier( (divisor >> 8) & 0x0ff ); /* BRD_HIGH */
255 Proc::sti_restore(o);
260 Uart::TransferMode Uart::get_mode()
266 int Uart::write(char const *s, size_t count)
268 /* disable uart irqs */
271 ier(old_ier & ~0x0f);
274 for (unsigned i = 0; i < count; i++)
276 while (!(lsr() & 0x20 /* THRE */))
281 /* wait till everything is transmitted */
282 while (!(lsr() & 0x40 /* TSRE */))
290 int Uart::getchar(bool blocking)
292 if (!blocking && !(lsr() & 1 /* DATA READY */))
295 Unsigned8 old_ier, ch;
297 ier(old_ier & ~0x0f);
298 while (!(lsr() & 1 /* DATA READY */))
306 int Uart::char_avail() const
308 if (lsr() & 1 /* DATA READY */)
316 int Uart::irq() const
321 IMPLEMENT inline NEEDS[Uart::ier]
322 void Uart::disable_rcv_irq()
328 // ------------------------------------------------------------------------
329 IMPLEMENTATION [16550-{ia32,amd64}]:
331 IMPLEMENT inline NEEDS[Uart::ier]
332 void Uart::enable_rcv_irq()