File:  [Power 6/32 Unix Tahoe 4.2BSD] / cci / d / ether / veiu.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 "veiu.h"
#include "conf.h"
#include "const.h"
#include "pte.h"

#define ACEBASE		0xff0000	/* ACE device base address	*/
#define ACEVECTOR	0x90		/* 				*/
#define RXHDLR		0x90		/* Receive vector interrupt	*/
#define TXHDLR 		0x91		/* Transmit vector interrupt	*/
#define VEIU_LEN	1		/* 1K for I/O registers		*/
#define DPM_SIZE	32		/* 32K DMP			*/

#define	LOWBUF		0		/* lowest dmp buffer index	*/
#define	HIGHBUF		15		/* highest dmp buffer index	*/
/*
	Errors
*/

struct errors 	{
	short	tx_retries;	/* number of retries		*/
	short	tx_discarded;	/* discarded packet count	*/
	short	tx_datagrams;	/* transmitted packet count	*/
	short	rx_overrn;	/* overrun error count		*/
	short	rx_oddbit;	/* odd # of bits count		*/
	short	rx_crcerr;	/* crc error			*/
	short	rx_undern;	/* underrun error		*/
	short	rx_datagrams;	/* received packet count	*/
	short	rx_mismtch;	/* Xmit & Rec msgs mismatched   */
	short	rx_rbcerr	/* rbc (of received messg) error*/
};

/*
	Xmit / Receive queue tracking pointers
*/

struct XRqueue	{
	short	currnd;			/* current random number	*/
	short	boundry;		/* Xmit/Rec boundary		*/
	char 	*dpmptr;		/* Pointer to dpm		*/
	short	Rptr;			/* Rx segment tracking ptr	*/
	short	Xptr;			/* Tx segment tracking ptr 	*/
	short 	Xnxt;			/* Next avail Xmit buffer	*/
	struct errors stats;		/* error tracker		*/
};

struct XRqueue   aceq;
struct acedevice *addr;			/* Pointer to device I/O registers */
long IObase;

#define NACE		2		/* No. of V/EIU devices		*/
#define NOFRAME		16		/* No. of available frames	*/
#define FRAMESZ		2048		/* Frames size: 2K		*/
/*
	Oftenly-used write routines
*/
#define NL		writes("\n");

long ace[NACE];				/* V/EIU address slots		*/
long dpmmap[] = {0xfff80000,0xfff90000};/* dpm address			*/

extern long savvec3, unused, clk_cnt, proc_no;
long oldunu;

char	ace_station[6*NACE] = {				/* addresses	*/
	~0x8,~0x0,~0x3,~0x0,~0x0,~0x1,
	~0x8,~0x0,~0x3,~0x0,~0x0,~0x2,
};

/*  	Test message							*/

char testmsg[] = "ABCDEFGHIJKLMNOPQRSTXYUYWZ0123456789\
abcdefghijklmnopqrstxyuv";

#define TMSGSZ (sizeof(testmsg) -1 )

char ace_hash_code[8*NACE]={				/* hash tables	*/
	~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,/*u 0*/
        ~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,/*u 1*/
}; 

short random_mask_tbl[16] = {				/* backoff table*/
	0x0040, 0x00C0, 0x01C0, 0x03C0, 
        0x07C0, 0x0FC0, 0x1FC0, 0x3FC0,
        0x7FC0, 0xFFC0, 0xFFC0, 0xFFC0,
        0xFFC0, 0xFFC0, 0xFFC0, 0xFFC0 
	};

short msgno, testno, reddy, firstrep;	/* global variables	*/

