File:  [Power 6/32 Unix Tahoe 4.2BSD] / cci / d / ioex / udc.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

/*
 *	Base of share memory for UDC is at : 0xff0000
 *
 *	The following configuration is required on UDC :
 *		SMD 	      : device 0
 *		CMD_fixed     : device 2
 *		CMD_removable : device 3
 *		Floppy0	      : device 4
 *		Floppy1	      : device 5
 */

#define  SBR		0
#define  PGSHIFT	10
#include "pte.h"
#include "udc.h"


/* 	UDC command packet 	*/
struct UDPAC udpac = {
	2, 0, 21, 0, 0, 0, 0, SECTSIZ, 0, 0, 0, 3
};


/* 	UDC status packet 	*/
struct UDSPAC udspac = {
	2, 0, 9, 0, 0, 0, 0, 3
};
long IObase;		/* Virtual addrss of UDC shares memory */
long Uack;		/* Flag polled for UDC acknowlege */
long Udone;		/* Flag polled for status packet */
long Probe = 0;		/* If set do not print error message */
extern long unused, iob0, iob2, iob4;

udc()
{	register long r12;
	long oldvec;

	writes("\n	** UDC test **\n");
	Probe = 0;
	m_udc();		/* Map UDC */

	/* Set handler for UDC interrupt */
	asm("movab udhdlr,r12");
	set_handler(UDCVEC,&oldvec,r12);

	/* Reset UDC controller */
	if ( udc_reset()==0 )  {
		writes("\n** Cannot reset UDC controller \n");
		return;  }
	u_ex();
}


/*	Routine to map UDC
*/
m_udc()
{	long r12, phys_pg, pte, old_pte, which1;

	phys_pg = ((UBASE+IOBASE) >> PGSHIFT) & 0x3fffff;
				/* 1st physical page of UDC in IO space */
	pte = phys_pg | PG_KW | PG_V | PG_NC;
	fix_pte(SBR,unused,&old_pte,pte);

	/* Base addr of common buffer */
	IObase = (unused << PGSHIFT);

	asm("mfpr $SLR,r12");
	r12++;
	asm("mtpr r12,$SLR");
	unused++;		/* Next unused PTE in system map */
}



/*	*********************
   	Reset UDC controller.
	*********************
*/
udc_reset()
{	register long cnt;

	IPC_RESET;
	DELAY(0x1f0000);		/* Wait for 3 seconds */
	cnt = RETRY;
	while (RD_MCSENT != READY)
		{ DELAY(0x40000);
		  if (--cnt == 0) return(0); }
	return(1);
}


/*	*********************************
	Routine to copy from disk to disk
	*********************************
*/
cpy_dd(sdev, ddev, sblk, dblk, noblk)
char sdev, ddev;
long sblk, dblk, noblk;
{	
	long  s_begsec, d_begsec;
	long ndatablks, s_nsblk, d_nsblk, blk;

for(blk=sblk;blk<=(sblk+noblk);blk++)
	{
	/* Read 1 block (1K) of data */
	if (disk_rw(READ,sdev,blk,1,&iob0)==0) return(0);
	    else writec('R');

	/* Write data */
	if (disk_rw(WRITE,ddev,dblk,1,&iob0)==0) return(0);
	    else {  writec('W');
		    dblk++;   }
	}
}



/* 
	******************************************
    	Routine to read/write N block from/to disk
	******************************************
*/
disk_rw(op,dev,blkno,no_blks,buf_adr)
char op, dev;
long no_blks, blkno;
char *buf_adr;
{	long  begsec;
	long nblks, nsblk;

	nblks = (no_blks*BLKSIZ)/UDC_BLKLEN;	/* no of blocks to be read */
	nsblk = BLKSIZ/SECTSIZ;		/* no of sects/logical blk on dev */

	begsec = (long)(blkno * nsblk);   /* begin sector no. */
	if (op==READ) {
	   writec('.');
	   return(disk_op(dev,UDREAD,UDWTRY,nblks,buf_adr,begsec));
	   }
	 else {
	   writec(',');
	   return(disk_op(dev,UDWRITE,UDWCMP,nblks,buf_adr,begsec));
	   }
}


/* 
	**********************************************************
    	Routine to set up, sent command packet to UDC and check
	status packet received from UDC. Return 0 if error occured
	**********************************************************
*/
disk_op(disk_no,cmd,func,noblk,buf_adr,beg_sctno)
char cmd, disk_no, func;
long noblk;
char *buf_adr;
long beg_sctno;
{

	udpac.pkdev = disk_no;
	udpac.pkcmd = cmd;
	udpac.pkfnc = func;
	udpac.pkcnt = noblk;
	udpac.pbsiz = UDC_BLKLEN;	/* 256 for UDC/FDC */

	udpac.pkmem[0] = (short)(((long)buf_adr >> 16) & 0xffff);
	udpac.pkmem[1] = (short)((long)buf_adr & 0xffff);

	udpac.psecno[0] = (short)((beg_sctno >> 16) & 0xffff);
	udpac.psecno[1] = (short)(beg_sctno & 0xffff);
	udpac.etx = (char)0x3;

	return(TP((char *)&udpac,disk_no));
}


/*	******************************************************
	Transfer a 21 bytes packet to the controller.
	the message is written to odd addresses, starting from
	the given address.
	******************************************************
*/
movep21(src, dest,cnt)
char	*src, *dest;
int cnt;
{
	for (; cnt>0; cnt--) {
		*dest++ = *src++;
		dest++;
	}
}



