/*
Sparc Softcard operations IMPLEMENTATION module
See also SparcSoftcardOpsImpl.Mesa for the Cedar side
*/
#include "standard.h"
#include "SparcSoftcard.h"
#include "SparcSoftcardOps.h"
static void ControlBitWrite(address, polarity, value)
long address;
SparcSoftcard←Polarity polarity;
BOOLEAN value;
{
if ( ( ( polarity == Polarity�tiveLow ) && ( value == TRUE ) )
|| ( ( polarity == Polarity�tiveHigh ) && ( value == FALSE ) ) )
io←poke((long)address, (long)0);
else io←poke((long)address, (long)commandBitMask);
};
static BOOLEAN ControlBitRead(address, polarity)
long address;
SparcSoftcard←Polarity polarity;
{
int value;
BOOLEAN result;
value = io←peek((long)address) & commandBitMask;
if ( ( ( polarity == Polarity�tiveLow ) && ( value == 0 ) )
|| ( ( polarity == Polarity�tiveHigh ) && ( value == 1 ) ) )
result = TRUE;
else result = FALSE;
return (result);
};
/*
Cache Operations
*/
void SparcSoftcardOps←SparcCacheDisable() {
ControlBitWrite((long)sparcCacheEnableRegisterByte, sparcCacheEnablePolarity, FALSE);
};
void SparcSoftcardOps←SparcCacheEnable() {
ControlBitWrite((long)sparcCacheEnableRegisterByte, sparcCacheEnablePolarity, TRUE);
};
/*
Interrupt Operations
*/
void SparcSoftcardOps←SetSparcToIOPInt() {
ControlBitWrite((long)sparcToIOPIntRegisterByte, sparcToIOPIntPolarity, TRUE);
};
void SparcSoftcardOps←ResetSparcToIOPInt() {
ControlBitWrite((long)sparcToIOPIntRegisterByte, sparcToIOPIntPolarity, FALSE);
};
void SparcSoftcardOps←SetSparcToMesaInt() {
ControlBitWrite((long)sparcToMesaIntRegisterByte, sparcToMesaIntPolarity, TRUE);
};
void SparcSoftcardOps←ResetSparcToMesaInt() {
ControlBitWrite((long)sparcToMesaIntRegisterByte, sparcToMesaIntPolarity, FALSE);
};
void SparcSoftcardOps←SetSparcToSparcInt() {
ControlBitWrite((long)sparcToSparcIntRegisterByte, sparcToSparcIntPolarity, TRUE);
};
void SparcSoftcardOps←ResetSparcToSparcInt() {
ControlBitWrite((long)sparcToSparcIntRegisterByte, sparcToSparcIntPolarity, FALSE);
};
void SparcSoftcardOps←SetIOPToSparcInt() {
ControlBitWrite((long)iOPToSparcIntRegisterByte, iOPToSparcIntPolarity, TRUE);
};
void SparcSoftcardOps←ResetIOPToSparcInt() {
ControlBitWrite((long)iOPToSparcIntRegisterByte, iOPToSparcIntPolarity, FALSE);
};
void SparcSoftcardOps←SetMesaToSparcInt() {
ControlBitWrite((long)mesaToSparcIntRegisterByte, mesaToSparcIntPolarity, TRUE);
};
void SparcSoftcardOps←ResetMesaToSparcInt() {
ControlBitWrite((long)mesaToSparcIntRegisterByte, mesaToSparcIntPolarity, FALSE);
};
void SparcSoftcardOps←SetSparcAbortInt() {
ControlBitWrite((long)sparcAbortIntRegisterByte, sparcAbortIntPolarity, TRUE);
};
void SparcSoftcardOps←ResetSparcAbortInt() {
ControlBitWrite((long)sparcAbortIntRegisterByte, sparcAbortIntPolarity, FALSE);
};
void SparcSoftcardOps𡤎nableInt() {
ControlBitWrite((long)enableIntRegisterByte, enableIntPolarity, TRUE);
};
void SparcSoftcardOps𡤍isableInt() {
ControlBitWrite((long)enableIntRegisterByte, enableIntPolarity, FALSE);
};
/*
Peripheral Interrupt Operations
*/
static void SetInterruptSource(interruptNumber, interruptSource)
SparcSoftcardOps←InterruptNumber interruptNumber;
SparcSoftcardOps←InterruptSource interruptSource;
{
long baseByteAddress;
/* Select address where to store */
switch (interruptNumber) {
case InterruptNumber←interruptA:
baseByteAddress = intASourceByte;
break;
case InterruptNumber←interruptB:
baseByteAddress = intBSourceByte;
break;
case InterruptNumber←interruptC:
baseByteAddress = intCSourceByte;
break;
};
/* write the Source Selection registers one at a time */
io←poke(baseByteAddress + intSourceReg0Offset , (((long) interruptSource) >> 3));
io←poke(baseByteAddress + intSourceReg1Offset , (((long) interruptSource) >> 2));
io←poke(baseByteAddress + intSourceReg2Offset , (((long) interruptSource) >> 1));
io←poke(baseByteAddress + intSourceReg3Offset , (((long) interruptSource) >> 0));
};
static void SetInterruptModeAndDest(interruptNumber, interruptMode, interruptProcessor)
SparcSoftcardOps←InterruptNumber interruptNumber;
SparcSoftcardOps←InterruptMode interruptMode;
SparcSoftcardOps←InterruptProcessor interruptProcessor;
{
long baseByteAddress;
/* Select address where to store */
switch (interruptNumber) {
case InterruptNumber←interruptA:
baseByteAddress = intAModeByte;
break;
case InterruptNumber←interruptB:
baseByteAddress = intBModeByte;
break;
case InterruptNumber←interruptC:
baseByteAddress = intCModeByte;
break;
};
/* select the mode (the bits are set and reset by a read at different locations */
switch (interruptMode) {
case InterruptMode�tiveLow:
(void) io←peek(baseByteAddress + intModeSetOffset + intModeReg3Offset);
/* set Polarity bit */
(void) io←peek(baseByteAddress + intModeSetOffset + intModeReg4Offset);
/* set Direct bit */
break;
case InterruptMode�tiveHigh:
(void) io←peek(baseByteAddress + intModeResetOffset + intModeReg3Offset);
/* reset Polarity bit */
(void) io←peek(baseByteAddress + intModeSetOffset + intModeReg4Offset);
/* set Direct bit */
break;
case InterruptMode←risingEdge:
(void) io←peek(baseByteAddress + intModeResetOffset + intModeReg3Offset);
/* reset Polarity bit */
(void) io←peek(baseByteAddress + intModeResetOffset + intModeReg4Offset);
/* reset Direct bit */
(void) io←peek(baseByteAddress + intModeResetOffset + intModeReg0Offset);
/* reset the "edge active" bit */
break;
case InterruptMode�llingEdge:
(void) io←peek(baseByteAddress + intModeSetOffset + intModeReg3Offset);
/* set Polarity bit */
(void) io←peek(baseByteAddress + intModeResetOffset + intModeReg4Offset);
/* reset Direct bit */
(void) io←peek(baseByteAddress + intModeResetOffset + intModeReg0Offset);
/* reset the "edge active" bit */
break;
};
/* select the processor (the bits are set and reset by a read at different locations */
switch (interruptProcessor) {
case InterruptProcessor𡤌p:  /* cp requires bits to be set to 1 1 */
(void) io←peek(baseByteAddress + intModeSetOffset + intModeReg1Offset);
(void) io←peek(baseByteAddress + intModeSetOffset + intModeReg2Offset);
break;
case InterruptProcessor←iOP:  /* IOP requires bits to be set to 1 0 */
(void) io←peek(baseByteAddress + intModeSetOffset + intModeReg1Offset);
(void) io←peek(baseByteAddress + intModeResetOffset + intModeReg2Offset);
break;
case InterruptProcessor←sparc:  /* sparc requires bits to be set to 0 1 */
(void) io←peek(baseByteAddress + intModeResetOffset + intModeReg1Offset);
(void) io←peek(baseByteAddress + intModeSetOffset + intModeReg2Offset);
break;
case InterruptProcessor←none:  /* requires bits to be set to 0 0 */
(void) io←peek(baseByteAddress + intModeResetOffset + intModeReg1Offset);
(void) io←peek(baseByteAddress + intModeResetOffset + intModeReg2Offset);
break;
};
};
void SparcSoftcardOps←SetPeriphIntMode(interruptSource, interruptMode, interruptNumber, interruptProcessor)
SparcSoftcardOps←InterruptSource interruptSource;
SparcSoftcardOps←InterruptMode interruptMode;
SparcSoftcardOps←InterruptNumber interruptNumber;
SparcSoftcardOps←InterruptProcessor interruptProcessor;
{
SparcSoftcardOps𡤍isableInt();
SetInterruptSource(interruptNumber, interruptSource);
SetInterruptModeAndDest(interruptNumber, interruptMode, interruptProcessor);
SparcSoftcardOps𡤎nableInt();
};
BOOLEAN ReadPeriphIntState(interruptNumber)
SparcSoftcardOps←InterruptNumber interruptNumber;
{
long baseByteAddress, direct;
/* Select address */
switch (interruptNumber) {
case InterruptNumber←interruptA:
baseByteAddress = intAModeByte;
break;
case InterruptNumber←interruptB:
baseByteAddress = intBModeByte;
break;
case InterruptNumber←interruptC:
baseByteAddress = intCModeByte;
break;
};
/* read the "direct" bit to know whitch value to return */
direct = io←peek(baseByteAddress + intModeReadOffset + intModeReg4Offset) & 1;
if (direct == 1) { /* return the value of the input bit xored with polarity */
return((BOOLEAN)(io←peek(baseByteAddress+intModeReadOffset+intModeReg5Offset) & 1));
}
else { /* return the value of the "edge active" bit */
return((BOOLEAN)(io←peek(baseByteAddress+intModeReadOffset+intModeReg0Offset) & 1));
};
};
void SparcSoftcardOps←ResetPeriphInt(interruptNumber)
SparcSoftcardOps←InterruptNumber interruptNumber;
{
long baseByteAddress;
/* Select address */
switch (interruptNumber) {
case InterruptNumber←interruptA:
baseByteAddress = intAModeByte;
break;
case InterruptNumber←interruptB:
baseByteAddress = intBModeByte;
break;
case InterruptNumber←interruptC:
baseByteAddress = intCModeByte;
break;
};
/* clear the "edge active" bit */
(void) io←peek(baseByteAddress + intModeResetOffset + intModeReg0Offset);
};
/*
DMA Operations
*/
void SparcSoftcardOps←SetDMAState(dMAState)
SparcSoftcardOps𡤍MAState dMAState;
{
if (dMAState == DMAState�tive)
ControlBitWrite((long)dMAActiveRegisterByte, dMAActivePolarity, TRUE);
else
ControlBitWrite((long)dMAActiveRegisterByte, dMAActivePolarity, FALSE);
};
void SparcSoftcardOps←SetDMAMode(dMAMode)
SparcSoftcardOps𡤍MAMode dMAMode;
{
switch (dMAMode) {
case DMAMode←printer:
ControlBitWrite((long)dMAMode0RegisterByte, dMAMode0Polarity, FALSE);
ControlBitWrite((long)dMAMode1RegisterByte, dMAMode1Polarity, FALSE);
break;
case DMAMode𡤍isplay:
ControlBitWrite((long)dMAMode0RegisterByte, dMAMode0Polarity, FALSE);
ControlBitWrite((long)dMAMode1RegisterByte, dMAMode1Polarity, TRUE);
break;
case DMAMode←versatecOneShot:
ControlBitWrite((long)dMAMode0RegisterByte, dMAMode0Polarity, TRUE);
ControlBitWrite((long)dMAMode1RegisterByte, dMAMode1Polarity, FALSE);
break;
case DMAMode←versatecStream:
ControlBitWrite((long)dMAMode0RegisterByte, dMAMode0Polarity, TRUE);
ControlBitWrite((long)dMAMode1RegisterByte, dMAMode1Polarity, TRUE);
break;
};
};
void SparcSoftcardOps𡤍MAAddressRegisterLoad (byteAddress)
long byteAddress;
{
long address = byteAddress / 8;
io←poke((long)dMAAddressRegisterLowByte, (long)address);
io←poke((long)dMAAddressRegisterHighByte, (long)(address>>16));
};
/*
Versatec Operations
*/
BOOLEAN VersatecPrinterEnd()
{
return (ControlBitRead((long)pVEndRegisterByte, pVEndPolarity));
};
BOOLEAN VersatecOnLine()
{
return (ControlBitRead((long)versOnLineRegisterByte, versOnLinePolarity));
};
BOOLEAN VersatecReady()
{
return (ControlBitRead((long)versReadyRegisterByte, versReadyPolarity));
};
void SetVersatecMode (versatecMode)
SparcSoftcardOps←VersatecMode versatecMode;
{
if ((versatecMode == VersatecMode←print) || (versatecMode == VersatecMode←SPPPrint)) {
ControlBitWrite((long)versatecPrintRegisterByte, versatecPrintPolarity, TRUE);
}
else {
ControlBitWrite((long)versatecPrintRegisterByte, versatecPrintPolarity, FALSE);
};
if ((versatecMode == VersatecMode←SPPPrint) || (versatecMode == VersatecMode←SPPPlot)) {
ControlBitWrite((long)versatecSPPRegisterByte, versatecPrintPolarity, TRUE);
}
else {
ControlBitWrite((long)versatecSPPRegisterByte, versatecPrintPolarity, FALSE);
};
};
BOOLEAN SendVersatecRCommand (versatecRCommand)
SparcSoftcardOps←VersatecRCommand versatecRCommand;
{
int byteAddress;
switch (versatecRCommand) {
case VersatecRCommand𡤌LEAR : {
byteAddress = versatecClearByte;
break;
};
case VersatecRCommand←RESET : {
byteAddress = versatecResetByte;
break;
};
case VersatecRCommand←RLTER : {
byteAddress = versatecRLTERByte;
break;
};
case VersatecRCommand←RFFED : {
byteAddress = versatecRFFEDByte;
break;
};
case VersatecRCommand←REOTR : {
byteAddress = versatecREOTRByte;
break;
};
};
(void) io←peek ((long)byteAddress);
while ((VersatecOnLine() == TRUE)
& (VersatecReady() == FALSE)) ;
return (VersatecOnLine());
};
BOOLEAN VersatecSendOneByte (data)
unsigned char data;
{
unsigned char s[16], *p;
long byteAddress;
if (VersatecOnLine() == FALSE) {
return(FALSE);
}
else {
byteAddress = (long) s;
byteAddress = (byteAddress + 7) & (~ 7);
p = ( unsigned char * ) byteAddress;
*p = data;
SparcSoftcardOps←SetDMAState(DMAState←inactive);
SparcSoftcardOps←SetDMAMode(DMAMode←versatecOneShot);
SparcSoftcardOps𡤍MAAddressRegisterLoad(byteAddress);
SparcSoftcardOps←SetDMAState(DMAState�tive);
while ((VersatecOnLine() == TRUE)
&& (VersatecPrinterEnd() == FALSE)) ;
SparcSoftcardOps←SetDMAState(DMAState←inactive);
return (VersatecOnLine());
};
};
void SetTimer(byteCount)
long byteCount;
{
long count, data;
count = (byteCount - 64) / 16;
io←poke((long)timAddress3Byte, (long)0x32); /* command: timer 0 mode 1 */
data = count;
io←poke((long)timAddress0Byte, data); /* store count value LS byte first */
data = data / 256;
io←poke((long)timAddress0Byte, data); /* store count value MS byte last */
};
BOOLEAN VersatecSendSmallBuffer (byteAddress, byteCount)
long byteAddress, byteCount;
{
if (VersatecOnLine() == FALSE) {
return(FALSE);
}
else {
SparcSoftcardOps←SetDMAState(DMAState←inactive);
SparcSoftcardOps←SetDMAMode(DMAMode←versatecStream);
SparcSoftcardOps𡤍MAAddressRegisterLoad(byteAddress);
SetTimer(byteCount);
SparcSoftcardOps←SetDMAState(DMAState�tive);
while ((VersatecOnLine() == TRUE)
&& (VersatecPrinterEnd() == FALSE)) ;
SparcSoftcardOps←SetDMAState(DMAState←inactive);
return (VersatecOnLine());
};
};
BOOLEAN VersatecSendBuffer (byteAddress, byteCount)
long byteAddress, byteCount;
{
long bytesToSend;
unsigned char *p;
while ( (byteAddress % 16) != 0 ) { /* align on an 16 bytes word bondary */
p = (unsigned char *) byteAddress;
if (VersatecSendOneByte (*p) == FALSE) return (FALSE);
byteAddress += 1;
byteCount -= 1;
};
while ( byteCount > 1024 * 1024 ) { /* send 1 mega byte chunk at a time */
bytesToSend = 1024 * 1024;
byteCount -= 1024 * 1024;
if ( byteCount < 96 ) {  /* impossible to send less than 96 bytes at a time */
bytesToSend -= 96;
byteCount += 96;
};
if (VersatecSendSmallBuffer (byteAddress, bytesToSend) == FALSE) return (FALSE);
byteAddress += bytesToSend;
};
bytesToSend = byteCount - byteCount % 16;
if (bytesToSend >= 96 ) { /* send a multiple of sixteen bigger or equal than 96 bytes */
if (VersatecSendSmallBuffer (byteAddress, bytesToSend) == FALSE) return (FALSE);
byteAddress += bytesToSend;
byteCount -= bytesToSend;
};
while ( byteCount != 0 ) { /* last bytes */
p = (unsigned char *) byteAddress;
if (VersatecSendOneByte (*p) == FALSE) return (FALSE);
byteAddress += 1;
byteCount -= 1;
};
return (TRUE);
};
/*
Those fonctions are the one defined by the interface but return a too complex argument... they are not used now
*/
/*
Map Access
*/
static long ComputeEntryAddress (mapEntry)
SparcSoftcardOps←MapEntry mapEntry;
{
long mapEntryNumber, entryAddressHighByte;
switch (mapEntry.vMSpace.name) {
case VMSpaceName𡤍MA : {
mapEntryNumber = 0x0E000;
if (mapEntry.virtualAddressByte >= 0x4000000) goto eRROR;
break;
};
case VMSpaceName←iOP : {
mapEntryNumber = 0x0A000;
if (mapEntry.virtualAddressByte >= 0x1000000) goto eRROR;
break;
};
case VMSpaceName𡤌P : {
mapEntryNumber = 0x0A000 + 0x1000000/softcardPageSizeByte;
if (mapEntry.virtualAddressByte >= 0x400000) goto eRROR;
break;
};
case VMSpaceName←sparcUserData : {
mapEntryNumber = 0;
if (mapEntry.virtualAddressByte >= 0x8000000) goto eRROR;
break;
};
case VMSpaceName←sparcUserProgram : {
mapEntryNumber = 0x4000;
if (mapEntry.virtualAddressByte >= 0x8000000) goto eRROR;
break;
};
case VMSpaceName←sparcSuperData : {
mapEntryNumber = 0x8000;
if (mapEntry.virtualAddressByte >= 0x4000000) goto eRROR;
break;
};
case VMSpaceName←sparcSuperProgram : {
mapEntryNumber = 0xC000;
if (mapEntry.virtualAddressByte >= 0x4000000) goto eRROR;
break;
};
default : {
eRROR: for(;;){};
};
};
mapEntryNumber = mapEntryNumber + mapEntry.virtualAddressByte/softcardPageSizeByte;
entryAddressHighByte = mapBaseByte + mapEntryNumber * mapEntrySizeByte;
return (entryAddressHighByte);
};
static long ConcreteFromEntry (mapEntry)
SparcSoftcardOps←MapEntry mapEntry;
{
long mapEntryConcreteCard, *p;
SparcSoftcardOps←MapEntryConcrete mapEntryConcrete, *q;
mapEntryConcrete.readOnly = mapEntry.flags.readOnly;
mapEntryConcrete.referenced = mapEntry.flags.referenced;
mapEntryConcrete.dirty = mapEntry.flags.dirty;
mapEntryConcrete.nonCachable = mapEntry.flags.nonCachable;
mapEntryConcrete.interrupt = mapEntry.flags.interrupt;
/* Implemented for 128 Mega in task 0 only */
mapEntryConcrete.task = 0;
mapEntryConcrete.virtualPageHiHi = 0;
mapEntryConcrete.virtualPageHiLow = 0;
mapEntryConcrete.realPage = mapEntry.realAddressByte/softcardPageSizeByte;
/* Convert this machine dependant structure into a long */
q = &mapEntryConcrete;
p = (long *) q;
mapEntryConcreteCard = *p;
return (mapEntryConcreteCard);
};
void SparcSoftcardOps←WriteMapEntry (mapEntry)
SparcSoftcardOps←MapEntry mapEntry;
{
long entryAddressHighByte, entryAddressLowByte;
long mapEntryConcrete;
entryAddressHighByte = ComputeEntryAddress (mapEntry);
entryAddressLowByte = entryAddressHighByte + mapEntryLowByteOffset - mapEntryHighByteOffset;
mapEntryConcrete = ConcreteFromEntry (mapEntry);
io←poke((long)entryAddressHighByte, ( mapEntryConcrete>>16));
io←poke((long)entryAddressLowByte, (mapEntryConcrete));
};