veiu() 
{	short ix;
	short Csr;

	for (ix=0; (ix < NACE) && ace[ix] ; ix++) { 
	       NL; writes("\nBEGIN TESTING V/EIU NO. "); writed(ix); NL;
	       if (!veiu_reset(ix)) {
		   writes("\n3. MODE 2 TEST------------------------------> ");
		   NL; NL;
		   testno = 2;		/* current test number */
		   veiu_ex();		/* Test this ACE    */
		   DELAY(0x200000);
		   Csr = (short)addr->csr;
		   Csr &= ~CSR_GO;	/* turn off mode 2  */
	    	   movew((short)Csr,&addr->csr);/* stop mode 2 */

	           movew((short)CSR_GO,&addr->csr);
	           Csr = (short)addr->csr;
	           if (Csr & CSR_ACTIVE)
	             {
		       Csr |= CSR_ENINT | CSR_LOOP3 | CSR_PROMISCUOUS;		
		       movew(Csr,&addr->csr);
	             }
	           else
		     {
		       writes("*** Controller would not go active.");
		       writes("  Test aborted ***");
		     }
		   NL;
		   writes("\n4. MODE 3 TEST------------------------------> ");
		   NL; NL;
		   testno = 3;		/* current test number */
		   init_erc();
		   veiu_ex();		/* Test this ACE    */

		   DELAY(0x200000);
		   Csr = (short)addr->csr;
		   Csr |= CSR_ENXMITODD;	/* enable oddbit */
	    	   movew((short)Csr,&addr->csr);/* update csr word */
		   NL;
		   writes("\n5. MODE 3, ODD # OF BITS ERROR TEST---------> ");
		   NL; NL;
		   testno = 4;		/* current test number */
		   init_erc();
		   veiu_ex();		/* Test this ACE    */
		   DELAY(0x200000);
		   Csr = (short)addr->csr;
		   Csr &= ~CSR_ENXMITODD;	/* disable oddbit  */
		   Csr |= CSR_NOXMITCRC;	/* suppressed crc  */
	    	   movew((short)Csr,&addr->csr);/* update csr word */
		   NL;
/*
		   writes("\n6. MODE 3, CRC ERROR TEST-------------------> ");
		   NL; NL;
		   testno = 5;
		   init_erc();
		   veiu_ex();
		   DELAY(200000);
		   NL;
		   writes("\n7. MODE 3, OVERRUN ERROR TEST---------------> ");
		   NL; NL;
		   testno = 6;
		   init_erc();
		   firstrep = 25;
		   veiu_ex();
*/
		   writes("\nEND TESTING OF UNIT: "); writed(ix); NL;
		}
	     } /* end for loop */
}

/* 
	Diagnostic routine
*/

veiu_ex()
{
short mxnofmsg, lostmsg, timecount;	/* max. number of messages	*/

	if (testno == 2)
	     mxnofmsg = 22;
	else	/* mode 3 */
	     mxnofmsg = 13;
	lostmsg = 0;
	for (msgno = 2; msgno < mxnofmsg; msgno++)
	    {
	     load_txbf();		/* fill up tx buffer	*/
	     reddy = 1;			/* block next message	*/
	     timecount = 0;
	     while (reddy) {		/* wait for rcvr to response 	*/
		DELAY(0x5000);		/* wait for receiver to finish	*/
		timecount++;		/* count waiting time		*/
		if (timecount > 100)	/* is receiver still not responding */
		   {			/* time out			*/
		    lostmsg++;		/* count lost message		*/
		    reddy = 0;		/* unlock next message		*/
		   }
	        }
	    }				/* OK!ready for next message 	*/
	report(lostmsg);		/* generate report 		*/
}

/*
	load transmit buffer
*/

load_txbf()
{
 	register struct XRqueue *is = &aceq;
	register struct tx_segment *txmbf; 
	short  ix, iy, cmd, bfptr, length, repetition;

	txmbf = (struct tx_segment *) (is->dpmptr + (is->Xnxt << 11));
	bfptr = 0;
	is->stats.tx_retries = 0; /* init number of retries */
	switch (testno) {
	   case 2: {
	            repetition = msgno;
	            length = TMSGSZ;
		    break;
		   }
	   case 3:
	   case 4:
	   case 5: {
	     	    length = 5*msgno;
	     	    repetition = 1;
		    break;
		   }
	   case 6: {
	            repetition = firstrep++;
	            length = TMSGSZ;
		   }
	};

/* now, fill up buffer				*/

	for (ix=0; ix < repetition; ix++)
	  for (iy=0; iy < length; iy++) 
	     txmbf->tx_data[bfptr++] = testmsg[iy];  /* fill buffer up */

/* update transmit command word & issue transmit command */

/*
if (testno > 2) {
   writes("Transmit message #"); writed(msgno-1);
   DELAY(1000);	
}
*/
	cmd = (bfptr & TCS_TBC) | TCS_TBFULL;	/* update rbc	  */
 	movew((short)cmd,&(txmbf->tx_csr));

	if (++is->Xnxt >= 16)	/* reach buf upper limit ? */
	   is->Xnxt = is->boundry; /* so, point to buf lower limit */
}

/* 
	Report generator
*/

