|
|
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");
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.