/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION  1986,1987,1988
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header:aed.c 12.0$ */
/* $ACIS:aed.c 12.0$ */
/* $Source: /ibm/acis/usr/sys/cacons/RCS/aed.c,v $ */

#if !defined(lint) && !defined(NO_RCS_HDRS)
static char *rcsid = "$Header:aed.c 12.0$";
#endif

#include "aed.h"
#if NAED > 0
#define AEDDEBUG
#include "../h/param.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/proc.h"
#include "../h/conf.h"
#include "../h/errno.h"
#include "../h/buf.h"
#include "../h/ioctl.h"
#include "../h/signal.h"
#include "../h/uio.h"
#include "../machine/debug.h"
#include "../h/aedioctl.h"
#include "../machine/machparam.h"
#include "../machineio/ioccvar.h"
#include "../h/tty.h"
#include "../machinecons/screen_conf.h"
#include "../machinecons/aeddefs.h"
#include "../machine/io.h"
#include "../machinecons/aedtty.h"

char aedstep = 0;		/* I guess */

#define ISPEED			B9600


AED aed_info;
struct buf aedbuf;
struct tty aedsotty;
extern 

int aedstrategy();
int aedatch();
int aedprobe();

struct	iocc_device *aedinfo[NAED];
caddr_t aedstd[] = { (caddr_t)  0xa0000 + MEM_BASE, 0 };
int aedintr();

#define AED_ISOPEN	0x01

aedopen(dev, tp, si)
dev_t dev;
register struct tty *tp;
register SCREEN_INFO *si;
{
	register AED *aed = &aed_info;	/* get AED state struct */
	register EMUL_INFO *ei = &si->oute;
	int dummy;
	AED_ENTER();

#ifdef AEDDEBUG
	if (aeddebug)
		printf("AEDOPEN\n");
#endif AEDDEBUG
	if (ei->flag & AED_ISOPEN)
		return (0);

	ei->flag = AED_ISOPEN;
	/* Should always reset aed structure */
	/* review whether the structure is even needed! */
	AED_DELAY;
	aed->state = 0;
	aed->pgrp = 0;
	aed->ctrl_offset = 0;
	aed->sram_loc = AED_MMAP + 0x4000;
	AED_DELAY;
	aedrd(&dummy,1,AED_RESET);	/* reset AED processor */
	AED_DELAY;

	/* Open a buffer emulator for putc output for this emulator */
	buf_open (dev, tp, si);

	AED_EXIT();
	return(0);
}


aedclose(tp, si)
register struct tty *tp;
register SCREEN_INFO *si;
{
	register EMUL_INFO *ei = &si->oute;
#ifdef AEDDEBUG
	if (aeddebug)
		printf("AEDCLOSE\n");
#endif AEDDEBUG
	ei->flag = 0;
	ei->unit = 0;
	return(0);
}

	/* the following needs to be simplified */
aedread(tp,uio,si)
register struct tty *tp;
register struct uio *uio;
register SCREEN_INFO *si;
{
#ifdef AEDDEBUG
	if (aeddebug)
		printf("AEDREAD\n");
#endif AEDDEBUG
	return(physio(aedstrategy,&aedbuf,tp->t_dev,B_READ,minphys,uio));
}

	/* the following needs to be simplified. */
aedwrite(tp,uio,si)
register struct tty *tp;
register struct uio *uio;
register SCREEN_INFO *si;
{
#ifdef AEDDEBUG
if (aeddebug)
	printf("AEDWRITE\n");
#endif AEDDEBUG
	return(physio(aedstrategy,&aedbuf,tp->t_dev,B_WRITE,minphys,uio));
}

int breakout = 0;
static int timeout = 250;

	/* the following needs to be simplified */