report(lostmsg)
short lostmsg;		/* no of msgs sent but not received	*/
{
	short ix;
	register struct XRqueue *is = &aceq;

	    NL; writes("Transmit: ");
	    writed(is->stats.tx_datagrams); writes(" messages"); NL;
	    writes("Receive : ");
	    writed(is->stats.rx_datagrams); writes(" message(s)"); NL;
	    writes("Discard: ");
	    writed(is->stats.tx_discarded); writes(" message(s)"); NL;
	    if (lostmsg)  {	/* there're lost msgs, report...	*/
		writes("Warning: Reveiver not responding. ");writed(lostmsg);
		writes(" message(s) are lost.\n\n");
	    }
	    if (testno > 2) {
	        NL; NL; writes("\t Number of Message(s) With"); NL;
	        NL; writes("Overrun   Underrun   CRC   Odd # of bits");
	        NL; NL; writes("   ");
	        writed(is->stats.rx_overrn); writes("        ");
	        writed(is->stats.rx_undern); writes("       ");
	        writed(is->stats.rx_crcerr); writes("         ");
	        writed(is->stats.rx_oddbit); NL; NL;
	    }
	    writes("Done with: ");
	    writed(is->stats.rx_mismtch);  
	    writes("  mismatched message(s)"); NL;
	    if (testno > 2) {
	        writes("           ");
	        writed(is->stats.rx_rbcerr);
	        writes("  received message(s) w/ incorrect byte count"); NL; NL;
	    }
    	    DELAY(0x10000);	/* relax	*/
}


/*
   VEIU test routine
	Return code: 0-----------------Error
		     1-----------------Good
*/

veiu_reset(unit)
short unit;		/* current vioc no */
{	register long ix, vbase;
	int veiu_init();

	NL; writes("\n1. RESET AND INITIALIZATION------------------>");
	vbase = ace[unit];
	NL; writes("\nInitialize V/EIU at: "); writeh(vbase);
	m_veiu(unit,vbase);		/* Set up map for IO space */
	if (veiu_init(unit))	/* Reset and init. VEIU */
		return(1);
	return(0);	/* good return */
}

/*
  Check vioc controllers' buffer address
*/

chk_veiu_adr()
{	register long curadr; 		/* current examine vioc address */
        short len, aceno, naces; 	/* address length		*/

	len = 2;
	naces = 0;
	curadr = ACEBASE + IOBASE;	/* first ACE buffer address	*/
	writes("\nProbing for V/EIUs...");
	for (aceno= 0; aceno < NACE; aceno++)
	   {
	   if (!badaddr(curadr,len))
	      {
	       ace[aceno] = curadr - IOBASE;
	       writes("\nV/EIU no. "); writed(aceno); 
	       writes(" at virtual address ");
               writeh((long)curadr);
	       naces++;
	      }
	   else   /* bad address return */
	      {		
	       ace[aceno] = 0;		/* bad address indicator	*/
	      }
	   curadr += 0x100; 		/* get to next dev io regs' address */
           }
	 NL; writed(naces); writes(" V/EIUs found."); NL;
         return(naces);
}

/*	Routine to Reset VEIU	
		     1---------------Good
		     0---------------Error
*/
veiu_init(unit)
short unit;
{
	short Csr;

	    writes("\nReset V/EIU unit no. "); writed(unit); NL; NL;
	/*
	 * Reset the controller, initialize the recieve buffers,
	 * and turn the controller on again and set board online.
	 */
	    movew((short)CSR_RESET,&addr->csr);
	    DELAY(10000);

	  /* clean up dpm since the controller might jumble dpm after
	     reset							*/

	    if (acesetetaddr(unit)) /* set station addr &  */
		return(1);	     /* emergency return    */
	    Csr = (short)addr->csr;
	    aceclean();
	    movew((short)CSR_GO,&addr->csr);	/* addr->csr = CSR_GO; */
	    Csr = (short)addr->csr;
	    if (Csr & CSR_ACTIVE)
	      {
		movew((short)ACEVECTOR,&addr->ivct);
		Csr |= CSR_ENINT | CSR_LOOP2 | CSR_PROMISCUOUS;
		movew(Csr,&addr->csr);
		return(0);
	      }
	    else
	     {
	       writes("*** Controller would not go active.");
	       writes("  Test aborted ***"); NL;
	       return(1);		/* bad return	*/
	     }

}

