/* implements the Parallel Interface operation under interrupts */ #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_DMAAddressRegisterLoad(tempByteAddress); SparcSoftcardOps_SetDMAState(DMAState_active); }; 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_DMAAddressRegisterLoad(byteAddress); SetTimer(bytesToSend); SparcSoftcardOps_SetDMAState(DMAState_active); 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); };