/*********************************************************************** 
* 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:	dr_req.c
 *
 * Description:
 *	Handle requests for the driver module.
 *
 * Routines:
 *	dr_req
 *	quicc_configure
 *	dr_readreq
 *	dr_setreq
 *	dr_eventind
 *	driver_init
 *	save_config
 *
 * Author:
 *	Jonathan Masel
 ********************************************************/

#include "gct.h"
#include "msg.h"
#include "types.h"
#include "mtypes.h"
#include "status.h"
#include "modules.h"
#include "config.h"
#include "quicc.h"
#include "bss.h"
#include "bisync.h"
#include "fatal.h"
#include "tm.h"
#include "ethernet.h"
#include "dma.h"


extern int issue_cmd(unsigned short cmd, volatile unsigned short * quicc);

/********************************************************
 * routine:	request
 *
 * description:
 *	Handle a request destined for the driver module.
 *
 * arguments:
 *	m	points to the mesage received
 *
 * return code:
 *
 * side effects:
 *
 ********************************************************/
dr_req(m)
register MSG *m;
{
	int i, info;
	struct driver_config *dr;
	int status = 0;
	extern char *pic_adr();
	GCT *gct;

	GETGCT(gct);
	if( (m->hdr.type & CTG) == READ_REQ ){
		dr_readreq(m);
		return;
	} else if( (m->hdr.type & CTG) == SET_REQ ){
		dr_setreq(m);
		return;
	} else if( (m->hdr.type & CTG) == EVENT_IND ){
		dr_eventind((HDR *)m);
		return;
	} else if( (m->hdr.type & CTG) != ACT_REQ ){
		m->hdr.status = BAD_TYPE;
		conf_msg((HDR *)m, m->hdr.src);
		return;
	}

	/*
	 * action requests
	 */
	switch( (int)m->hdr.type ){
	case RESET:
	case RESTART:
		dr = (struct driver_config *)m->param[0];
		if( dr->index >= MAX_QUICCS ){
			status = BAD_PARAM;
			break;
		}

		/*
		 * initialize driver global variables
		 * when resetting the first QUICC
		 */
		if( (m->hdr.type == RESET) && (dr->index == 0) )
			driver_init(dr);


		/*
		 * write QUICC configuration registers
		 * and issue the software-reset command
		 */
		quicc_configure(dr);

		/*
		 * initialize protocol state machine
		 * the state of the driver machine is
		 * HDLC, UART or BISYNC for each SCC
		 */
		for(i = 0; i < 4; i++){
			if( dr->max <= dr->scc[i].child_id )
				continue;
			if( scc_ioctl(i, &dr->scc[i]) ){
				status = NO_MEM;
				break;
			}
		}

		/*
		 * If an SCC is in the Ethernet mode, The pio_pcpar
		 * register should be re-initialized after the SCCs
		 * mode register has been initialized.
		 */
		dr->internal_ram->pio_pcpar = dr->pio_pcpar;

		for(i = 0; i < 2; i++){
			if( dr->max <= dr->idma[i].child_id )
				continue;
			dma_ioctl(i, &dr->idma[i]);
		}
		for(i = 0; i < 2; i++){
			if( dr->max <= dr->smc[i].child_id )
				continue;
			smc_ioctl(i, &dr->smc[i]);
		}


		if( dr->max > dr->spi.child_id )
			status = spi_init(&dr->spi);


		/*
		 * now initialize the timer (only for
		 * the first QUICC.
		 * Note that this does not imply that a
		 * timer on this QUICC is being used, it merely
		 * prevents resetting timers when the other QUICC's
		 * are reset. (This assumes that the first QUICC
		 * is set up first).
		 */
		if( dr->index == 0 ) {
			timer_init();
			ethernet_tables_init();
		}
		break;

	case IOCTL_SCC:
		/*
		 * m->hdr.id is the SCC channel number (0/1/2/3)
		 */
		info = scc_ioctl((int)m->hdr.id,
				(struct scc *)m->param);
		if( info ){
			status = NO_MEM;
			m->hdr.err_info = info;
			break;
		}
		break;

	case IOCTL_SMC:
		/*
		 * m->hdr.id is the SMC channel number (0/1)
		 */
		info = smc_ioctl((int)m->hdr.id,
				(struct smc *)m->param);
		if( info ){
			status = NO_MEM;
			m->hdr.err_info = info;
			break;
		}
		break;

	case IOCTL_SPI:
		/*
		 * param[0] = upper
		 */
                status = spi_init((struct spi *)m->param);
		break;

	case RECONFIG:
		save_config();
		break;

	case RECEIVER:
		status = driver_rx(m);
		break;

	case CONFIRMER:
		status = driver_conf(m);
		break;

	case KEEP_TIME:
		/*
		 * start timer services for a module
		 * NOTE: keep_time calls conf_msg, so
		 * we must return, rather than break here.
		 */
		keep_time(m);
		return;

	case REMOVE_TIMER:
		/*
		 * remove a timer
		 * NOTE: clear_time calls conf_msg, so
		 * we must return, rather than break here.
		 */
		clear_timer(m);
		return;

	case ISSUE_CMD:
		{ GCT *gct;
		WORK_AREA *wa;

		GETGCT(gct);
		wa = (WORK_AREA *)gct->driver->child[0].work_area;
		status = issue_cmd((unsigned short)(m->param[0]),
				(unsigned short *)wa->quicc);
		}
		break;

	case ENET_ADD_ADR:
		status = ethernet_add_addr(m);
		break;

	case ENET_CLR_ADRS:
		if( m->param[0] & CLR_GRP_ADDRS)
			status = ethernet_clr_grp_addrs(m);
		if( m->param[0] & CLR_IND_ADDRS)
			status = ethernet_clr_ind_addrs(m);
		break;

	default:
		FATAL(pic_adr("bad request for driver (%x)\n", DRIVER),
			m->hdr.type);
		break;
	}

	m->hdr.status = status;
	conf_msg((HDR *)m, m->hdr.src);
}