acesetetaddr(unit)
short unit;
{
register short *pData0, i;
register char *pData1;
short Csr;

	for (pData0 = (short *)&(addr->rar.station_addr[0]),
	     	pData1 = &ace_station[unit*6], i = 6; --i >= 0;) {
	    movew((short)(*pData1++),(pData0++)); 
	    }

	for (pData0 = (short *)&(addr->rar.mcast_hash_code[0]), 
	     pData1 = &ace_hash_code[unit * 8], i =  8;
	     --i >= 0;){
	    movew((short)(*pData1++),(pData0++)); 
  	    }

	movew((short)0x0,&addr->rar.broadcast_en[0]); 
	movew((short)0x0,&addr->rar.broadcast_en[1]);

	Csr = (short)addr->csr;
	if (Csr & CSR_ACTIVE) /* make sure ctlr is not active before */
	   {			  /* reading RARs			*/
	    Csr |= ~CSR_ACTIVE;
	    movew((short)Csr,&addr->csr);
	   }
        if (reg_test(unit,(short *)&addr->rar.station_addr[0]))
	   {
	    writes("\nRVT Fatal error(s) detected. Test aborted.");
	    return(1);	/* bad return */
	   }
	return(0);	/* good return*/
}

Xd_int()
{
	asm(".align 2");
	asm(".globl Xd_hdlr");
asm("Xd_hdlr:");
	chk_Xd();
	asm("rei");
}

/*
 * Transmit done handler.
 */

chk_Xd()
{
register struct XRqueue *is = &aceq;
register struct tx_segment *txseg;	/* ptr to V/EIU tx seg            */
short eostat;

	txseg = (struct tx_segment *)((is->Xptr << 11) + is->dpmptr);
	if (((eostat = txseg->tx_csr) & TCS_TBFULL) == 0) {
	    	is->stats.tx_retries += (eostat & TCS_RTC);
	    	if (eostat & TCS_RTFAIL) { 
		    is->stats.tx_discarded++;
		    reddy = 0; 		/* unlock next message Xmission */
		    }
	    	else 
		    is->stats.tx_datagrams++;

	    	if (++is->Xptr >= 16)
	      	    is->Xptr = is->boundry; 
	   } 
}

/*
 * Ethernet interface receiver interrupt.
 * If input error just drop packet.
 * Otherwise purge input buffered data path and examine 
 * packet to determine type.  If can't determine length
 * from type, then have to drop packet.  Othewise decapsulate
 * packet based on type and pass to type specific higher-level
 * input routine.
 */

Rxd_int()
{
	asm(".align 2");
	asm(".globl Rxd_hdlr");
asm("Rxd_hdlr:");
	chk_Rxd();
	asm("rei");
}

chk_Rxd()
{
register struct XRqueue *is = &aceq;
register struct rx_segment *rxseg;	/* ptr to V/EIU rx seg            */
short eistat;
int len;
	
	DELAY(0x1000);		/* To make sure crs is updated */
	rxseg = (struct rx_segment *)((is->Rptr << 11) + is->dpmptr);

/*
if (testno > 2) {
   writes("...receive status: "); writeh(rxseg->rx_csr & 0xFFFF); NL;
   DELAY(5000);
}
if (testno >= 3) {
   dumpchar(&(rxseg->rx_data[0]),5*msgno);
   DELAY(100000);
}
*/

	if ((eistat = rxseg->rx_csr) & RCS_RBFULL)
	  {
	    if (++is->Rptr >= is->boundry) 
		    is->Rptr = 0;

	    len = (eistat & RCS_RBC);

	    if ((eistat & (RCS_ROVRN | RCS_RCRC | RCS_RODD)) ||
		 (len > (ET_MAXLEN+CRC_SIZE)))
	      {
		if (eistat & RCS_ROVRN) is->stats.rx_overrn++;
		if (eistat & RCS_RCRC) is->stats.rx_crcerr++;
		if (eistat & RCS_RODD) is->stats.rx_oddbit++;
	        if ((testno > 2) & (len < ET_MINLEN)) is->stats.rx_undern++;
		if (len > (ET_MAXLEN+CRC_SIZE)) is->stats.rx_overrn++;
	    	compare(rxseg,is);  /* compare receive & Xmit mssgs */
	      }
	    else  
	    	compare(rxseg,is);  /* compare receive & Xmit mssgs */
	  }
	is->stats.rx_datagrams++;
	rxseg->rx_csr = 0;	
	reddy = 0;		/* unlock next message Xmission	*/
}

