File:  [Power 6/32 Unix Tahoe 4.2BSD] / cci / d / pits / vioc.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Sun Jul 28 12:24:19 2019 UTC (6 years, 11 months ago) by root
Branches: bsd, MAIN
CVS tags: v12b, v121, HEAD
Power 6/32 Unix version 1.2b

#include "vioc.h"
#include "conf.h"
#include "const.h"
#include "pte.h"

#define  MAXPORT	16
#define  MAXRLEN	50
#define  MAXSLEN	256
#define  NL		writec('\n')
#define  STAR		writes(" ***");

/*		Pointers to VIOC structures in I/O space 	*/
struct vblok *VP;			/* Pointer to common buffer */
struct cmd_inp cblok;			/* VIOC command block (from HOST) */
struct cmd_res *rblok;			/* PTR to CMD respond blk (from VIOC) */

short *s_entry;
short cmdrsp[MAXRLEN];

long viocb[NVIOC];                      /* vioc buffer's address */
long vioctype[NVIOC];                   /* viocs type */
long msg_on = 1;			/* Global flag to enable messages */
long cmd_id = 0;
long IObase;				/* Virtual Address of VIOC base */
long vioc_ack, vioc_rsp;
long log_first = 1;			/* Logical port no. of 1st terminal */
long log_last = 0;			/* Logical port no. of last terminal */
init_flg = 0;
char port_on[MAXPORT];
extern long savvec3, unused, clk_cnt, proc_no;

