#endif
struct s_queue ttyinq[NUM_DEV_TTY+1] = { /* ttyinq[0] is never used */
- { NULL, NULL, NULL, 0, 0, 0 },
- { tbuf1, tbuf1, tbuf1, TTYSIZ, 0, TTYSIZ/2 },
+ {NULL, NULL, NULL, 0, 0, 0},
+ {tbuf1, tbuf1, tbuf1, TTYSIZ, 0, TTYSIZ/2},
#ifdef CONFIG_PPP
- { tbufp, tbufp, tbufp, TTYSIZ, 0, TTYSIZ/2 },
+ {tbufp, tbufp, tbufp, TTYSIZ, 0, TTYSIZ/2},
#endif
};
-/* FIXME: implement */
+uint16_t divisor_table[16] = {
+ 0, UART_CLOCK / 16 / 50, UART_CLOCK / 16 / 75, UART_CLOCK / 16 / 110,
+ UART_CLOCK / 16 / 134, UART_CLOCK / 16 / 150, UART_CLOCK / 16 / 300,
+ UART_CLOCK / 16 / 600, UART_CLOCK / 16 / 1200, UART_CLOCK / 16 / 2400,
+ UART_CLOCK / 16 / 4800, UART_CLOCK / 16 / 9600,
+ UART_CLOCK / 16 / 19200, UART_CLOCK / 16 / 38400,
+ UART_CLOCK / 16 / 57600, UART_CLOCK / 16 / 115200
+};
+
void tty_setup(uint8_t minor)
{
- minor;
+ uint16_t b;
+ uint8_t lcr = 0;
+ if (minor == 1) {
+ b = ttydata[minor].termios.c_cflag & CBAUD;
+ if (b > 0 && b < 16) {
+ UART0_LCR = 0x80; /* LCR = DLAB ON */
+ UART0_DLL = divisor_table[b] & 0xFF;
+ UART0_DLH = divisor_table[b] >> 8;
+ }
+ /* word length 5(00), 6(01), 7(10), or 8(11) */
+ lcr = (ttydata[minor].termios.c_cflag & CSIZE) >> 4;
+ /* stop bits 1(0), or 2(1) */
+ lcr |= (ttydata[minor].termios.c_cflag & CSTOPB) >> 4;
+ /* parity disable(0), or enable(1) */
+ lcr |= (ttydata[minor].termios.c_cflag & PARENB) >> 5;
+ /* parity odd(0), or even(1) */
+ lcr |= ((ttydata[minor].termios.c_cflag & PARODD) ^ PARODD) >> 5;
+ UART0_LCR = lcr;
+ UART0_MCR = 0x03; /* DTR = ON, RTS = ON */
+ }
}
-/* FIXME: implement (although /DCD is hardwired to GND) */
int tty_carrier(uint8_t minor)
{
- minor;
- return 1;
+ uint8_t c;
+ if (minor == 1) {
+ c = UART0_MSR;
+ return (c & 0x80) ? 1 : 0; /* test DCD */
+ }
+ return 1;
}
-void tty_interrupt(void)
+void tty_pollirq_uart0(void)
{
- uint8_t reg = UART0_LSR;
- if (reg & 0x01) {
- /* data available */
- reg = UART0_RBR;
- tty_inproc(1, reg);
+ uint8_t iir, msr, lsr;
+ while (true) {
+ iir = UART0_IIR;
+ lsr = UART0_LSR;
+ /* IRR bits
+ * 3 2 1 0
+ * -------
+ * x x x 1 no interrupt pending
+ * 0 1 1 0 6 LSR changed -- read the LSR
+ * 0 1 0 0 4 receive FIFO >= threshold
+ * 1 1 0 0 C received data sat in FIFO for a while
+ * 0 0 1 0 2 transmit holding register empty
+ * 0 0 0 0 0 MSR changed -- read the MSR
+ */
+ switch (iir & 0x0F) {
+ case 0x0: /* MSR changed */
+ case 0x2: /* transmit register empty */
+ msr = UART0_MSR;
+ if ((msr & 0x10) && (lsr & 0x20)){
+ /* CTS high, transmit reg empty */
+ tty_outproc(1);
+ }
+ /* fall through */
+ case 0x6: /* LSR changed */
+ /* we already read the LSR register so int has cleared */
+ UART0_IER = 0x01; /* enable only receive interrupts */
+ break;
+ case 0x4: /* receive (FIFO >= threshold) */
+ case 0xC: /* receive (timeout waiting for FIFO to fill) */
+ while (lsr & 0x01) { /* Data ready */
+ tty_inproc(1, UART0_RBR);
+ lsr = UART0_LSR;
+ }
+ break;
+ default:
+ return;
+ }
}
}
void tty_sleeping(uint8_t minor)
{
- minor;
+ if (minor == 1) {
+ UART0_IER = 0x0B; /* enable all but LSR interrupt */
+ }
}
ttyready_t tty_writeready(uint8_t minor)
{
- uint8_t reg;
+ uint8_t c;
if (minor == 1) {
- reg = UART0_LSR;
- return (reg & 0x20) ? TTY_READY_NOW : TTY_READY_SOON;
+ c = UART0_MSR;
+ if ((c & 0x10) == 0) /* CTS not asserted? */
+ return TTY_READY_LATER;
+ c = UART0_LSR;
+ if (c & 0x20) /* THRE? */
+ return TTY_READY_NOW;
+ return TTY_READY_SOON;
}
return TTY_READY_NOW;
}
out (UART0_DLL),a ; set low byte of divisor
ld a,#CONSOLE_DIVISOR_HIGH ; baud rate divisor - high byte
out (UART0_DLH),a ; set high byte of divisor
- ld a,#3 ; value for LCR and MCR
+ ld a,#0x03 ; value for LCR and MCR
out (UART0_LCR),a ; 8 bit data, 1 stop, no parity
out (UART0_MCR),a ; DTR ON, RTS ON
- ld a,#6 ; disable and reset FIFOs
- out (UART0_FCR),a
- ld a,#1 ; enable receive data available
+ ld a,#0x07 ; enable and clear FIFOs
+ out (UART0_FCR),a ; interrupt theshold 1 byte
+ ld a,#0x01 ; enable receive data available
out (UART0_IER),a ; interrupt
; initialize CTC
ld a,#0x47 ; counter mode, disable interrupts