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

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

#ifndef MINIROOT
#include "lp.h"
/*
 *	This module contains screen printing utilities. 
 *
 *		lp_put puts a character
 *
 *		lp_screen_blank,
 *		lp_screen_move,
 *		lp_pos_cursor (a macro in screen_conf.h),
 *	and	lp_screen_print are utilities to help apa devices shadow their
 *	ascii characters.
 *
 *	Printing is conditional on lp being configured
 */
#include "../machinecons/consdefs.h"
#include "../machinecons/screen_conf.h"
#include "../machine/io.h"

int lpstatus = -1;

/*
 * "clear" lines in the shadow buffer
 */
lp_screen_blank(buffer,sline,scol,eline,ecol,device)
	char *buffer;
	int	sline,scol,eline,ecol,device;
{
	int width = screen_sw[device].width;

	bzero(&buffer[(width*sline)+scol],(eline-sline)*width+(ecol-scol)+1);
}

	
/*
 * "scroll" lines around in the shadow buffer
 */
lp_screen_move(buffer,top,bottom,dest,device)
	char 	*buffer;
	long	top,bottom,dest;
	int	device;
{
	int width = screen_sw[device].width;
	int length = screen_sw[device].lines-1;
	

	if (((bottom-top)+dest) > length) {
		bottom = length;
	}

	if ((dest > top) && (dest < bottom)) {
		register char *start,*end,*next;
		end = &buffer[top*width];
		next = &buffer[(dest+(bottom-top)+1)*width -1];
		for (start = &buffer[(bottom+1)*width - 1];
					start >= end; start--,next--) 
			*next =*start;
	} else {
		bcopy(&buffer[top*width],&buffer[dest*width],
						((bottom-top)+1)*width);
	}
}

/*
 * shadow buffer printing:
 */
lp_screen_print(buffer,si, flag, device)
register char *buffer;
register SCREEN_INFO *si;
register int flag;
register int device;
{
	register int l, i;
	int length = screen_sw[device].lines;
	int width = screen_sw[device].width;
	char c;

	for (l = 0; l < length*width; l+=width) {
		for (i = 0; i < width; ++i) {
			if ((c = buffer[l+i]) == 0) {
				c = ' ';
			}
			if (lp_put(si,c)) {
				goto done; /* quit if error */
			}
		}
		lp_put(si, '\r');
		lp_put(si, '\n');
	}
	lp_put(si, '\f');		       /* skip to top of form */
done:
	put_status(si, 33, "       ");
	lpstatus = -1;
}

#if NLP > 0
#define OUT_DATA     0x3bc	       /* Data register    */
#define OUT_CMD      0x3be	       /* Command register */
#define IN_STAT      0x3bd	       /* status  register */
#define STROB_HIGH   0x0d	       /* strobe high      */
#define STROB_LOW    0x0c	       /* strobe low       */
#define RESET_LOW    0x8	       /* reset line LOW   */
#define RESET_HIGH   0x0c	       /* no interrupt, no auto LF */

#define LP_BUSY		0x80
#define LP_ACK		0x40
#define LP_NOPAPER	0x20
#define LP_SELECT	0x10
#define LP_ERROR	0x08
#define LP_TIMEOUT 	0x01

#define LP_ERROR_BITS	LP_NOPAPER+LP_ERROR
#define LP_INVERT	LP_ACK+LP_ERROR+LP_BUSY

#define LP_DELAY  500000

LOCAL int lp_hard_delay = LP_DELAY;

LOCAL lp_status(si, n)
register SCREEN_INFO *si;
register int n;
{
	register int i = ((in(IN_STAT) ^LP_INVERT) & LP_ERROR_BITS) | n;
	static char msg[10] = "ERROR";

	if (i != lpstatus) {
		put_status(si, 33, i ? (n ? "TIMEOUT" : msg) : "       ");
	}
	return (lpstatus = i);
}

lp_put(si, c)
	register SCREEN_INFO *si;
	register int c;
{
	register int i;
	static char first_time = 0;

	if (first_time == 0) {
		first_time++;
		lp_reset(si);
	}
	/* reset */
	for (i = 0; i < lp_hard_delay; i++) { /* time out loop */
		if ((in(IN_STAT) & LP_BUSY) != 0) {
			out(OUT_DATA, c); /* output character */
			i = i;
			i = i;	       /* at least .5 us */
			out(OUT_CMD, STROB_HIGH); /* hardware handshake */
			i = i;
			i = i;	       /* at least .5 us */
			out(OUT_CMD, STROB_LOW);
			i = i;
			i = i;	       /* at least .5 us */
			return (lp_status(si, 0));
		}
	}
	return (lp_status(si, LP_TIMEOUT));	      /* timed out */

}

LOCAL lp_reset(si)
	register SCREEN_INFO *si;
{
	out(OUT_CMD, RESET_LOW);
	delay(2);
	out(OUT_CMD, RESET_HIGH);
	delay(200);
	lpstatus = -1;
	lp_put(si, 0);
	return (lp_status(si, 0));
}
#else
lp_put(si,c)
	register SCREEN_INFO *si;
	register int c;
{
	put_status(si, 33, " NO LP ");
	return(1);
}
#endif
#endif /* !MINIROOT */