vioc() 
{	register long ix;
	long vnum;

	for (ix=vnum=0; ix < NVIOC ; ix++)  {
	    if (viocb[ix]) 
	       if (vioc_diag(ix,vnum)) {
		    v_ex(ix);	/* Test this VIOC */
	       }
	vnum++;
	   }
}
/*
   VIOC test routine
	Return code: 0-----------------Error
		     1-----------------Good
*/
vioc_diag(unit,vdnum)
long unit,vdnum;		/* current vioc no */
{	register long ix, vbase;
	long v_reset(), v_init();

	NL; writes("\nBEGIN TESTING VIOC NO. "); writed(vdnum); NL;
	vbase = viocb[unit];
	cmd_id = 0;
	writes("\nInitialize VIOC at "); writeh(vbase); NL;
	m_vioc(vbase);			/* Set up map for IO space */
	writes("\n1. Internal VIOC Reset Diagnostic"); NL;
	if (v_reset(unit,vbase)) {	/* Reset VIOC */
	 	if (vioctype[ix]==VIOC_B) {
		      writes("\n    VIOC-B currently not supported\n");
		      return(0);
		      }
		else  writes("\n    Reset Passed");
		}
	else	{ 
		writes("\n     Reset Failed"); NL;
		return(0);
		}	
	NL; writes("\n2. Initialize VIOC"); 
	init_flg = 1;
	if (v_init()) {		/* Initialize VIOC */
		writes(" - initialization passed"); NL;
		DELAY(0x400000);
		init_flg = 0;
		}
	else	{ 
		writes(" - initialization failed"); NL;
		return(0);
		}
	writes("\n3. Initialize ports' parameters");NL;
	if (log_last < log_first) writes("\n\n    No ports are available\n"); 
	else 	{
		set_port();		/* Check how many ports on line */
		}
	return(1);	/* good return */
}
/*
  Check vioc controllers' buffer address
*/
chk_vadr()
{	register long curadr; 		/* current examine vioc address */
        short len, viocno, nviocs,ix; 	/* address length		*/
	ix = len = 1;
	writes("\n\nProbing for VIOC controller(s)...");
	curadr = 0xfe0000 + IOBASE;
	 for (nviocs=viocno= 0; viocno < NVIOC; viocno++)
	   {
	   if (!badaddr(curadr,len))
	      {
	       viocb[viocno] = curadr-IOBASE;
	       writes("\nVIOC controller no. "); writed(nviocs); 
	       writes(" at address ");
               writeh((long)curadr-IOBASE);
	       nviocs++;
	      }
	   else   /* bad address return */
	      {		
	       viocb[viocno] = 0;	/* bad address indicator */
	       /* writed(viocno); writes("               ");
               writes("At bad address"); NL;
		*/
	      }
	   if (ix >= 4){
		curadr -= 0x1c000;
		ix = 1;
		}
	   else {
	   	curadr += 0x4000; 	/* get to next buffer's address */
	   	ix++;
		}
           }
	 NL; writed(nviocs); writes(" VIOC controller(s) found"); NL;
         return(nviocs);
}
/*
	Routine to Reset VIOC	
	Poll for 10 sec. then check 
	    if (VIOC busy flag is clear) and (VIOC is ready)
	Return code: 0---------------Fault
		     1---------------Good
*/
v_reset(unit,vbase)
long unit,vbase;
{
	VP->v_fault = (char)0;		/* Clear fault flag */
	VP->v_vioc = V_BSY;		/* Set VIOC busy flag */
	VP->v_hdwre = V_RESET;		/* Reset VIOC	*/
	DELAY(0x700000);		/* Wait for reset to complete */
	if (VP->v_fault != V_ALLOK) { 
		writes("\n\tVIOC error after Reset !");
		writes("\n\tVIOC I.D : ");
		writeh(((long)VP->v_ident)&0xff);
		writes(", Fault code : ");
		writeh(((long)VP->v_fault)&0xff);
		return(0);
		}
	vioctype[unit] = 0x0;		/* Initialize vioc type */
	switch (VP->v_ident)   {	/* Determine VIOC type */
	    case 0x1B:	/* VIOC-X */
	 	{
		vioctype[unit] = VIOC_X;
	        writes("\n    VIOC-X  controller is at "); writeh(vbase); 
		break;
		}
	    case 0x1C:	/* VIOC-B */
		{
		vioctype[unit] = VIOC_B;
	        writes("\n    VIOC-B  controller is at "); writeh(vbase); 
		break;
		}
	    default:
		{
	        writes("\n    Unrecognized VIOC ID"); writeh(VP->v_ident);
		}
	    }				/* end switch */
	writes(", virtual address : "); writeh((long)VP);
	writes("\n    Max transmit block size      "); writeh(VP->xmtsiz);
	writes("\n    Max receive silo char number "); writeh(VP->rcvsilo);
	VP->v_fault = (char)0x0;	/* Clear fault flag */
	VP->v_ustat = 0x0;		/* Clear unsol status */
	VP->v_uqual = 0x0;		/* Clear unsol qual and bsy flag */
	return(1);
}
/*
	For DEBUG. size in bytes.
*/
dump(addr,size)
register char *addr;
long size;
{	register long ix = 0;
	for (;size;ix++) {
		if (!(ix%4)) {
			NL; writeh(addr); writes(":  ");
			}
		writeh((*addr++)&0xff); writes(" ");
		writeh((*addr++)&0xff); writes(" ");
		writeh((*addr++)&0xff); writes(" ");
		writeh((*addr++)&0xff); writes("  ");
		size -= 4;
	}
}

/*
	dump characters version 
*/