/*	***************************************
 	Read status packet from the controller.
   	Only read from odd addresses.
	***************************************
*/
rdspac(src, dest,cnt)
char	*src, *dest;
int cnt;
{
	for (; cnt>0; cnt--) {
		*dest++ = *src++;
		src++;
	}
}


/* 	******************************************************
	Transmit packet UDC controller and check return status 
	******************************************************
*/
TP(packet,disk_no)
char *packet, disk_no;
{	long cnt, retry;
	char *src, ack, stat, get_ack(), chk_stat();

	cnt = retry = 0;
again:
	Uack = Udone = 0;
	if (udc_ready()) sent_pck(packet);
		else { writes("\nUDC not ready, did a reset..");
			return(0); }
	switch (ack = get_ack()) {
		case PCK_OK  : break;
		case RETRANS : { if (++cnt<10) goto again;
				else { writes("IPC ack error\n"); 
				       return(0); }
			       }
		default   : { writes("\ndid not get ACK\n");
			   return(0); }
		}
wtspk:
	if (stat_wait()==0) {		/* Wait for status packet */
		IPC_RESET;
		return(0); }
	rdspac((char *)IPC_PCK,(char *)&udspac,9);	/* Get packet */

	switch (stat=chk_stat(disk_no))  {
		case 0 : break;
		case 1 : {
	      		writes("\nTP : unsolicited status packet !");
			prt_stat();
	      		goto invlspk; }
		case 2 : {
	      		writes("\nTP : unexpected dev_no in status_pkt !");
			prt_stat();
	      		goto invlspk; }
		case 3 : {
			if (!Probe) { 
				writes("\nTP : command didnot complete !");
				prt_stat(); }
			goto end; }
		}
	ipc_ack(PCK_OK);
	return(1);
invlspk:
	if ((++retry) > 10) goto end;	/* Too many errors */	
	ipc_ack(RETRANS);		/* Retransmit packet */
	goto wtspk;			/* go wait for status packet */	
end:
	ipc_ack(PCK_OK);
	return(0);
}


/*	***************************
	Routine to get ACK from UDC
	***************************
*/
char get_ack()
{	char ack;
	register long cnt;

	cnt = 0xfff00;
	while (Uack==0)  {	/* Wait for Ack */
		if (--cnt <= 0) {
			writes("\ntime out on Uack..\n");
			return(0); }
		}
	ack=RD_IPCACK;
	if ((ack==PCK_OK) || (ack==RETRANS)) return(ack);    /* received ACK */
	return(0);
}

/*	******************************************
	Routine to poll for status packet from UDC
	******************************************
*/
stat_wait()
{	register long cnt;

	cnt = 0xfff00;
	while (!Udone) {	/* Wait for completion interrupt */
		if (--cnt <= 0) {
			writes("\ntime out on Udone..\n");
			return(0); }
		}
	return(1);
}


/*	****************************************
	Routine to check status packet from UDC
	return 0 : status OK; command completed
	       1 : Unsolicited packet
	       2 : Status from unexpected device
	       3 : Command did not completed
	****************************************
*/
char chk_stat(devno)
char devno;
{
	if (udspac.id == (char)0xff) return((char)1);	/* unsolicited packet */
	if (udspac.dev != devno) return((char)2);
	if ((udspac.stype!=0x70) || (udspac.stat!=0)) return((char)3);
	return((char)0);
}

/*	***********************
	Routine to print status 
	***********************
*/
prt_stat()
{
	writes("\nDevice no.  : "); writeh((long)udspac.dev);
	writes("\nStatus type : ");
	writeh((long)udspac.stype); 
	writes("\nStatus code : ");
	writeh((long)udspac.stat);
	writec('\n');
}


/*	**************************************
	Routine to sent a command paket to UDC
	**************************************
*/
sent_pck(packet)
char *packet;
{
	movep21(packet, (char *)MC_PCK,21);
	WR_MCSENT(0x80);	/* User packet placed */
	WR_IPCACK(0);	/* Reset for results of packet format test by IPC */
	IPC_INT;		/* Interrupt IPC */
}

/*	**************************************************
	Routine to check if UDC is ready to receive packet
	if not then reset UDC and return 0
	**************************************************
*/
udc_ready()
{	long cnt;

	cnt = RETRY;
	while (RD_MCSENT != READY)
		{ DELAY(1000);
		  if (--cnt==0) { writes("\nTP : time out\n"); goto end; }
		}
	return(1);
end:
	IPC_RESET;
	return(0);
}

/* 	*****************************************************
	Routine to acknowlege status packet received from UDC 
	*****************************************************
*/
ipc_ack(stat)
char stat;
{
	WR_IPCSENT(0);			/* Packet processed */
	WR_MCACK(stat);			/* Packet status */
	IPC_INT;
}

/*	UDC interrupt handler 
*/
ud_hdlr()
{
	if (RD_IPCACK != 0) {  Uack = 1; 	/* received ACK */
			 }
	if ((RD_IPCSENT&0xff) == 0x80) { 
			Udone = 1;    /* Status packet placed */
			}
}

Udchdlr()
{	long dummy;
	asm(".align 2");
asm("udhdlr:");
	asm("svpctx");
	ud_hdlr();		/* UDC handler */
	asm("ldpctx");
	asm("rei");
}


unix.superglobalmegacorp.com

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