/********************************************************
 * routine:	scc_ioctl
 *
 * description:
 *	Initialize an SCC channel. Registers are set,
 *	protocol tables set up and receive buffer pool
 *	created.
 *
 * arguments:
 *	i		SCC channel number
 *	scc		SCC configuration structure
 *
 * return code:
 *	0		on success
 *	otherwise	not enough memory for receive buffer pool
 *
 * side effects:
 *
 ********************************************************/
scc_ioctl(port, scc)
int port;
struct scc *scc;
{
	int j, child_id;
	register unsigned long mode;
	GCT *gct;
	GWA *gwa;
	WORK_AREA *wa;

	GETGCT(gct);
	child_id = (int)scc->child_id;
	wa = (WORK_AREA *)gct->driver->child[child_id].work_area;
	/*
	 * initialize global SCC parameters
	 */
	scc_init(port, scc);
	mode = scc->scc_gsmra;

	if( (mode&MODE) == HDLC_PORT )
		hdlc_init(child_id, scc);
	else if( (mode&MODE) == UART )
		uart_init(child_id, scc);
	else if( (mode&MODE) == BISYNC_PORT )
		bisync_init(child_id, scc);
	else if( (mode&MODE) == ETHERNET_PORT )
		ethernet_init(child_id, scc);

	if (wa->more_flags & SCC_TRX)
		wa->intr_rxfr = TM_RBD;
	if (wa->more_flags & SCC_TTX)
		wa->t_error = TM_T_ERROR;
	/*
	 * prepare the transmission table
	 */
	scc_itx(child_id, scc->tsize);

	/*
	 * build the receive pool
	 */
	j = scc_pool((unsigned short)child_id, scc->psize);

	/*
	 * set up SCC channel registers
	 */
	scc_regs(child_id, scc);

	return(j? NO_MEM: 0);
}

/********************************************************
 * routine:	smc_ioctl
 *
 * description:
 *	Initialize an SMC channel. Registers are set,
 *	protocol tables set up and receive buffer pool
 *	created.
 *
 * arguments:
 *	i		SCC channel number
 *	smc		SCC configuration structure
 *
 * return code:
 *	0		on success
 *	otherwise	not enough memory for receive buffer pool
 *
 * side effects:
 *
 ********************************************************/
smc_ioctl(port, smc)
int port;
struct smc *smc;
{
	int j, child_id;
	register unsigned long mode;
	GCT *gct;
	GWA *gwa;
	WORK_AREA *wa;

	GETGCT(gct);
	child_id = (int)smc->child_id;
	wa = (WORK_AREA *)gct->driver->child[child_id].work_area;
	/*
	 * initialize global SCC parameters
	 */
	smc_init(port, smc);
	mode = smc->smc_smcmr;

	if( (mode&SMC_MODE) == SMC_UART )
		smc_uart_init(child_id, smc);
	if( (mode&SMC_MODE) == SMC_TRANSPARENT )
		smc_tm_init(child_id, smc);

	/*
	 * prepare the transmission table
	 */
	smc_itx(child_id, smc->tsize);

	/*
	 * build the receive pool
	 */
	j = smc_pool((unsigned short)child_id, smc->psize);

