|
|
|
#include <common.h>
|
|
|
|
#include <ns16550.h>
|
|
|
|
#include "short_types.h"
|
|
|
|
#include "memio.h"
|
|
|
|
#include "articiaS.h"
|
|
|
|
|
|
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
|
|
|
|
#ifndef CFG_NS16550
|
|
|
|
static uint32 ComPort1;
|
|
|
|
|
|
|
|
uint16 SerialEcho = 1;
|
|
|
|
|
|
|
|
|
|
|
|
#define RECEIVER_HOLDING 0
|
|
|
|
#define TRANSMITTER_HOLDING 0
|
|
|
|
#define INTERRUPT_ENABLE 1
|
|
|
|
#define INTERRUPT_STATUS 2
|
|
|
|
#define FIFO_CONTROL 2
|
|
|
|
#define LINE_CONTROL 3
|
|
|
|
#define MODEM_CONTROL 4
|
|
|
|
#define LINE_STATUS 5
|
|
|
|
#define MODEM_STATUS 6
|
|
|
|
#define SCRATCH_PAD 7
|
|
|
|
|
|
|
|
#define DIVISOR_LATCH_LSB 0
|
|
|
|
#define DIVISOR_LATCH_MSB 1
|
|
|
|
#define PRESCALER_DIVISION 5
|
|
|
|
|
|
|
|
#define COM_WRITE_BYTE(reg, byte) out_byte((ComPort1+reg), byte)
|
|
|
|
#define COM_READ_BYTE(reg) in_byte((ComPort1+reg))
|
|
|
|
|
|
|
|
static int serial_init_done = 0;
|
|
|
|
|
|
|
|
void serial_init (void)
|
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
uint32 clock_divisor = 115200 / baudrate;
|
|
|
|
uint8 cfg;
|
|
|
|
uint8 a;
|
|
|
|
uint16 devfn = 7 << 3;
|
|
|
|
|
|
|
|
if (serial_init_done)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Enter configuration mode */
|
|
|
|
cfg = pci_read_cfg_byte (0, devfn, 0x85);
|
|
|
|
pci_write_cfg_byte (0, devfn, 0x85, cfg | 0x02);
|
|
|
|
|
|
|
|
/* Set serial port COM1 as 3F8 */
|
|
|
|
out_byte (0x3F0, 0xE7);
|
|
|
|
out_byte (0x3f1, 0xfe);
|
|
|
|
|
|
|
|
/* Set serial port COM2 as 2F8 */
|
|
|
|
out_byte (0x3f0, 0xe8);
|
|
|
|
out_byte (0x3f1, 0xeb);
|
|
|
|
|
|
|
|
/* Enable */
|
|
|
|
out_byte (0x3f0, 0xe2);
|
|
|
|
a = in_byte (0x3f1);
|
|
|
|
a |= 0xc;
|
|
|
|
out_byte (0x3f0, 0xe2);
|
|
|
|
out_byte (0x3f1, a);
|
|
|
|
|
|
|
|
/* Reset the configuration mode */
|
|
|
|
pci_write_cfg_byte (0, devfn, 0x85, cfg);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ComPort1 = 0x3F8;
|
|
|
|
|
|
|
|
/* Disable interrupts */
|
|
|
|
COM_WRITE_BYTE (INTERRUPT_ENABLE, 0x00);
|
|
|
|
|
|
|
|
/* Set baud rate */
|
|
|
|
/* COM_WRITE_BYTE(LINE_CONTROL, 0x83); */
|
|
|
|
/* COM_WRITE_BYTE(DIVISOR_LATCH_LSB, (uint8)(clock_divisor & 0xFF)); */
|
|
|
|
/* COM_WRITE_BYTE(DIVISOR_LATCH_MSB, (uint8)(clock_divisor >> 8)); */
|
|
|
|
/* __asm("eieio"); */
|
|
|
|
|
|
|
|
/* Set 8-N-1 */
|
|
|
|
COM_WRITE_BYTE (LINE_CONTROL, 0x03);
|
|
|
|
__asm ("eieio");
|
|
|
|
|
|
|
|
/* Disable FIFO */
|
|
|
|
COM_WRITE_BYTE (MODEM_CONTROL, 0x03);
|
|
|
|
COM_WRITE_BYTE (FIFO_CONTROL, 0x07);
|
|
|
|
|
|
|
|
__asm ("eieio");
|
|
|
|
serial_init_done = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern int console_changed;
|
|
|
|
|
|
|
|
void serial_putc (const char sendme)
|
|
|
|
{
|
|
|
|
if (sendme == '\n') {
|
|
|
|
while ((in_byte (0x3FD) & 0x40) == 0);
|
|
|
|
out_byte (0x3f8, 0x0D);
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((in_byte (0x3FD) & 0x40) == 0);
|
|
|
|
out_byte (0x3f8, sendme);
|
|
|
|
}
|
|
|
|
|
|
|
|
int serial_getc (void)
|
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
uint8 c;
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
uint8 x = in_byte (0x3FD);
|
|
|
|
|
|
|
|
if (x & 0x01)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (x & 0x0C)
|
|
|
|
out_byte (0x3fd, 0x0c);
|
|
|
|
}
|
|
|
|
|
|
|
|
c = in_byte (0x3F8);
|
|
|
|
|
|
|
|
return c;
|
|
|
|
#else
|
|
|
|
while ((in_byte (0x3FD) & 0x01) == 0) {
|
|
|
|
if (console_changed != 0) {
|
|
|
|
printf ("Console changed\n");
|
|
|
|
console_changed = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return in_byte (0x3F8);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
int serial_tstc (void)
|
|
|
|
{
|
|
|
|
return (in_byte (0x03FD) & 0x01) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void serial_debug_putc (int c)
|
|
|
|
{
|
|
|
|
serial_puts ("DBG");
|
|
|
|
serial_putc (c);
|
|
|
|
serial_putc (0x0d);
|
|
|
|
serial_putc (0x0A);
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
const NS16550_t Com0 = (NS16550_t) CFG_NS16550_COM1;
|
|
|
|
const NS16550_t Com1 = (NS16550_t) CFG_NS16550_COM2;
|
|
|
|
|
|
|
|
int serial_init (void)
|
|
|
|
{
|
|
|
|
uint32 clock_divisor = 115200 / gd->baudrate;
|
|
|
|
|
|
|
|
NS16550_init (Com0, clock_divisor);
|
|
|
|
/* NS16550_reinit(Com1, clock_divisor); */
|
|
|
|
/* serial_puts("COM1: 3F8h initalized"); */
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
void serial_putc (const char c)
|
|
|
|
{
|
|
|
|
NS16550_putc (Com0, c);
|
|
|
|
if (c == '\n')
|
|
|
|
NS16550_putc (Com0, 0x0D);
|
|
|
|
}
|
|
|
|
|
|
|
|
int serial_getc (void)
|
|
|
|
{
|
|
|
|
return (int) NS16550_getc (Com0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int serial_tstc (void)
|
|
|
|
{
|
|
|
|
return NS16550_tstc (Com0);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
void serial_putc (const char sendme)
|
|
|
|
{
|
|
|
|
if (sendme == '\n') {
|
|
|
|
while ((in_byte (0x3FD) & 0x40) == 0);
|
|
|
|
out_byte (0x3f8, 0x0D);
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((in_byte (0x3FD) & 0x40) == 0);
|
|
|
|
out_byte (0x3f8, sendme);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extern int console_changed;
|
|
|
|
|
|
|
|
int serial_getc (void)
|
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
uint8 c;
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
uint8 x = in_byte (0x3FD);
|
|
|
|
|
|
|
|
if (x & 0x01)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (x & 0x0C)
|
|
|
|
out_byte (0x3fd, 0x0c);
|
|
|
|
}
|
|
|
|
|
|
|
|
c = in_byte (0x3F8);
|
|
|
|
|
|
|
|
return c;
|
|
|
|
#else
|
|
|
|
while ((in_byte (0x3FD) & 0x01) == 0) {
|
|
|
|
if (console_changed != 0) {
|
|
|
|
console_changed = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return in_byte (0x3F8);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
int serial_tstc (void)
|
|
|
|
{
|
|
|
|
return (in_byte (0x03FD) & 0x01) != 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void serial_puts (const char *string)
|
|
|
|
{
|
|
|
|
while (*string)
|
|
|
|
serial_putc (*string++);
|
|
|
|
}
|
|
|
|
|
|
|
|
void serial_setbrg (void)
|
|
|
|
{
|
|
|
|
uint32 clock_divisor = 115200 / gd->baudrate;
|
|
|
|
|
|
|
|
NS16550_init (Com0, clock_divisor);
|
|
|
|
}
|