/* implements the Parallel Interface operation under interrupts */
#include "standard.h"
#include "SparcSoftcard.h"
#include "SparcSoftcardOps.h"
extern BOOLEAN VersatecOnLine();
long pILock, newPIByteAddress, newPIByteCount;
unsigned char tempPIBuffer[16];
void PISetMode (mode)
SparcSoftcardOps←VersatecMode mode;
{
while (pILock != 0) {};
pILock = 1;
SetVersatecMode (mode);
pILock = 0;
};
static void SendOneByte (data)
unsigned char data;
{
unsigned char *p;
long tempByteAddress;
tempByteAddress = (long) tempPIBuffer;
tempByteAddress = (tempByteAddress + 7) & (~ 7);
p = ( unsigned char * ) tempByteAddress;
*p = data;
SparcSoftcardOps←SetDMAState(DMAState←inactive);
SparcSoftcardOps←SetDMAMode(DMAMode←versatecOneShot);
SparcSoftcardOps𡤍MAAddressRegisterLoad(tempByteAddress);
SparcSoftcardOps←SetDMAState(DMAState�tive);
};
BOOLEAN PISendOneByte (data)
unsigned char data;
{
while (pILock != 0) {};  /* Wait for pILock to be released */
if (VersatecOnLine() == FALSE) {
return(FALSE);   /* bad termination */
};
pILock = 1;      /* take the pILock (will be released by the interrupt) */
newPIByteCount = 0;  /* tells to the interrupt routine that the transfert is finished */
SendOneByte (data);  /* actually send the byte */
return (VersatecOnLine()); /* don't wait to return*/
};
BOOLEAN PISendBuffer (byteAddress, byteCount)
long byteAddress, byteCount;
{
unsigned char *p;
long bytesToSend, remainCount;
while (pILock != 0) {};  /* Wait for pILock to be released */
if (VersatecOnLine() == FALSE) {
return(FALSE);   /* bad termination */
};
if (byteCount == 0 ) {
return(TRUE);   /* nothing to do */
};
if ( (byteAddress % 16) != 0 || (byteCount < 96)) {
/* not aligned on an 16 bytes word bondary or buffer too small */
/* send one byte at a time */
pILock = 1;
newPIByteAddress = byteAddress + 1; /* tells the int routine to continue */
newPIByteCount = byteCount - 1;
p = (unsigned char *) byteAddress;
SendOneByte (*p);
return (VersatecOnLine()); /* don't wait to return*/
};
/* buffer bigger than 96 aligned on an 16 bytes word bondary */
if ( byteCount > 1024 * 1024 ) {  /* send 1 mega byte max at a time */
bytesToSend = 1024 * 1024;
remainCount = byteCount - 1024 * 1024;
if (remainCount < 96) bytesToSend -= 96; /* extend the last chunk to more than 96 */
}
else {          /* buffer smaller than 1 mega */
bytesToSend = byteCount - (byteCount % 16);
};
newPIByteAddress = byteAddress + bytesToSend;
newPIByteCount = byteCount - bytesToSend;
pILock = 1;     /* take the pILock (will be released by the interrupt) */
SparcSoftcardOps←SetDMAState(DMAState←inactive);
SparcSoftcardOps←SetDMAMode(DMAMode←versatecStream);
SparcSoftcardOps𡤍MAAddressRegisterLoad(byteAddress);
SetTimer(bytesToSend);
SparcSoftcardOps←SetDMAState(DMAState�tive);
return (VersatecOnLine()); /* don't wait to return*/
};
void PIInterrupt ()
{
pILock = 0;  /* release lock */
if (newPIByteCount == 0) {  /* transfert done */
return;
};
/* restart transfert */
(void) PISendBuffer (newPIByteAddress, newPIByteCount);
};