	/*
	 * set up SMC channel registers
	 */
	smc_regs(child_id, smc);

	return(j? NO_MEM: 0);
}


/********************************************************
 * routine:	dma_ioctl
 *
 * description:
 *	Initialize an IDMA channel. Registers are set
 *	and protocol tables set up
 *
 * arguments:
 *	i		IDMA channel number
 *	idma		IDMA configuration structure
 *
 * return code:
 *
 * side effects:
 *
 ********************************************************/
dma_ioctl(port, idma)
int port;
struct idma *idma;
{
	int j, child_id;
	register unsigned long mode;
	GCT *gct;
	GWA *gwa;
	WORK_AREA *wa;

	GETGCT(gct);
	child_id = (int)idma->child_id;
	wa = (WORK_AREA *)gct->driver->child[child_id].work_area;
	/*
	 * initialize global IDMA parameters
	 */
	dma_init(port, idma);
	mode = idma->idma_cmr;

	/* Single Buffer Mode */
	if (!(mode&RCI_BIT)) {
		dma_regs(child_id, idma, port);
		return;
	}

	/*
	 * prepare the transmission table
	 */
	dma_itx(child_id, idma->isize);

	/*
	 * set up IDMA channel registers
	 */
	dma_regs(child_id, idma, port);
}

/********************************************************
 * routine:	quicc_configure
 *
 * description:
 *	Initialze the QUICC by writing all of its configuration
 *	registers.
 *
 * arguments:
 *	dr		points to driver configuration structure
 *
 * return code:
 *
 * side effects:
 *
 ********************************************************/
quicc_configure(dr)
struct driver_config *dr;
{
	QUICC *quicc;
	int	i;
	GCT *gct;

	GETGCT(gct);
	quicc = dr->internal_ram;

	/*
	 * write system configuration registers
	 * and registers 
	 */

	 /* sim */
	quicc->sim_mcr = dr->sim_mcr;
	quicc->sim_simtr = dr->sim_simtr;
	quicc->sim_avr = dr->sim_avr;
	quicc->sim_clkocr = dr->sim_clkocr;
	quicc->sim_pllcr = dr->sim_pllcr;
	quicc->sim_cdvcr = dr->sim_cdvcr;
	quicc->sim_pepar = dr->sim_pepar;
	quicc->sim_swiv = dr->sim_swiv;
	quicc->sim_sypcr = dr->sim_sypcr;
	quicc->sim_picr = dr->sim_picr;
	quicc->sim_pitr = dr->sim_pitr;
	quicc->sim_swsr = dr->sim_swsr;
	quicc->sim_bkar = dr->sim_bkar;
	quicc->sim_bkcr = dr->sim_bkcr;
	quicc->memc_gmr = dr->memc_gmr;
	
	quicc->memc_br1 = dr->memc_br1;
	quicc->memc_or1 = dr->memc_or1;
	quicc->memc_br2 = dr->memc_br2;
	quicc->memc_or2 = dr->memc_or2;
	quicc->memc_br3 = dr->memc_br3;
	quicc->memc_or3 = dr->memc_or3;
	quicc->memc_br4 = dr->memc_br4;
	quicc->memc_or4 = dr->memc_or4;
	quicc->memc_br5 = dr->memc_br5;
	quicc->memc_or5 = dr->memc_or5;
	quicc->memc_br6 = dr->memc_br6;
	quicc->memc_or6 = dr->memc_or6;
	quicc->memc_br7 = dr->memc_br7;
	quicc->memc_or7 = dr->memc_or7;



	quicc->idma_iccr = dr->idma_iccr;
	quicc->sdma_sdcr = dr->sdma_sdcr;

	quicc->intr_cicr |= dr->intr_cicr;

	quicc->pio_papar = dr->pio_papar;
	quicc->pio_pcpar =
			dr->pio_pcpar & 0xfff0;

	quicc->timer_tgcr = dr->timer_tgcr;

	quicc->cp_rccr |= dr->cp_rccr;
	quicc->cp_rmdr = dr->cp_rmdr;
	quicc->cp_cpcr1 = dr->cp_cpcr1;
	quicc->cp_cpcr2 = dr->cp_cpcr2;
	quicc->cp_cpcr3 = dr->cp_cpcr3;
	quicc->cp_cpcr4 = dr->cp_cpcr4;

	quicc->pip_pbpar = dr->pip_pbpar;


	/*
	 * issue software reset command
	 */
	issue_cmd(SOFTWARE_RESET, (unsigned short *)quicc);


	/* idma */

