/*********************************************************************** 
* NOTICE
* All files contained on this disk are subject to the licensing conditions
* issued by MOTOROLA Inc.
*
* All files are copyright 1993 by MOTOROLA Inc. 
************************************************************************/


/********************************************************
 * File:	uart.c
 *
 * Description:
 *	The driver routines for handling a UART port.
 *
 * Routines:
 *	uart_init
 *	uart_status
 *
 * Author:
 *	Jonathan Masel
 ********************************************************/

#include "gct.h"
#include "msg.h"
#include "config.h"
#include "types.h"
#include "mtypes.h"
#include "bss.h"
#include "quicc.h"
#include "states.h"
#include "uart.h"





/********************************************************
 * routine:	uart_init
 *
 * description:
 *	Initialize the driver tables for
 *	UART ports.
 *
 * arguments:
 *	n		the driver's child number
 *	uart		points to an scc configuration structure
 *
 * return code:
 *
 * side effects:
 *
 ********************************************************/
uart_init(n, scc)
int n;
struct scc *scc;
{
	GCT *gct;
	int (* *protocol)();
	unsigned adr, rom;
	CHILD *child;
	WORK_AREA *wa;
	int i;
	extern int uart_txreq(), uart_rxfr(), uart_conf(),
		return_to_pool(), uart_busy(), uart_status(),
		uart_abort(), uart_freeze();
	extern int uart_tx0(), uart_tx1(), uart_tx2(), uart_tx3();
	extern int uart_txchar(), uart_txbuf(), uart_rxbuf();

	GETGCT(gct);
	protocol = gct->driver->protocol;
	rom = gct->driver->rom;
	adr = (unsigned)uart_txreq + rom;
	child = &gct->driver->child[n];
	wa = (WORK_AREA *)child->work_area;

	adr = (unsigned)uart_txreq + rom;
	protocol[SUB(TX_REQ) | UART_STATE] = (int (*)())adr;
	adr = (unsigned)uart_rxfr + rom;
	protocol[SUB(RX_IND) | UART_STATE] = (int (*)())adr;
	adr = (unsigned)uart_conf + rom;
	protocol[SUB(TX_CONF) | UART_STATE] = (int (*)())adr;
	adr = (unsigned)uart_busy + rom;
	protocol[SUB(BUSY) | UART_STATE] = (int (*)())adr;
	adr = (unsigned)return_to_pool + rom;
	protocol[SUB(RTP) | UART_STATE] = (int (*)())adr;
	adr = (unsigned)uart_status + rom;
	protocol[SUB(STATUS) | UART_STATE] = (int (*)())adr;
	adr = (unsigned)uart_abort + rom;
	protocol[SUB(ABORT) | UART_STATE] = (int (*)())adr;
	adr = (unsigned)uart_freeze + rom;
	protocol[SUB(FREEZE) | UART_STATE] = (int (*)())adr;

	gct->driver->child[n].upper = scc->upper;
	gct->driver->child[n].state = UART_STATE;
	gct->driver->child[n].smac = &protocol[UART_STATE];
	wa->minpool = 0;	/* always zero (only for HDLC mode) */

	/*
	 * first BD in messages are set as follows:
	 * if multidrop, the address and preamble
	 * bits are set for the header buffers.
	 * if not multidrop, only the preamble.
	 * in any event, the firstBD bits ONLY
	 * apply to the header buffer.
	 */
	if( ((scc->scc_psmr&UOPT) == OPT_MULTD)
		|| ((scc->scc_psmr&UOPT) == OPT_AUTO) )
		wa->BDfirst = T_I | T_A | T_P;
	else
		wa->BDfirst = T_I | T_P;
	wa->BDlast = T_I | T_CR;
	wa->BDrx = R_I;
	wa->intr_rxfr = UART_RX;
	wa->intr_txbd = UART_TX;
	wa->intr_terr = 0;
	wa->intr_busy = UART_BUSY;
	wa->t_error = UART_T_ERROR;

	/*
	 * initialize uart specific parameter ram
	 */
	wa->pram->pscc.u.max_idl = scc->pram.u.max_idl;
	wa->pram->pscc.u.brkcr = scc->pram.u.brkcr;
	wa->pram->pscc.u.uaddr1 = scc->pram.u.uaddr1;
	wa->pram->pscc.u.uaddr2 = scc->pram.u.uaddr2;
	wa->pram->pscc.u.toseq = scc->pram.u.toseq;
	for(i = 0; i < 8; i++)
		wa->pram->pscc.u.cc[i] = scc->pram.u.cc[i];
	wa->pram->pscc.u.rccm = scc->pram.u.rccm;
	/*
	 * zeroing the rccr ensures that the MSB is zero.
	 * this is used to delimit the cc table.
	 */
	wa->pram->pscc.u.rccr = 0;

	/*
	 * zero counters
	 */
	wa->pram->pscc.u.parec = 0;
	wa->pram->pscc.u.frmer = 0;
	wa->pram->pscc.u.nosec = 0;
	wa->pram->pscc.u.brkec = 0;


	/*
	 * if the requested pool size is zero,
	 * the uart handler functions in the
	 * character oriented mode.
	 */
	if( scc->psize == 0 ){
		child->flags |= UART_CHARMODE;
		adr = (unsigned)uart_rxbuf + rom;
		protocol[SUB(RX_IND) | UART_STATE] = (int (*)())adr;
		adr = (unsigned)uart_txbuf + rom;
		protocol[SUB(TX_CONF) | UART_STATE] = (int (*)())adr;

		switch( n ){
		case 0:
			adr = (unsigned)uart_tx0 + rom;
			break;
		case 1:
			adr = (unsigned)uart_tx1 + rom;
			break;
		case 2:
			adr = (unsigned)uart_tx2 + rom;
			break;
		case 3:
			adr = (unsigned)uart_tx3 + rom;
			break;
		}

		if( gct )
			if( !gct->cput )
				gct->cput = (int (*)())adr;
	}
}



uart_status()
{
}

uart_tx0(c)
unsigned char c;
{
	uart_txchar(c, 0);
}

uart_tx1(c)
unsigned char c;
{
	uart_txchar(c, 1);
}

uart_tx2(c)
unsigned char c;
{
	uart_txchar(c, 2);
}

uart_tx3(c)
unsigned char c;
{
	uart_txchar(c, 3);
}
