/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1987,1988
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */

/* $Header:asy.c 12.0$ */
/* $ACIS:asy.c 12.0$ */
/* $Source: /ibm/acis/usr/sys/pc_code/RCS/asy.c,v $ */

#ifndef lint
static char    *rcsid = "$Header:asy.c 12.0$";
#endif


#include <dos.h>
#include <stdio.h>
#include <sys/types.h>
#include "pcparam.h"
#include "rb.h"
#include "abios_st.h"
#include "bios.h"
#include "asy.h"
#include "trace.h"
#include "vars.h"

#define COM1  0x3f8
#define COM2  0x2f8

#define B1200LSB 0x60
#define B1200MSB 0x00

#define IER_DR   0x01
#define IER_LSR   0x04
#define IER_MSR   0x08

#define MCR_DTR   0x01
#define MCR_RTS   0x08
#define MCR_IEN   0x08
#define MCR_LOOP  0x10

#define LCR_8BIT 0x03
#define LCR_EPS  0x10
#define LCR_DLAB 0x80

#define TXB 0
#define RXB TXB
#define DLLSB TXB
#define IER 1
#define DLMSB IER
#define IIR  2
#define LCR  3
#define MCR  4
#define LSR  5
#define MSR  6


char            com1buff[5];
int             com1stat = 0;

char            com2buff[5];
int             com2stat = 0;


struct asy     *asy_ptrs[8] = {0};

struct asy      asy_info[MAX_ASY];
long            asy3_save, asy4_save;

#define SEOI    0x60		/* specific EOI command */

/*
 * irq 3 interrupts for the asy come here after being taken over
 *
 */
asy3(old_stack)
	struct i_stack far *old_stack;
{
	struct asy     *asy = asy_ptrs[3];

#ifdef notdef
	if (asy == 0) {
		rompint3(3, IRQ3, 0xff, 0, (struct cbcb *) 0);
		return;
	}
#endif
	asy_int(asy, COM2, old_stack);
	eoi_master(3 + SEOI);
}


/*
 * irq 4 interrupts for the asy come here after being taken over
 */
asy4(old_stack)
	struct i_stack far *old_stack;
{
	struct asy     *asy = asy_ptrs[4];

#ifdef notdef
	if (asy == 0) {
		rompint3(3, IRQ4, 0xff, 0, (struct cbcb *) 0);
		return;
	}
#endif
	asy_int(asy, COM1, old_stack);
	eoi_master(4 + SEOI);
}


asy_int(asy, com, old_stack)
	struct asy     *asy;
	struct i_stack far *old_stack;
{
	int             iir = IOIN(com + IIR);
	int             rslt = IOIN(com + LSR);
	char            data = IOIN(com + RXB);
#ifdef DEBUG
	struct asy_trace {
		char far *stack;
		u_short	ip;
		u_short cs;
		u_short flags;
		int	com;
	} asy_trace;
	asy_trace.com =  com;
	asy_trace.stack = (char far *)old_stack;
	asy_trace.ip = old_stack->IP;
	asy_trace.cs = old_stack->CS;
	asy_trace.flags = old_stack->flags;
#endif /* DEBUG */

	TRACE(TRACE_ASY,&asy_trace,sizeof(asy_trace));
	if (com == COM1) {
		atmsprocchar(data, com1buff, &com1stat);
	} else if (com == COM2) {
		atmsprocchar(data, com2buff, &com2stat);
	}
/*      rbprintf("port %x: iir=%x lsr=%x data=%x\n",com,iir,rslt,data); */
	IOOUT(com + IER, IER_DR | IER_LSR | IER_MSR);
}


atmsprocchar(data, combuff, comstat)
	char            data;
	char           *combuff;
	int            *comstat;

{
	short           x = 0, y = 0;

	extern u_short  msstatus, msx, msy;

	if (*comstat == 0) {
		if ((data & 0x00f8) == 0x80) {
			combuff[*comstat] = (char) data;
			(*comstat)++;
		} else
			*comstat = 0;
	} else {
		combuff[*comstat] = (char) data;

		if (*comstat >= 4) {
			*comstat = 0;
			x = (short) (combuff[1]) + (short) (combuff[3]);
			y = (short) (combuff[2]) + (short) (combuff[4]);
			/* rbprintf("ss = %x\n", (int)(*combuff));  */
			msstatus = 0x08 | (x < 0 ? 0x10 : 0) | (y < 0 ? 0x20 : 0) |
				((*combuff & 0x01) ? 0 : 0x02) |
				((*combuff & 0x04) ? 0 : 0x01) |
				((*combuff & 0x02) ? 0 : 0x03);
			msx = x;
			msy = y;
			mouseint(0, 0);
		} else
			(*comstat)++;
	}
}



/*
 * initialize the cbcb pointer for the asy code
 */

asy_init()
{
	char far       *farptr;
	farptr = (char far *) asy_info;
	cbcbptr->cbcb_ent[ASYENT].pc_cb = exchl(physaddr((u_long) farptr, 0, 0));

}

/*
 * code for supporting serial mouse (on PC/AT)
 */

atmsinit()
{
	extern void     irq3asy();
	extern void     irq4asy();
	int             irq;
	int             com;
	int             s;

	if ((option_flag & OPTION_MSASY) == 0)
		return;
	s = spl();
	if (option_flag & OPTION_MSCOM2) {
		irq = 3;
		com = COM2;
		TAKE_VECTOR(vector_map[3], asy3_save, irq3asy);
	} else {
		irq = 4;
		com = COM1;
		TAKE_VECTOR(vector_map[4], asy4_save, irq4asy);
	}
	rbprintf("asymouse: irq=%d port=%x\n", irq, com);
#ifdef notdef
	outp(com + IER, IER_MSR);
	outp(com + MCR, MCR_IEN);
	outp(com + MCR, MCR_IEN | MCR_LOOP);
	outp(com + MCR, MCR_IEN);
	outp(com + IER, 0);
#endif
#ifdef notdef
	inp(com + MSR);
	outp(com + MCR, MCR_IEN | MCR_DTR | MCR_RTS);
	outp(com + IER, IER_DR | IER_LSR | IER_MSR);	/* */

	/* set the baud rate */

	outp(com + LCR, LCR_8BIT);
	outp(com + LCR, inp(com + LCR) | LCR_DLAB);
	outp(com + DLLSB, B1200LSB);
	outp(com + DLMSB, B1200MSB);
	outp(com + LCR, inp(com + LCR) & ~LCR_DLAB);
	outp(com + IER, IER_DR | IER_LSR | IER_MSR);
#endif
	splx(s);
}