aedioctl(tp,cmd,data,si)
register struct tty *tp;
register caddr_t data;
register SCREEN_INFO *si;
{
	register AED *aed = &aed_info;
	int dummy;
	int counter;
	short poll;
	AED_ENTER();

#ifdef AEDDEBUG
	if (aeddebug)
		printf("AEDIOCTL\n");
#endif AEDDEBUG
	switch (cmd) {
	case AED_BEEP:
		beep();		/* kernel beep routine. in cons.c ? */
		break;
	case AEDGET_CTRL_LOC:
		/* Report current offset of AED control store pointer */
		*(long *)data = (long)aed->ctrl_offset;
		break;
	case AEDSET_CTRL_LOC:
		/* set offset of AED control store pointer */
		if (*(long *)data < 0 || *(long *)data >= CTRL_STORE_SIZE)
			return(EINVAL);
		aed->ctrl_offset = *(long *)data;
		break;
	case AEDGET_SRAM_LOC:
		/* report address of AED shared RAM */
		*(long *)data = (long)aed->sram_loc;
		break;
	case AEDRESET:
		/* reset AED processor */
		AED_DELAY;
		aedrd(&dummy,1,AED_RESET);
		AED_DELAY;
		break;
	case AEDSTART:
		/* start AED processor */
		AED_DELAY;
		aedrd(&dummy,1,AED_START);
		AED_DELAY;
		break;
	case AEDSTOP:
		/* stop AED processor */
		AED_DELAY;
		aedrd(&dummy,1,AED_STOP);
		AED_DELAY;
		break;
	case AEDSTATE:
		/* report AED state variable */
		*(unsigned long *)data = aed->state;
		break;
	case AEDSEM_WHILE:
		/*  AED semaphore and read until it changes */
		AED_DELAY;
		counter = 0;
		do {
			AED_DELAY;
			aedrd(&poll,1,AED_SEMAPHORE);	/* read semaphore */
			AED_DELAY;
			if (breakout) break;
		} while ((poll == *(short *)data) && (counter++ < timeout));
		breakout = 0;
		AED_DELAY;
		*(short *)data = poll;
		if (counter >= timeout) return(EINVAL);  /* time-out */
		break;
	case AEDSEM_READ:
		/* read AED semaphore */
		AED_DELAY;
		aedrd((short *)data,1,AED_SEMAPHORE);	/* read semaphore */
		break;
	case AEDSEM_SET:
		/* set AED semaphore */
		AED_DELAY;
		aedwr((short *)data,1,AED_SEMAPHORE);	/* set semaphore */
		break;
	case AEDSEM_TIMEOUT:
		timeout = *(int *)data;
		break;
	case AEDSEM_UNTIL:
		/*  AED semaphore and read until it matches data */
		AED_DELAY;
		counter = 0;
		do {
			AED_DELAY;
			aedrd(&poll,1,AED_SEMAPHORE);	/* read semaphore */
			AED_DELAY;
			if (breakout) break;
		} while ((poll != *(short *)data) && (counter++ < timeout));
		breakout = 0;
		AED_DELAY;
		*(short *)data = poll;
		if (counter >= timeout) return(EINVAL);  /* time-out */
		break;
	case AEDSEM_SET_WAIT:
		/* set AED semaphore and read until it has changed */
		if (*(short *)data == 0)
			return(EINVAL);
		AED_DELAY;
		aedwr((short *)data,1,AED_SEMAPHORE);	/* set semaphore */
		counter = 0;
		do {
			AED_DELAY;
			aedrd(&poll,1,AED_SEMAPHORE);	/* read semaphore */
			AED_DELAY;
			if (breakout)
				break;
		} while ((poll == *(short *)data) && (counter++ < timeout));
		breakout = 0;
		AED_DELAY;
		*(short *)data = poll;
		if (counter >= timeout) return(EINVAL);  /* time-out */
		break;
	case AED_TOG_DEBUG:
		/* toggle debugging */
		aeddebug = !aeddebug;
		break;
	case AEDDELAY:
		AED_DELAY;
		break;
	case AED_LEDS:
		AED_DELAY;
		display(*(int *)data);
		AED_DELAY;
		break;
	default:
		/* Not this emulator's command */
		return(-1);
	}
	AED_EXIT();
	return(0);
}

aedstrategy(aedbp)
register struct buf *aedbp;	/* pointer to user buffer */
{
	register AED *aed = &aed_info;	/* get address of AED info struct */
	register long loc;
	AED_ENTER();

	loc = aed->ctrl_offset;	/* get pointer to AED control store */

	if (aedbp->b_flags & B_READ)
	{
#ifdef AEDDEBUG
if (aeddebug>10)
	printf("AEDSTRATEGY: read (%d) at loc (%x)\n",aedbp->b_bcount, loc);
#endif AEDDEBUG
		aedrd(aedbp->b_un.b_addr,aedbp->b_bcount>>1, loc);
	} else {
#ifdef AEDDEBUG
if (aeddebug>10)
	printf("AEDSTRATEGY: write (%d) at loc (%x)\n",aedbp->b_bcount, loc);
#endif AEDDEBUG
		aedwr(aedbp->b_un.b_addr, aedbp->b_bcount>>1, loc);
	}

	aed->ctrl_offset += aedbp->b_bcount; /* adjust control store pointer */
	iodone(aedbp);
	AED_EXIT();
	return(0);
}

#endif NAED