dumpc(addr,size)
register char *addr;
long size;
{
	register long ix;

	for (;size;size-=25) {
		
	    for (ix=25;ix;--ix) {
		writec((*addr++)&0xff); writes(" ");
		}
	}
}
/*	
	VIOC initialization routines : Send LIDENT cmd
	(1) Define interrupt vectors
	(2) Set 1st, Last logical port no.
*/
v_init()
{	short *flycmd(), *rsp_blk, stat_wd;
	
	cblok.opcode = LIDENT;		/* Set opcode */
	cblok.byte[0] = ACK_VIOC;	/* Set ack interrupt vector */
	cblok.byte[1] = CMD_RESP;	/* Set cmd interrupt vector */
	cblok.byte[2] = 0x0;		/* Not used */
	cblok.byte[3] = UNS_VEC;	/* Set unsol interrupt vector */
	cblok.byte[5] = log_first = 1;	/* 1st port is logical no. 1 */
	log_last = 0;			/* Clear last port variable */
	if (! (rsp_blk=flycmd()) ) return(0); 	/* Send command to VIOC */
	log_last = (long)(rsp_blk[6] & 0xff); 	/* Last logical port no */
	return(chk_stat(rsp_blk,"\nLIDENT"));	/* Check status and return */
}
/*
	Set ports to manual mode with (DTR) and (RTS) disabled
*/
man_init(pno)
long pno;
{
	short *rsp_blk;
	cblok.opcode = MDMCTL;			/* Set opcode */
	cblok.byte[0] = 0x80;			/* DTR/RTS disabled */
	cblok.byte[1] = (char)pno;		/* Port no. */
	if (! (rsp_blk=flycmd()) ) return(0); 	/* Send to VIOC */
	return(chk_stat(rsp_blk,"\nMDMCTL"));	/* Check status and rtn */
}
/*
	check out how many ports are on line 
*/
set_port()
{	long ix;
	short  *v_reqpar();
	char *rsp;

	for(ix=1; ix<=log_last; ix++) { 	/* Initialize ports */
		msg_on = 0;			/* Turn off msgs */
		port_on[ix-1] = (char)1;	/* This port is on */
		writes("\n    Port number "); writeh(ix-1); 
		man_init(ix);			/* Set manual mode */
		if ( !v_initp(ix,NDBT,NSBT,BAUD,PARY))  {
			port_on[ix-1] = (char)0;	/* This port is off */
			writes(" is not on line");	
			}
		   else {
			if (rsp=(char *)v_reqpar(ix)) {	/* Get port parameter */
			   if ((rsp[10] == (char)NDBT) 
				&& (rsp[11] == (char)NSBT)
				&& (rsp[12] == (char)BAUD)
				&& (rsp[13] == (char)PARY)) {
				writes(" has successfully initialized");
				init_buf(ix);   /* Init. input buffer */
				}
			   else {
			         writes(" cannot be initialized");
			         port_on[ix-1] = (char)2; /* Turn it off */
				}
			}
		}
		msg_on = 1;
	}
	return(0);	/* don't care return code */
}
/*
	Routine to send LPRARAX command to VIOC
	Also used to probe if a port is on line.
	return 1 if port is on line else return 0
*/
v_initp(pno, ndbits, nsbits, baud, parity)
long pno, ndbits, nsbits, baud, parity;
{
	short *flycmd(), stat_wd, *rsp_blk;

	cblok.opcode = LPARAX;		/* Set opcode */
	cblok.byte[0] = 0x0;		/* not used */
	cblok.byte[1] = (char)pno;	/* Port no. */
	cblok.byte[2] = 0x0;		/* Enable port's transmitter */
	cblok.byte[3] = 0x0;
	cblok.byte[4] = (char)ndbits;	/* no. data bit */
	cblok.byte[5] = (char)nsbits;	/* no. stop bit */
	cblok.byte[6] = (char)baud;	/* Baud rate */
	cblok.byte[7] = (char)parity;	/* Parity */

	if (! (rsp_blk=flycmd()) ) return(0);	/* Send command to VIOC */
	return(chk_stat(rsp_blk,"\nLPARAX"));	/* Check status and rtn */
}
/*
	Request port parameters 
	return code:
	   	0 ------------- command error
		1 ------------- good
*/
short *
v_reqpar(pno)
long pno;
{	short *flycmd(), *rsp_blk, stat_wd;

	cblok.opcode = RPARALX;		/* Set opcode  */
	cblok.byte[0] = 0;		/* unused      */
	cblok.byte[1] = (char)pno;		/* port number */
					/* Send command to VIOC */
	if (! (rsp_blk=flycmd()) ) return(0);
	if (chk_stat(rsp_blk,"\nRPARALX") == 0) return(0); /* error */
	return(rsp_blk);	/* good return */
}

/*	Routine to send AUTO loop back/local echo
	command to VIOC;
	return 1 if port is on line else return 0
*/
v_autol(pno,on,op)
long pno,on, op;
{
	short *flycmd(), stat_wd, *rsp_blk;

	cblok.opcode = AUTOLP;		/* Set opcode */
	cblok.byte[0] = on | op;	/* enable/disable auto loopback/echo */
	cblok.byte[1] = pno;		/* port no */

	/* Send command to VIOC */
	if (! (rsp_blk=flycmd()) ) return(0);
	return(chk_stat(rsp_blk,"\nAUTOLP"));
}