/*
	Initialize Tahoe SCB vectors to handle Rec & Xmit interrupts
*/

init_veiu_vec()
{	long old_vec1, old_vec2, old_vec3;

	asm("movab Rxd_hdlr,_savvec3");
	set_handler(RXHDLR,&old_vec1,savvec3);  /* Set handler for VEIU Rxr */
	asm("movab Xd_hdlr,_savvec3");
	set_handler(TXHDLR,&old_vec2,savvec3); /* Set handler for VEIU Txr */
}

/*
	I/O registers access routines
*/

movew(data,to)
short data;
short *to;
{
	asm("movow 6(fp),*8(fp)");
}

aceclean()
{
register struct XRqueue *is = &aceq;
register short i, data;
register char *pData1;
short ix;

	init_erc();
	is->currnd = (short)49123;
	for (pData1 = (char *)(is->dpmptr + (is->boundry << 11)),
	     i = (SEG_MAX + 1) - is->boundry;
	     (--i >= 0); pData1 += sizeof (struct tx_segment))
	     acebakoff(((struct tx_segment*)pData1),15);

}

/*
	Initialize error counts & clear dpm buffer
*/

init_erc()
{
register struct XRqueue *is = &aceq;
short *bptr, ix, reg;

	bptr = (short *)is->dpmptr;
	for (ix=0; ix < 16383; ix++)
	   {
	     *bptr = 0;	
	      bptr++;
	   }					
	is->stats.tx_datagrams = 0; 
	is->stats.tx_discarded = 0; 
	is->stats.rx_datagrams = 0; 
	is->stats.rx_overrn = 0;
	is->stats.rx_crcerr = 0;
	is->stats.rx_undern = 0; 
	is->stats.rx_oddbit = 0;
	is->stats.rx_mismtch = 0;
	is->stats.rx_rbcerr = 0;
	DELAY(0x2000);	/* try to avoid machine check error	*/
	reg = (short)addr->rseg;
	DELAY(0x2000);
	is->Rptr =  (reg & 0x7800) >> 11;
	DELAY(0x2000);
	reg = (short)addr->tseg;
	DELAY(0x2000);
	is->Xptr = is->Xnxt = (reg & 0x7800) >> 11;
}

/*
	back off
*/

acebakoff(txseg, retries)
struct tx_segment *txseg;	/* ptr to V/EIU tx seg            */
register int retries;		/* # of randoms to generate       */
{
	short *pMask;			/* ptr to mask table.	     	  */
	register short *pBakNum;	/* ptr to # entry in Tx seg table */
	register short random_num;	/* random number value.	     	  */


	pMask   = &random_mask_tbl[0];
	pBakNum = &txseg->tx_backoff[0];

	for (; --retries >= 0;)
	  {
	    random_num   = (aceq.currnd = (aceq.currnd * 18741)-13849);
	    random_num  &= *(pMask++);
	    *(pBakNum++) = random_num ^ (short)(0xFF00 | 0x00FC);
	  }
	return(0);
}

/*
	Compare receive msg against Xmit msg to see if they are matched
*/

compare(rxbuf,is)
struct rx_segment *rxbuf;
struct XRqueue *is;
{
	short bytc, rbc, ix, iy;


	switch(testno) {
	   case 2: {
		    bytc = msgno*TMSGSZ;
		    break;
		   }
	   case 3:
	   case 4: { /* received with crc */
		    rbc = (rxbuf->rx_csr & (short)RCS_RBC) - (short)CRC_SIZE;
		    bytc = msgno*5;
		    if (rbc != bytc) 
			is->stats.rx_rbcerr++;
		    break;
		   }
	   case 5: { /* crc suppressed */
		    rbc = (rxbuf->rx_csr & (short)RCS_RBC);
		    bytc = msgno*5;
		    if (rbc != bytc) 
			is->stats.rx_rbcerr++;
		   }
	   default:
		   break;
	};
	iy = 0;
	for (ix=0; ix < bytc; ix++, iy++)
	   {
	    if (iy >= TMSGSZ)
		 iy = 0;
	    if (rxbuf->rx_data[ix] != testmsg[iy]) {
		 is->stats.rx_mismtch++;
		 break;
	 	 }
	   }
	return(0);   /* matched */
}

/*
	Routine to map VEIU :
	VEIU space is map from 1st unused virtual page on
*/