	quicc->idma1_cmr = dr->idma[1].idma_cmr;
	quicc->idma1_sapr = dr->idma[1].idma_sapr;
	quicc->idma1_dapr = dr->idma[1].idma_dapr;
	quicc->idma1_bcr = dr->idma[1].idma_bcr;
	quicc->idma1_fcr = dr->idma[1].idma_fcr;
	quicc->idma1_cmar = dr->idma[1].idma_cmar;
	quicc->idma1_csr = dr->idma[1].idma_csr;
	quicc->idma2_cmr = dr->idma[2].idma_cmr;
	quicc->idma2_sapr = dr->idma[2].idma_sapr;
	quicc->idma2_dapr = dr->idma[2].idma_dapr;
	quicc->idma2_bcr = dr->idma[2].idma_bcr;
	quicc->idma2_fcr = dr->idma[2].idma_csr;
	quicc->idma2_cmar = dr->idma[2].idma_cmar;
	quicc->idma2_csr = dr->idma[2].idma_csr;


	/* sdma */
	quicc->sdma_sdar = dr->sdma_sdar;

	/* interrupt controller */
	quicc->intr_cimr = dr->intr_cimr;

	/* parallel I/O */
	quicc->pio_padir = dr->pio_padir;
	quicc->pio_paodr = dr->pio_paodr;
	quicc->pio_padat = dr->pio_padat;
	quicc->pio_pcdir = dr->pio_pcdir;
	quicc->pio_pcso = dr->pio_pcso;
	quicc->pio_pcdat = dr->pio_pcdat;
	quicc->pio_pcint = dr->pio_pcint;

	/* timer */
	quicc->timer_tmr1 = dr->timer_tmr1;
	quicc->timer_tmr2 = dr->timer_tmr2;
	quicc->timer_trr1 = dr->timer_trr1;
	quicc->timer_trr2 = dr->timer_trr2;
	quicc->timer_tmr3 = dr->timer_tmr3;
	quicc->timer_tmr4 = dr->timer_tmr4;
	quicc->timer_trr3 = dr->timer_trr3;
	quicc->timer_trr4 = dr->timer_trr4;

	/* cp */
	quicc->cp_cr = dr->cp_cr;
	quicc->cp_rtmr = dr->cp_rtmr;

	/* brg */
	quicc->brgc1 = dr->brgc1;
	quicc->brgc2 = dr->brgc2;
	quicc->brgc3 = dr->brgc3;
	quicc->brgc4 = dr->brgc4;

	/* pip */
	quicc->pip_pipc = dr->pip_pipc;
	quicc->pip_ptpr = dr->pip_ptpr;
	quicc->pip_pbdir = dr->pip_pbdir;
	quicc->pip_pbodr = dr->pip_pbodr;
	quicc->pip_pbdat = dr->pip_pbdat;

	/* si */
	quicc->si_simode = dr->si_simode;
	quicc->si_sigmr = dr->si_sigmr;
	quicc->si_sicr = dr->si_sicr;


	/* memc */






}



/********************************************************
 * routine:	dr_readreq
 *
 * description:
 *	Handle a read request for the driver
 *
 * arguments:
 *	m		the message received
 *
 * return code:
 *
 * side effects:
 *
 ********************************************************/
dr_readreq(m)
MSG *m;
{
	GCT *gct;
	WORK_AREA *wa;
	T_QUEUE *tq;
	R_QUEUE *rq;

	GETGCT(gct);
	wa = (WORK_AREA *)gct->driver->child[m->hdr.id].work_area;

	switch( (int)m->hdr.type ){
	case INTERNAL_RAM:
		/*
		 * address of structure is returned in param[0]
		 */
		wa = (WORK_AREA *)gct->driver->child[0].work_area;
		m->param[0] = (int)wa->quicc;
		break;
	case TX_QUEUE:
		tq = (T_QUEUE *)m->param;
		tq->conf_q = wa->conf_q;
		tq->ack_q = 0;
		tq->tx_q = wa->tx_q;
		tq->req_q = wa->req_q;
		break;
	case RX_QUEUE:
		rq = (R_QUEUE *)m->param;
		rq->rx_q = wa->rx_q;
		rq->pool_q = wa->pool_q;
		rq->rtp_q = wa->rtp_q;
		break;
	case R_CHILD:
		m->param[0] = (int)&(gct->driver->child[m->hdr.id]);
		break;
	case R_BSS:
		m->param[0] = (int)gct->driver;
		break;
	case RXERR_MASK:
		m->param[0] = wa->rxerr_mask;
		break;
	}
	conf_msg((HDR *)m, m->hdr.src);
}