/*	
	Routine to send XMITIMM CMD to VIOC.
	Used to put a char to port #pno
	Return a 1 if command executed else return 0
*/
pchar(pno,c)
long pno;
char c;
{	register long slen, ix;
	char str[3], *cptr;
	register short *rsp_blk;

	str[0] = c;
	slen = 0;
	if (c=='\n') {
		slen = 2;
		str[1] = '\r';
		str[2] = NULL;	}
	/* Fill command buffer */
	cblok.opcode = (short)XMITIMM;	/* XMIT immediate */
	cblok.byte[0] = (char)pno;	/* Port no. */
	cblok.byte[1] = (char)slen;	/* Byte count */

	cptr = (char *)&cblok.byte[2];
	for (ix=0;ix <= slen; ix++) *cptr++ = str[ix];
	if (! (rsp_blk=flycmd()) ) return(0);
	return(chk_stat(rsp_blk,"\nXMITIMM"));
}
/*	
	Routine to send XMITDTA CMD to VIOC.
	Used to send a string to port #pno
	Return a 1 if command executed else return 0
*/
pstr(pno,c)
long pno;
char *c;
{	register long *lptr, slen, phys_adr;
	char *cptr;
	short *rsp_blk, stat_wd , *flycmd();

	/* Count length of string */
	slen = 0;
	for (cptr=c; *cptr++ != NULL; slen++);

	/* Fill command buffer */
	cblok.opcode = XMITDTA;		/* XMIT opcode */
	cblok.byte[0] = pno;	/* Port no. */
	cblok.byte[1] = (char)slen;	/* Byte count */

	lptr = (long *)&cblok.byte[2];
	phys_adr = va2pa((long)c);	/* Convert VA of string to phys. addr */
	*lptr = (long)phys_adr;		/* Set address of buffer */	

	if (! (rsp_blk=flycmd()) ) return(0);

	return(chk_stat(rsp_blk,"\nXMITDTA"));
}
/*
	Routine to check returned status of CMD
	return 0 if error else return 1
*/
chk_stat(rsp_blk,cmd)
short *rsp_blk;
char *cmd;
{	short stat_wd;

	stat_wd = *rsp_blk;			/* Get status word */
	if (stat_wd & (short)C_ERR) {		/* CMD Error */ 
		if (msg_on) {			/* Print error msg */	
			writes("\t"); writes(cmd); writes(" error ");
			stat_wd = rsp_blk[1];
			writeh((long)stat_wd); NL;
			}
		return(0);			/* Return bad status */
		}
	return(1);				/* Return good status */
}
/*
	Send a command to VIOC, wait for respond and
	(1) return pointer to respond buffer
	(2) Check for matched CMD ID.
	** Routine that called this has to check for
	cmd completion status itself. If cmd can not
	be send, return a NULL pointer.
*/
short *
flycmd()
{	register long *r12;
	short *sent_cmd(), *rsp_blk, stat_wd;

	rsp_blk = sent_cmd(&cblok);	/* issue command to VIOC */
	if (!rsp_blk) {
		/* 
		   Should try to abort this cmd, reset VIOC
		   to known state and continue
		*/
		return(0); 	/* ERR : CMD cannot be sent. */
	}
	stat_wd = (*rsp_blk) & 0xffff;
	rsp2v(rsp_blk);			/* Send ACK interrupt to VIOC */
	return(rsp_blk);
}
/*	
	Routine to send a command to VIOC, Command buffer should be 
	filled by HOST before calling this routine :
	    Issue CMD INP INT to VIOC, Wait for VIOC to send ACK INT
	    If VIOC ACK with INT ERR bit set, print INT ERR code and return 0
		else wait for CMD RESP INT from VIOC
	Return pointer to Command Respond block.
	return code:	0-----------------VIOC/CMD busy flag set.
			else--------------response buffer address.
*/
short *
sent_cmd(cmdblk)
struct cmd_inp *cmdblk;
{
	register long cnt, *r11;
	register short *rsp_stat;
	short *sptr, *gt_rspadr(), ix, sec;