m_veiu(unit,vbase)
long unit, vbase;			/* device's base address	*/
{
	register long phys_pg, pte, which1;
	register struct XRqueue *is = &aceq;
	long old_pte, at;

	if (!unit) {
	   phys_pg = ((vbase+IOBASE) >> PGSHIFT) & 0x3fffff;
				/* 1st physical page of VEIU IOR space */
	   pte = phys_pg | PG_KW | PG_V | PG_NC;
	   fix_pte(SBR,unused,&old_pte,pte);
	   addr = (struct acedevice *)(unused << PGSHIFT);
	   IObase = (long)addr;
	   unused++; 		/* Next unused PTE in system map */
	   }
	else
	   addr = (struct acedevice *)(IObase + 0x100);
	phys_pg = (dpmmap[unit] >> PGSHIFT) & 0x3fffff;
				/* 1st physical page of DMP      */
	pte = phys_pg | PG_KW | PG_V | PG_NC;
	for (which1=unused; which1<(unused+DPM_SIZE); which1++) {
		fix_pte(SBR,which1,&old_pte,pte);
		pte++;
		}
	is->dpmptr = (char *)((unused << PGSHIFT));
	unused = which1;
	   asm("mfpr $SLR,_savvec3");
	   savvec3 += (DPM_SIZE + VEIU_LEN);
	   asm("mtpr _savvec3,$SLR");
	asm("mtpr $1,$TBIA");
	asm("mtpr $1,$PADC");
}

/*
	Print mismatched message - For debuging aid only
*/
print_msg(ptr,bytcnt)
char *ptr;			/* pointer to received data	*/
short bytcnt;			/* number of char in rev buffer	*/
{
	short ix;

	for (ix=0; ix < bytcnt; ix++)
	    writec(ptr[ix]);
	NL;
}

/*
	Debuging aid
*/

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

	for (;size > 0; size-=30) {
		
	    for (ix=30;ix;--ix) {
		  writec((*addr++)&0xff); writes(" ");
		}
	    NL;
	}
}

/*
	Registers validation test
*/

reg_test(unit,pdata0)
short unit;
short *pdata0;
{
	register struct XRqueue *is = &aceq;
	short ix, reg, regerr, xseg, rseg, errcode = 0;
	char *pdata1;

	writes("2. REGISTER VALIDATION TEST------------------>");
	NL; NL;
	regerr = 0;
	pdata1 = (char *)&ace_station[unit*6];
	for (ix=0; ix < 6; ix++, pdata0++, pdata1++)
	   {
	    reg = *pdata0;
	    if ((char)(reg & 0xff)!= (char)(*pdata1 & 0xff)) {
	        regerr++;
		}
	   }
	for (ix=0; ix < 2; ix++, pdata0++)
	   {
	    reg = *pdata0;
	    if ((char)(reg & 0x00)) {
	        regerr++;
		}
	   }
	pdata1 = (char *)&ace_hash_code[unit*8];
	for (ix=0; ix < 8; ix++, pdata0++, pdata1++)
	    {
	    reg = *pdata0;
	    if ( (char)(reg & 0xff) != (char)(*pdata1 & 0xff)) {
	        regerr++;
		}
	     }
	writes("RAR registers test:  ");
	writed(regerr); writes(" error(s)\n\n");
	writes("Transmit segment register (tseg): "); 
	DELAY(0x2000);		/* wait for write done	*/
	reg = (short)addr->tseg;
	DELAY(0x2000);		/* wait for data avail  */
	xseg = (reg & 0x7800) >> 11;
	writed(xseg); NL;
	writes("Receive segment register  (rseg): "); 
	DELAY(0x2000);
	reg = (short)addr->rseg;
	DELAY(0x2000);
	rseg = (reg & 0x7800) >> 11;
	writed(rseg); NL;
	writes("Segment boundary register (segb): ");
	DELAY(0x2000);
	reg = (short)addr->segb;
	DELAY(0x2000);
	is->boundry = (reg & 0x7800) >> 11;
	writed(is->boundry); NL;
	if (rseg)
	   writes("\nWarning: rseg is not pointing at the 1st recv buffer");
	if (rseg > is->boundry)
	   writes("\nWarning: rseg register > segb register");
	if (xseg != is->boundry)
	   writes("\nWarning: tseg register <> segb register");
	DELAY(0x10000);		/* just to take a break	*/
	return(errcode);	/* good return */
}

unix.superglobalmegacorp.com

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