/********************************************************
 * routine:	dr_setreq
 *
 * description:
 *	Handle a set request for the driver
 *
 * arguments:
 *	m		the message received
 *
 * return code:
 *
 * side effects:
 *
 ********************************************************/
dr_setreq(m)
MSG *m;
{
	GCT *gct;
	WORK_AREA *wa;

	GETGCT(gct);
	wa = (WORK_AREA *)gct->driver->child[m->hdr.id].work_area;

	switch( (int)m->hdr.type ){
	case RXERR_MASK:
		wa->rxerr_mask = m->param[0];
		break;
	}

	conf_msg((HDR *)m, gct->driver->child[m->hdr.id].upper);
}


/********************************************************
 * routine:	dr_eventind
 *
 * description:
 *	Handle an event indication. Note that the message
 *	received is not an allocated block, and should
 *	not be relm-ed.
 *
 * arguments:
 *	h		points to the message received
 *
 * return code:
 *
 * side effects:
 *
 ********************************************************/
dr_eventind(h)
HDR *h;
{
	switch( (int)h->type ){
	case TIMER_TICK:
		timer_tick(h);
		break;
	case POLL:
		break;
	}
}


/********************************************************
 * routine:	driver_init
 *
 * description:
 *	Initialize the global variables of the driver module.
 *
 * arguments:
 *	dr		points to the configuration structure
 *
 * return code:
 *
 * side effects:
 *
 ********************************************************/

#define getadr(x)	((unsigned)x + (gct->driver->rom))

driver_init(dr)
struct driver_config *dr;
{
	register int i;
	GCT *gct;
	CHILD *child;
	GWA *gwa;
	WORK_AREA *wa;
	unsigned adr;
	int (* *protocol)();
	extern int tick(), bad_prim();
	extern int  piopc0_intr()
		, scc1_intr()
		, scc2_intr()
		, scc3_intr()
		, scc4_intr()
		, piopc1_intr()
		, tim1_intr()
		, piopc2_intr()
		, piopc3_intr()
		, sdmaberr_intr()
		, dma1_intr()
		, dma2_intr()
		, tim2_intr()
		, cptim_intr()
		, piopc4_intr()
		, piopc5_intr()
		, tim3_intr()
		, piopc6_intr()
		, piopc7_intr()
		, piopc8_intr()
		, tim4_intr()
		, piopc9_intr()
		, spi_intr()
		, smc1_intr()
		, smc2_intr()
		, piopc10_intr()
		, piopc11_intr()
		, error_intr();



	GETGCT(gct);
	gwa = (GWA *)gct->driver->work_area;
	gct->driver->rom = dr->rom;
	gct->driver->max = dr->max;
	gwa->num_timers = dr->num_timers;
	gwa->trace_mask = dr->trace_mask;
	gwa->intr_trace = dr->intr_trace;
	gwa->timer_tick = (TIMER_TICK << 16);
	gwa->timer_poll = (POLL << 16);
	gwa->soh = 1;
	gwa->stx = 2;
	gwa->etx = 3;
	gwa->eot = 4;
	gwa->conf[dr->index] = dr;
	if( !gct->tick )
		gct->tick = (int (*)())getadr(tick);
	gct->QUICCpiopc0 = (int (*)())getadr(piopc0_intr);
	gct->QUICCscc1 = (int (*)())getadr(scc1_intr);
	gct->QUICCscc2 = (int (*)())getadr(scc2_intr);
	gct->QUICCscc3 = (int (*)())getadr(scc3_intr);
	gct->QUICCscc4 = (int (*)())getadr(scc4_intr);
	gct->QUICCpiopc1 = (int (*)())getadr(piopc1_intr);
	gct->QUICCtim1 = (int (*)())getadr(tim1_intr);
	gct->QUICCpiopc2 = (int (*)())getadr(piopc2_intr);
	gct->QUICCpiopc3 = (int (*)())getadr(piopc3_intr);
	gct->QUICCsdmaberr = (int (*)())getadr(sdmaberr_intr);
	gct->QUICCdma1 = (int (*)())getadr(dma1_intr);
	gct->QUICCdma2 = (int (*)())getadr(dma2_intr);
	gct->QUICCtim2 = (int (*)())getadr(tim2_intr);
	gct->QUICCcptim = (int (*)())getadr(cptim_intr);
	gct->QUICCpiopc4 = (int (*)())getadr(piopc4_intr);
	gct->QUICCpiopc5 = (int (*)())getadr(piopc5_intr);
	gct->QUICCtim3 = (int (*)())getadr(tim3_intr);
	gct->QUICCpiopc6 = (int (*)())getadr(piopc6_intr);
	gct->QUICCpiopc7 = (int (*)())getadr(piopc7_intr);
	gct->QUICCpiopc8 = (int (*)())getadr(piopc8_intr);
	gct->QUICCtim4 = (int (*)())getadr(tim4_intr);
	gct->QUICCpiopc9 = (int (*)())getadr(piopc9_intr);
	gct->QUICCspi = (int (*)())getadr(spi_intr);
	gct->QUICCsmc1 = (int (*)())getadr(smc1_intr);
	gct->QUICCsmc2 = (int (*)())getadr(smc2_intr);
	gct->QUICCpiopc10 = (int (*)())getadr(piopc10_intr);
	gct->QUICCpiopc11 = (int (*)())getadr(piopc11_intr);
	gct->QUICCerror = (int (*)())getadr(error_intr);