	if (v_busy()) return(0); 	/* Test VIOC BUSY flag */
	if (!v_rdy4cmd()) return(0); 	/* Test CMD BUSY flag */
	set_cadr((long)cmdblk);		/* Load CMD address in common buffer */
	vioc_ack = vioc_rsp = 1;
	VP->v_vcbsy = V_BSY;		/* Set CMD BUSY FLAG	*/
	v_int((char)V_CMDI);		/* Send CMD INPUT INTERRUPT */
	sec = 0x0000;
	while ((vioc_ack != 0) && (sec <= 0x100)) {
		DELAY(0x5000);
		if (sec == 0x100) {
		   writes("\n\t*** Time out on CMD ACK interrupt ***\n");
		   return(0);   /* no response */
		}
		sec++;
	}
	cmd_id = (long)(VP->v_vcid & 0xff);
	if (cmd_id & V_ERR)
		{
		writes("\n\tCmd ID/ERR : ");
		writeh((long)(cmd_id & 0x3C)); NL;
		return(0);
		}
	sec = 0x0000;
	while ((vioc_rsp != 0) && (sec <= 0x100)) {
		DELAY(0x5000);
		if (sec == 0x100) {
		   writes("\n\t*** Time out on CMD RESP interrupt ***\n");
		   return(0); /* no response ! */
		}
		sec++;
	}							
	rsp_stat =  gt_rspadr();	/* Get addr of Respond buffer */
	/* For debugging only : Read command respond buffer from VIOC */
	sptr = rsp_stat;
	for (ix=0; ix <MAXRLEN; ix++) cmdrsp[ix] = *sptr++;

	return(rsp_stat);
}
/*
	This routine send a command respond interrupt to VIOC
*/
rsp2v(rsp_blk)
short *rsp_blk;
{	register long cnt;

	if (v_busy()) panic("\n\t*** Rsp2v time out on VBSY flag ***\n");
	*rsp_blk &= ~V_BSY; 		/* Clear RESP. BUSY Flag */
	v_int((char)V_CMDRI);		/* Send a cmd respond int. to VIOC */
}
/* 	Routine return the address of CMD RESP. Buffer in 
	shared area
*/
short *
gt_rspadr()
{
	return((short *)( ((char *)VP) + (VP->v_rsp & 0x7fff)));
}
/*
	Routine to send an interrupt to VIOC	
	Input : Bit 0,1 of 'qual' indicate type of interrupt
*/
v_int(qual)
char qual;
{
	char vint;

	vint = (char)((V_BSY | qual) & 0xff);
	VP->v_vioc = vint;	/* Set busy flag, int. qualifier */
	VP->v_hdwre = V_INTR;	/* Interrupt VIOC */
}
/*
	Routine to test if VIOC is ready to accept new command
	Return 1 if ready Else return 0
*/
v_rdy4cmd()
{	register long cnt;

	cnt = 0x100;
	while (VP->v_vcbsy & V_BSY) {
		  DELAY(0x5000);
		  if (--cnt == 0) {
		  	writes("\n\t*** VIOC CMD BUSY flag set ***\n");
			return(0); }
		}
	return(1);
}
/*
	Routine to test if VIOC busy, Return 1
	if not busy Else return 0
*/
v_busy()
{	register long cnt, *r12;

	cnt = 0x100;
	while (VP->v_vioc & V_BSY) {
		  DELAY(0x5000);
		  if (--cnt == 0) {
			writes("\n\t*** VIOC BUSY flag set ***\n");
			return(1);
			}
		}
	return(0);
}
/* 
	Handler of VIOC CMD RESP. INT 
*/
rsp_handlr()
{
	asm(".align 2");
	asm(".globl rsp_hdlr");
asm("rsp_hdlr:");
	vioc_rsp = 0;			/* Clear Vioc_rsp flag */
	asm("rei");
}
/* 
	Handler of VIOC ACK INT 
*/
ack_handlr()
{
	asm(".align 2");
	asm(".globl ack_hdlr");
asm("ack_hdlr:");
	vioc_ack = 0;			/* Clear Vioc ack flag */
	asm("rei");
}
/*	
	Global variables used in Unsolicited int. handler 
*/
long silo_no, no_char, cin, count;
char ascii;

