/*
    IOHal.c, Copyright (c) by Silvio Dragone & David Reist,
    Swiss Federal Institute of Technology,
    Computer Engineering and Networks Laboratory.
 
    TOPSY -- A Teachable Operating System.
             Implementation of a tiny and simple
             micro kernel for teaching purposes.
 
    For further information, please visit http://www.tik.ee.ethz.ch/~topsy
 
    This software is provided under the terms of the GNU General Public Licence.
 
    A full copy of the GNU GPL is provided in the file COPYING found in the 
    development root of Topsy.
*/

#include "Topsy.h"
#include "IOHal.h"
#include "IODevice.h"

/* very simple console output routine. accesses hardware directly, used at
 * startup and on catastrophic events/debugging...
 */

/* This is a "light" version of the SA1100_UART driver,
	 refer to SA1100_UART.c & SA1100_UART.h for further details
 */

void ioConsoleInit()
{
  unsigned int* control = (unsigned int*) UART_CR_REGISTER;

  /* device init */

  /* following instruction not needed */
  /* *control = *control & ~UART_ENABLE; */			/* disable UART */

  ioDelayAtLeastCycles( NBCYCLESFORDELAY);
  *control = *control & ~PARITY_ENABLE;					/* no parity */
  ioDelayAtLeastCycles( NBCYCLESFORDELAY);
  *control = (*control & ~DATA_SIZE_SELECT_MASK) |
             (0x3 << 5);																	/* 8 bits/char */
  ioDelayAtLeastCycles( NBCYCLESFORDELAY);
  *control = *control & ~STOP_BIT_SELECT;				/* 1 stop bit */
  ioDelayAtLeastCycles( NBCYCLESFORDELAY);
  *control = (*control & ~BAUD_RATE_DIVISOR_MASK) |
             (0x17 << 16);																/* 9600 baud */
  ioDelayAtLeastCycles( NBCYCLESFORDELAY);
  *control = *control & ~UART_INTERRUPT_SELECT;	/* IRQ UART interrupt */
  ioDelayAtLeastCycles( NBCYCLESFORDELAY);
  *control = (*control | RX_INTERRUPT_ENABLE) &	/*  enable Rx interrupt */
             ~TX_INTERRUPT_ENABLE;												/* disable Tx interrupt */
  ioDelayAtLeastCycles( NBCYCLESFORDELAY);
  *control = *control | UART_ENABLE;						/* enable UART */
  ioDelayAtLeastCycles( NBCYCLESFORDELAY);
}


void ioConsolePutChar(char c)
{
  unsigned int* tx_data;
  unsigned int* status;

  tx_data = (unsigned int*) UART_DR_REGISTER;
  status = (unsigned int*) UART_SR_REGISTER;

  /* Wait for UART to become ready */
  while ((*status & TX_FIFO_READY) != TX_FIFO_READY)
  {
    ioDelayAtLeastCycles( NBCYCLESFORDELAY);
  }
  *tx_data = (*tx_data & ~UART_DATA_MASK) | (unsigned int) c; /* send it finally */
  ioDelayAtLeastCycles( NBCYCLESFORDELAY);
}