	/* initialize protocol table routines */
	adr = (unsigned)bad_prim + dr->rom;
	protocol = gct->driver->protocol;
	for(i = 0; i < TABLE; i++)
		protocol[i] = (int (*)())adr;

	/* initialize child field values */
	for(i = 0; i < dr->max; i++){
		child = &gct->driver->child[i];
		child->key = i;
		child->layer = LAYER(DRIVER);
		child->flags = 0;
		wa = (WORK_AREA *)child->work_area;
		wa->rx_q = 0;
		wa->conf_q = 0;
		wa->more_flags = 0;
	}
}


/********************************************************
 * routine:	save_config
 *
 * description:
 *	Save the current QUICC configuration, as defined in
 *	its internal registers.
 *	This may be done before a RESTART request in order
 *	to change the driver's default configuration.
 *	NOTE: This routine is written for the ADS boards.
 *	It is assumed here that only 1 QUICC is being used
 *	(index 0) and that the first three children of the
 *	driver are assigned to SCC channels 1,2,3 respectively.
 *
 * arguments:
 *
 * return code:
 *
 * side effects:
 *
 ********************************************************/
save_config()
{
	GCT *gct;
	struct driver_config *driver;
	QUICC *quicc;
	CHILD *child;
	WORK_AREA *wa;
	int i, j;
	unsigned long mode;

	GETGCT(gct);
	driver = ((GWA *)gct->driver->work_area)->conf[0];
	wa = (WORK_AREA *)gct->driver->child[0].work_area;
	quicc = wa->quicc;

	 /* sim */
	driver->sim_mcr = quicc->sim_mcr;
	driver->sim_simtr = quicc->sim_simtr;
	driver->sim_avr = quicc->sim_avr;
	driver->sim_clkocr = quicc->sim_clkocr;
	driver->sim_pllcr = quicc->sim_pllcr;
	driver->sim_cdvcr = quicc->sim_cdvcr;
	driver->sim_pepar = quicc->sim_pepar;
	driver->sim_swiv = quicc->sim_swiv;
	driver->sim_sypcr = quicc->sim_sypcr;
	driver->sim_picr = quicc->sim_picr;
	driver->sim_pitr = quicc->sim_pitr;
	driver->sim_swsr = quicc->sim_swsr;
	driver->sim_bkar = quicc->sim_bkar;
	driver->sim_bkcr = quicc->sim_bkcr;

	/* memc
	driver->memc_gmr = quicc->memc_gmr;
	driver->memc_br0 = quicc->memc_br0;
	driver->memc_or0 = quicc->memc_or0;
	driver->memc_br1 = quicc->memc_br1;
	driver->memc_or1 = quicc->memc_or1;
	driver->memc_br2 = quicc->memc_br2;
	driver->memc_or2 = quicc->memc_or2;
	driver->memc_br3 = quicc->memc_br3;
	driver->memc_or3 = quicc->memc_or3;
	driver->memc_br4 = quicc->memc_br4;
	driver->memc_or4 = quicc->memc_or4;
	driver->memc_br5 = quicc->memc_br5;
	driver->memc_or5 = quicc->memc_or5;
	driver->memc_br6 = quicc->memc_br6;
	driver->memc_or6 = quicc->memc_or6;
	driver->memc_br7 = quicc->memc_br7;
	driver->memc_or7 = quicc->memc_or7;

	/* idma */
	driver->idma_iccr = quicc->idma_iccr;
	for(i = 0; i < 2; i++){
		driver->idma[i].idma_cmr = IDMA_CMR(i);
		driver->idma[i].idma_sapr = IDMA_SAPR(i);
		driver->idma[i].idma_dapr = IDMA_DAPR(i);
		driver->idma[i].idma_bcr = IDMA_BCR(i);
		driver->idma[i].idma_fcr = IDMA_FCR(i);
		driver->idma[i].idma_cmar = IDMA_CMAR(i);
		driver->idma[i].idma_csr = IDMA_CSR(i);
	}

	/* sdma */
	driver->sdma_sdcr = quicc->sdma_sdcr;
	driver->sdma_sdar = quicc->sdma_sdar;

	/* interrupt controller */
	driver->intr_cicr = quicc->intr_cicr;
	driver->intr_cimr = quicc->intr_cimr;

	/* parallel I/O */
	driver->pio_padir = quicc->pio_padir;
	driver->pio_papar = quicc->pio_papar;
	driver->pio_paodr = quicc->pio_paodr;
	driver->pio_padat = quicc->pio_padat;
	driver->pio_pcdir = quicc->pio_pcdir;
	driver->pio_pcpar = quicc->pio_pcpar;
	driver->pio_pcso = quicc->pio_pcso;
	driver->pio_pcdat = quicc->pio_pcdat;
	driver->pio_pcint = quicc->pio_pcint;

	/* timer */
	driver->timer_tgcr = quicc->timer_tgcr;
	driver->timer_tmr1 = quicc->timer_tmr1;
	driver->timer_tmr2 = quicc->timer_tmr2;
	driver->timer_trr1 = quicc->timer_trr1;
	driver->timer_trr2 = quicc->timer_trr2;
	driver->timer_tmr3 = quicc->timer_tmr3;
	driver->timer_tmr4 = quicc->timer_tmr4;
	driver->timer_trr3 = quicc->timer_trr3;
	driver->timer_trr4 = quicc->timer_trr4;

	/* cp */
	driver->cp_cr = quicc->cp_cr;
	driver->cp_rccr = quicc->cp_rccr;
	driver->cp_rmdr = quicc->cp_rmdr;
	driver->cp_cpcr1 = quicc->cp_cpcr1;
	driver->cp_cpcr2 = quicc->cp_cpcr2;
	driver->cp_cpcr3 = quicc->cp_cpcr3;
	driver->cp_cpcr4 = quicc->cp_cpcr4;
	driver->cp_rtmr = quicc->cp_rtmr;

	/* brg */
	driver->brgc1 = quicc->brgc1;
	driver->brgc2 = quicc->brgc2;
	driver->brgc3 = quicc->brgc3;
	driver->brgc4 = quicc->brgc4;

	/* smc */
	for(i = 0; i < 2; i++){
		driver->smc[i].smc_smcmr = quicc->smc_regs[i].smc_smcmr;
		driver->smc[i].smc_smce = quicc->smc_regs[i].smc_smce;
		driver->smc[i].smc_smcm = quicc->smc_regs[i].smc_smcm;

		/* parameter ram */
		driver->smc[i].rbase =
			wa->pram->pothers.idma_smc.psmc.u.rbase;
		driver->smc[i].tbase =
			wa->pram->pothers.idma_smc.psmc.u.tbase;
		driver->smc[i].rfcr =
			wa->pram->pothers.idma_smc.psmc.u.rfcr;
		driver->smc[i].tfcr =
			wa->pram->pothers.idma_smc.psmc.u.tfcr;
		driver->smc[i].mrblr =
			wa->pram->pothers.idma_smc.psmc.u.mrblr;
		driver->smc[i].rbptr =
			wa->pram->pothers.idma_smc.psmc.u.rbptr;
		driver->smc[i].tbptr =
			wa->pram->pothers.idma_smc.psmc.u.tbptr;


		mode = driver->smc[i].smc_smcmr;
		if( (mode&SMC_MODE) == SMC_UART ) {
			driver->smc[i].pram.u.max_idl =
				wa->pram->pothers.idma_smc.psmc.u.max_idl;
			driver->smc[i].pram.u.brkln =
				wa->pram->pothers.idma_smc.psmc.u.brkln;
			driver->smc[i].pram.u.brkec =
				wa->pram->pothers.idma_smc.psmc.u.brkec;
			driver->smc[i].pram.u.brkcr =
				wa->pram->pothers.idma_smc.psmc.u.brkcr;
		}
	}

	for(i = 0; i < 4; i++){
		child = &gct->driver->child[i];
		wa = (WORK_AREA *)child->work_area;
		driver->scc[i].upper = child->upper;
		driver->scc[i].tsize = wa->tsize;
		driver->scc[i].rsize = wa->rsize;
		driver->scc[i].minpool = wa->minpool;
		driver->scc[i].rxerr_mask = wa->rxerr_mask;

		driver->scc[i].scc_gsmra = quicc->scc_regs[i].scc_gsmra;
		driver->scc[i].scc_gsmrb = quicc->scc_regs[i].scc_gsmrb;
		driver->scc[i].scc_psmr = quicc->scc_regs[i].scc_psmr;
		driver->scc[i].scc_dsr = quicc->scc_regs[i].scc_dsr;
		driver->scc[i].scc_sccm = quicc->scc_regs[i].scc_sccm;

		driver->scc[i].rbase = wa->pram->pscc.h.rbase;
		driver->scc[i].tbase = wa->pram->pscc.h.tbase;
		driver->scc[i].rfcr = wa->pram->pscc.h.rfcr;
		driver->scc[i].tfcr = wa->pram->pscc.h.tfcr;
		driver->scc[i].mrblr = wa->pram->pscc.h.mrblr;
		driver->scc[i].rbptr = wa->pram->pscc.h.rbptr;
		driver->scc[i].tbptr = wa->pram->pscc.h.tbptr;
		driver->scc[i].crc_p = wa->pram->pscc.t.crc_p;
		driver->scc[i].crc_c = wa->pram->pscc.t.crc_c;


		/* parameter RAM */
		mode = driver->scc[i].scc_gsmra;
		if( (mode&MODE) == HDLC_PORT ){
			/* HDLC parameter RAM */
			driver->scc[i].pram.h.c_mask =
					wa->pram->pscc.h.c_mask;
			driver->scc[i].pram.h.c_pres =
					wa->pram->pscc.h.c_pres;
			driver->scc[i].pram.h.disfc =
					wa->pram->pscc.h.disfc;
			driver->scc[i].pram.h.crcec =
					wa->pram->pscc.h.crcec;
			driver->scc[i].pram.h.abtsc =
					wa->pram->pscc.h.abtsc;
			driver->scc[i].pram.h.nmarc =
					wa->pram->pscc.h.nmarc;
			driver->scc[i].pram.h.retrc =
					wa->pram->pscc.h.retrc;
			driver->scc[i].pram.h.mflr =
					wa->pram->pscc.h.mflr;
			driver->scc[i].pram.h.rfthr =
					wa->pram->pscc.h.rfthr;
			driver->scc[i].pram.h.hmask =
					wa->pram->pscc.h.hmask;
			driver->scc[i].pram.h.haddr1 =
					wa->pram->pscc.h.haddr1;
			driver->scc[i].pram.h.haddr2 =
					wa->pram->pscc.h.haddr2;
			driver->scc[i].pram.h.haddr3 =
					wa->pram->pscc.h.haddr3;
			driver->scc[i].pram.h.haddr4 =
					wa->pram->pscc.h.haddr4;

		} /* else if( ((mode&MODE) == ASYNC_PORT) &&
			((mode&UOPT) != OPT_DDCMP) ){
			* UART parameter RAM *
			driver->scc[i].pram.u.max_idl =
				wa->pram->pscc.u.max_idl;
			driver->scc[i].pram.u.brkcr =
				wa->pram->pscc.u.brkcr;
			driver->scc[i].pram.u.uaddr1 =
				wa->pram->pscc.u.uaddr1;
			driver->scc[i].pram.u.uaddr2 =
				wa->pram->pscc.u.uaddr2;
			driver->scc[i].pram.u.uaddm =
				wa->pram->pscc.u.uaddm;
			driver->scc[i].pram.u.toseq =
				wa->pram->pscc.u.toseq;
			for( j = 0; j < 8; j++)
				driver->scc[i].pram.u.cc[j] =
					wa->pram->pscc.u.cc[j];
			driver->scc[i].pram.u.rccm =
				wa->pram->pscc.u.rccm;
		} else if( (mode&MODE) == BISYNC_PORT ){
			* BISYNC parameter RAM *
			driver->scc[i].pram.b.prcrc =
				wa->pram->pscc.b.prcrc;
			driver->scc[i].pram.b.ptcrc =
				wa->pram->pscc.b.ptcrc;
			driver->scc[i].pram.b.bsync =
				wa->pram->pscc.b.bsync;
			driver->scc[i].pram.b.bdle =
				wa->pram->pscc.b.bdle;
			for( j = 0; j < 8; j++)
				driver->scc[i].pram.b.cc[j] =
					wa->pram->pscc.b.cc[j];
			driver->scc[i].pram.b.rccm =
				wa->pram->pscc.b.rccm;
		}
*/
		/* there is no V.110 specific parameter RAM */
	}

}