/* 	
	Handler of VIOC UNSOLICITED interrupt : service on ISP
	(1) Dump silo contents
*/
unsol_handlr()
{
	asm(".align 2");
	asm(".globl unsol_hdlr");
asm("unsol_hdlr:");
	asm("svpctx");		/* Save context, also switch to ISP */
	dmp_silo();
	asm("ldpctx");		/* Restore context, switch to KSP */
	asm("rei");
}
dmp_silo()
{	register long rsp_qual, pno, error, rec_err;
	register long ptr2silo;
	short ix;

	rec_err = 0;
	if(init_flg) goto nomore; 
/*	ptr2silo = (long)*(short *)(&VP->v_usdata[0]);
	ptr2silo &= 0x3fff;					*/
	rsp_qual = VP->v_uqual & 0x7;
	switch (rsp_qual)	{
		case 1 : {	
			writes("\n\t*** Received data error. ***");
			goto nomore; }
		case 2 : {	
			writes("\n\t*** VIOC process error. ***");
			goto nomore; }
		case 3 : {	
			error = VP->v_ustat & 0x3f;
			writes("\n\t*** Data set change, STATUS ");
			writeh(error); STAR;
			goto nomore; }
		case 4 : {	
			writes("\n\t*** Secondary receive change ***");
			goto nomore; }
		case 7 : 	
		case 6 : 	
		case 5 : {	
			writes("\n\t*** Undefined UNSOL INT QUAL ***");
			writeh(rsp_qual);
			goto nomore; }
		}
	/* Data available */
/* 		
		s_entry = (short *) ((char *)VP) + ((char *)ptr2silo & 0xffff);
*/
		ptr2silo = (long)*(short *)(&VP->v_usdata[0]);
		ptr2silo &= 0x3fff;
		ptr2silo += (long)VP;    /* VAX's Tahoe compiler sucks rock. */
		s_entry = (short *)ptr2silo;
		cin = (long)((*s_entry) & 0xffff);  	/* Get char. count */
		if (cin==0) goto nomore;
		/* Print contents of 1 SILO */
		for(no_char=1; no_char<=cin; no_char++)
			{
			ascii = (char)((s_entry[no_char] >> 8) & 0xff);
			if ( !(s_entry[no_char] & 0x00c0) )  {
				pno = s_entry[no_char] & 0x3f;

				/* Check for port no out of bound */
				if (!((pno>log_last) || (pno<log_first))) {
				   	if (!fillc(pno,ascii)) 
					    goto nomore; /* exit */
				     }
				else {
					writes("\n\t*** Port out of bound : ");
					writed(pno); STAR;
					}
			}
			   else {
				/* Data receive error : parity,frame,overrun */
				writes("\n\t*** data receive error ");
				error = (long)(s_entry[no_char] & 0xc0) >> 6;
				writeh(error & 0x3); STAR; NL;
				}
			}
		*s_entry = 0;  		/* Clear char. count */
nomore:
	if (v_busy())
	   panic("\n\t*** UNSOL hdlr : Time out on VIOC busy flag ***\n");
	
	VP->v_uqual = 0;		/* Reset UNSOL BUSY FLAG */
	v_int((char)V_URESP);		/* Send ACK UNSOL interrupt to VIOC */
	return(0);
}
fillc(pno,c)
long pno;
char c;
{	struct vbuf *vb;

	vb = &vi_buf[pno-1];
	if (vb->cnt >= BUFLEN) {
		writes("\n\t*** Input overflow, port no. ");
		writed(pno-1); STAR; NL;
/*		dumpc(&(vb->buf[0]),100); /* dump input buffer */
		return(0); }
	vb->buf[vb->nxt_fill++] = c;
	vb->cnt++;
	if (vb->nxt_fill > BUFLEN) vb->nxt_fill = 0; 
	return(1);
}
char get1c(pno)
long pno;
{	struct vbuf *vb;
	char c;

	vb = &vi_buf[pno-1];
	if (vb->cnt == 0) return((char)0xff);
	c = vb->buf[vb->nxt_c++];
	vb->cnt--;
	if (vb->nxt_c > BUFLEN) vb->nxt_c = 0; 
	return(c);
}
/*
	Routine to map VIOC :
	VIOC space is map from 1st unused virtual page on
*/
m_vioc(vbase)
long vbase;
{	register long phys_pg, pte, which1;
	long old_pte;
	phys_pg = ((vbase+IOBASE) >> PGSHIFT) & 0x3fffff;
				/* 1st physical page of VIOC in IO space */
	pte = phys_pg | PG_KW | PG_V | PG_NC;
	for (which1=unused; which1<(unused+VIOC_LEN); which1++) {
		fix_pte(SBR,which1,&old_pte,pte);
		pte++;}
	VP = (struct vblok *)(unused << PGSHIFT);
	IObase = (long)VP;		/* Base addr of common buffer */
	asm("mfpr $SLR,_savvec3");	/* Get number of PTE's */
	savvec3 += VIOC_LEN;		/* Add buffer pages */
	asm("mtpr _savvec3,$SLR");	/* Set SBR */
	asm("mtpr _savvec3,$P0LR");	/* Set P0LR also */
	unused = which1;		/* Next unused PTE in system map */
	asm("mtpr $1,$TBIA");		/* Clear translation buffer */
	asm("mtpr $1,$PADC");		/* Purge all data cache */
}
/*	
	Initialize Tahoe SCB vectors to handle VIOC interrupts
*/
init_vec()
{	long old_vec1, old_vec2, old_vec3;

	asm("movab ack_hdlr,_savvec3");
	set_handler(ACK_VIOC,&old_vec1,savvec3);  /* Set handler for VIOC ACK */
	asm("movab rsp_hdlr,_savvec3");
	set_handler(CMD_RESP,&old_vec2,savvec3);  /* Set handler for VIOC RSP */
	asm("movab unsol_hdlr,_savvec3");
	set_handler(UNS_VEC,&old_vec3,savvec3);  /* Set hdler for VIOC UNSOL */
}
/*	
	Routine translate virtual address to physical address
*/
va2pa(va)
long va;
{	register long *base, pte, pte_no, page_no, cmdadr;

	/* Translate virtual to physical address */
	asm("mfpr $SBR,r12");
	pte_no = (va >> PGSHIFT) & 0x3fffff; /* Virtual pgno of cmd addr */
	pte = base[pte_no];			 /* PTE for this page no */
	page_no = pte & 0x3fffff;
	cmdadr = (page_no << PGSHIFT) | (va & 0x3ff);
	return(cmdadr);
}
panic(msg)
char *msg;
{
	writes(msg);
	asm("halt");
}
/*	
	Routine to set cmd address in common buffer. 
	Command address has to be translated to physical
	address. 
	input : blkadr (virtual address)
*/
set_cadr(blkadr)
long blkadr;
{	register long word1, cmdadr;

	cmdadr = va2pa(blkadr);		/* VA to physical address */
	VP->v_vcp1 = (short)(cmdadr & 0xffff);
	word1 = (cmdadr >> 16) & 0xffff;
	VP->v_vcp0 = (short)word1;
}
/*
	routine to initialize input buffer for port X
	input : pno - logical port no. on VIOC
*/
init_buf(pno)
long pno;
{	struct vbuf *vb;
	register long ix;

	vb = &vi_buf[pno-1];
	vb->cnt = vb->nxt_c = vb->nxt_fill = 0;
	for(ix=0; ix<BUFLEN; ix++) vb->buf[ix] = 0;
}
/* 
	Request current port parameters and print them to console
*/
/*
	Send a break command to vioc
	return code:
	   	0 ------------- command error
		1 ------------- good return
*/
v_break(pno,brklgth)
long pno;
short brklgth;
{	short *flycmd(), *rsp_blk, stat_wd;

	cblok.opcode = SNDBRKX;		/* Set opcode  */
	cblok.byte[0] = brklgth;	/* break length*/
	cblok.byte[1] = pno;		/* port number */
					/* Send command to VIOC */
	if (! (rsp_blk=flycmd()) ) return(0);
	if (chk_stat(rsp_blk,"\nSNDBRKX") == 0) return(0); /* error */
	return(1);	/* good return */
}
/*
	Send a command to flush the hung xmit command
	return code:
	   	0 ------------- command error
		1 ------------- good return
*/
v_flush(pno)
long pno;
{	short *flycmd(), *rsp_blk, stat_wd;

	cblok.opcode = FDTATOX;		/* Set opcode  */
	cblok.byte[0] = 0;		/* not used    */
	cblok.byte[1] = pno;		/* port number */
					/* Send command to VIOC */
	if (! (rsp_blk=flycmd()) ) return(0);
	if (chk_stat(rsp_blk,"\nFDTATOX") == 0) return(0); /* error */
	return(1);	/* good return */
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.