AppleRS232Serial.cpp [plain text]
#include <libkern/OSByteOrder.h>
#include <IOKit/IOLib.h>
#include <IOKit/IOReturn.h>
#include <IOKit/IOKitKeys.h>
#include <IOKit/IOPlatformExpert.h>
#include <IOKit/IODeviceTreeSupport.h>
#include <IOKit/serial/IOSerialKeys.h>
#include "AppleRS232Serial.h"
#if USE_ELG
com_apple_iokit_XTrace *gXTrace = 0;
UInt32 gTraceID;
#endif
#define super IOSerialDriverSync
OSDefineMetaClassAndStructors(AppleRS232Serial, IOSerialDriverSync);
#if USE_ELG
#define DEBUG_NAME "AppleRS232Serial"
IOReturn KernelDebugFindKernelLogger()
{
OSIterator *iterator = NULL;
OSDictionary *matchingDictionary = NULL;
IOReturn error = 0;
matchingDictionary = IOService::serviceMatching("com_apple_iokit_XTrace");
if (!matchingDictionary)
{
error = kIOReturnError;
IOLog(DEBUG_NAME "[FindKernelLogger] Couldn't create a matching dictionary.\n");
goto exit;
}
iterator = IOService::getMatchingServices(matchingDictionary);
if (!iterator)
{
error = kIOReturnError;
IOLog(DEBUG_NAME "[FindKernelLogger] No XTrace logger found.\n");
goto exit;
}
gXTrace = (com_apple_iokit_XTrace*)iterator->getNextObject();
if (gXTrace)
{
IOLog(DEBUG_NAME "[FindKernelLogger] Found XTrace logger at %p.\n", gXTrace);
}
exit:
if (error != kIOReturnSuccess)
{
gXTrace = NULL;
IOLog(DEBUG_NAME "[FindKernelLogger] Could not find a logger instance. Error = %X.\n", error);
}
if (matchingDictionary)
matchingDictionary->release();
if (iterator)
iterator->release();
return error;
}
#endif
#if LOG_DATA
#define dumplen 32 // Set this to the number of bytes to dump and the rest should work out correct
#define buflen ((dumplen*2)+dumplen)+3
#define Asciistart (dumplen*2)+3
UInt8 Asciify(UInt8 i)
{
i &= 0xF;
if ( i < 10 )
return( '0' + i );
else return( 55 + i );
}
void SerialLogData(UInt8 Dir, UInt32 Count, char *buf)
{
SInt32 wlen;
#if USE_ELG
UInt8 *b;
UInt8 w[8];
#else
UInt32 llen, rlen;
UInt16 i, Aspnt, Hxpnt;
UInt8 wchr;
char LocBuf[buflen+1];
#endif
switch (Dir)
{
case kSerialIn:
#if USE_ELG
XTRACE2(buf, Count, "SerialLogData - Read Complete, address, size");
#else
IOLog( "AppleRS232Serial: SerialLogData - Read Complete, address = %8x, size = %8d\n", (UInt)buf, (UInt)Count );
#endif
break;
case kSerialOut:
#if USE_ELG
XTRACE2(buf, Count, "SerialLogData - Write, address, size");
#else
IOLog( "AppleRS232Serial: SerialLogData - Write, address = %8x, size = %8d\n", (UInt)buf, (UInt)Count );
#endif
break;
case kSerialOther:
#if USE_ELG
XTRACE2(buf, Count, "SerialLogData - Other, address, size");
#else
IOLog( "AppleRS232Serial: SerialLogData - Other, address = %8x, size = %8d\n", (UInt)buf, (UInt)Count );
#endif
break;
}
#if DUMPALL
wlen = Count;
#else
if (Count > dumplen)
{
wlen = dumplen;
} else {
wlen = Count;
}
#endif
if (wlen == 0)
{
#if USE_ELG
XTRACE2(0, Count, "SerialLogData - No data, Count=0");
#else
IOLog( "AppleRS232Serial: SerialLogData - No data, Count=0\n" );
#endif
return;
}
#if (USE_ELG)
b = (UInt8 *)buf;
while (wlen > 0) {
bzero(w, sizeof(w)); bcopy(b, w, min(wlen, 8));
switch (Dir)
{
case kSerialIn:
XTRACE2((w[0] << 24 | w[1] << 16 | w[2] << 8 | w[3]), (w[4] << 24 | w[5] << 16 | w[6] << 8 | w[7]), "SerialLogData - Rx buffer dump");
break;
case kSerialOut:
XTRACE2((w[0] << 24 | w[1] << 16 | w[2] << 8 | w[3]), (w[4] << 24 | w[5] << 16 | w[6] << 8 | w[7]), "SerialLogData - Tx buffer dump");
break;
case kSerialOther:
XTRACE2((w[0] << 24 | w[1] << 16 | w[2] << 8 | w[3]), (w[4] << 24 | w[5] << 16 | w[6] << 8 | w[7]), "SerialLogData - Misc buffer dump");
break;
}
wlen -= 8; b += 8;
}
#else
rlen = 0;
do
{
for (i=0; i<=buflen; i++)
{
LocBuf[i] = 0x20;
}
LocBuf[i] = 0x00;
if (wlen > dumplen)
{
llen = dumplen;
wlen -= dumplen;
} else {
llen = wlen;
wlen = 0;
}
Aspnt = Asciistart;
Hxpnt = 0;
for (i=1; i<=llen; i++)
{
wchr = buf[i-1];
LocBuf[Hxpnt++] = Asciify(wchr >> 4);
LocBuf[Hxpnt++] = Asciify(wchr);
if ((wchr < 0x20) || (wchr > 0x7F)) {
LocBuf[Aspnt++] = 0x2E; } else {
LocBuf[Aspnt++] = wchr;
}
}
LocBuf[(llen + Asciistart) + 1] = 0x00;
IOLog(LocBuf);
IOLog("\n");
IOSleep(Sleep_Time);
rlen += llen;
buf = &buf[rlen];
} while (wlen != 0);
#endif
}
#endif
static inline UInt64 getDebugFlagsTable(OSDictionary *props)
{
OSNumber *debugProp;
UInt64 debugFlags = gIOKitDebug;
debugProp = OSDynamicCast(OSNumber, props->getObject(gIOKitDebugKey));
if (debugProp)
debugFlags = debugProp->unsigned64BitValue();
return debugFlags;
}
bool AppleRS232Serial::start(IOService *provider)
{
IORegistryEntry *parentEntry;
OSString *matched;
IOMemoryMap *map;
OSData *cProp;
char *tmp;
Boolean ok = false;
IOService *topProvider = NULL;
IOService *tProvider;
#if USE_ELG
XTraceLogInfo *logInfo;
KernelDebugFindKernelLogger();
if (gXTrace)
{
gXTrace->retain(); gTraceID = gXTrace->GetNewId();
ELG((UInt32)this, 0xbeefbeef, "AppleRS232Serial: Hello from start");
logInfo = gXTrace->LogGetInfo();
IOLog("AppleRS232Serial::start - Log is at %x\n", (unsigned int)logInfo);
} else {
return false;
}
#endif
ELG(this, provider, "AppleRS232Serial::start - this, provider");
if (!super::start(provider))
{
ALERT(0, 0, "AppleRS232Serial::start - super failed");
return false;
}
fProvider = OSDynamicCast(AppleMacIODevice, provider);
if (!fProvider)
{
ALERT(0, 0, "AppleRS232Serial::start - provider invalid");
return false;
}
parentEntry = provider->getParentEntry(gIODTPlane);
if (!parentEntry || IODTMatchNubWithKeys(parentEntry, "'escc-legacy'"))
{
ELG(0, 0, "AppleRS232Serial::start - escc-legacy not supported");
return false;
}
ok = false;
cProp = OSDynamicCast(OSData, provider->getProperty("AAPL,connector"));
if (cProp != NULL)
{
tmp = (char *)cProp->getBytesNoCopy();
if (strcmp(tmp, "DB9") == 0)
{
ok = true;
}
}
if (0)
{
tProvider = fProvider;
while (tProvider)
{
topProvider = tProvider; tProvider = tProvider->getProvider();
}
if (topProvider && IODTMatchNubWithKeys(topProvider, "'RackMac1,1'"))
{
ok = true;
}
}
if (!ok)
{
ALERT(0, 0, "AppleRS232Serial::start - returning false early, Connector or machine incorrect");
return false;
}
{
UInt32 debugFlags;
if (!PE_parse_boot_arg("debug", &debugFlags))
debugFlags = 0;
if (debugFlags & 8)
{
ALERT(0, 0, "AppleRS232Serial::start - returning false early, Serial debugging is enabled");
return false;
}
}
matched = (OSString *)getProperty(gIONameMatchedKey);
if (matched->isEqualTo("ch-a"))
{
ELG(0, 0, "AppleRS232Serial::start - escc Port A");
fPort.whichPort = serialPortA;
} else {
if (matched->isEqualTo("ch-b"))
{
ELG(0, 0, "AppleRS232Serial::start - escc Port B");
fPort.whichPort = serialPortB;
} else {
ALERT(0, 0, "AppleRS232Serial::start - Port invalid");
return false;
}
}
fWorkLoop = getWorkLoop();
if (!fWorkLoop)
{
ALERT(0, 0, "AppleRS232Serial::start - getWorkLoop failed");
return false;
}
fWorkLoop->retain();
fCommandGate = IOCommandGate::commandGate(this);
if (!fCommandGate)
{
ALERT(0, 0, "AppleRS232Serial::start - commandGate failed");
shutDown();
return false;
}
if (fWorkLoop->addEventSource(fCommandGate) != kIOReturnSuccess)
{
ALERT(0, 0, "AppleRS232Serial::start - addEventSource(commandGate) failed");
shutDown();
return false;
}
fCommandGate->enable();
fPort.IODBDMARxLock = IOLockAlloc();
fPort.IODBDMATrLock = IOLockAlloc();
fPort.DTRAsserted = true; fPort.aboveRxHighWater = false;
fPort.SCCAccessLock = IOLockAlloc();
if (!fPort.SCCAccessLock)
{
ALERT(0, 0, "AppleRS232Serial::start - Allocate SCC Access lock failed");
shutDown();
return false;
}
if (!initializePort(&fPort)) {
ALERT(0, 0, "AppleRS232Serial::start - Initialize port failed");
shutDown();
return false;
}
setStructureDefaults(&fPort);
fPort.Instance = fPort.whichPort;
fPort.RS232 = this;
map = provider->mapDeviceMemoryWithIndex(0);
if (!map)
{
ALERT(0, 0, "AppleRS232Serial::start - Mapping device memory failed");
shutDown();
return false;
}
fPort.Base = map->getVirtualAddress();
fPort.ChipBaseAddress = fPort.Base;
SccSetDMARegisters(&fPort, provider);
if ((fPort.TxDBDMAChannel.dmaChannelAddress == NULL) || (fPort.TxDBDMAChannel.dmaBase == NULL) ||
(fPort.RxDBDMAChannel.dmaChannelAddress == NULL) || (fPort.RxDBDMAChannel.dmaBase == NULL))
{
ALERT(0, 0, "AppleRS232Serial::start - DMA setup failed");
shutDown();
return false;
}
fPort.TXStats.BufferSize = BUFFER_SIZE_DEFAULT;
fPort.RXStats.BufferSize = BUFFER_SIZE_DEFAULT;
initChip(&fPort);
sccInterruptSource = IOInterruptEventSource::interruptEventSource(this, (IOInterruptEventAction)&AppleRS232Serial::interruptHandler,
provider, kIntChipSet);
if (!sccInterruptSource)
{
ALERT(0, 0, "AppleRS232Serial::start - Interrupt event source failed");
shutDown();
return false;
}
if (fWorkLoop->addEventSource(sccInterruptSource) != kIOReturnSuccess)
{
ALERT(0, 0, "AppleRS232Serial::start - Add interrupt source to work loop failed");
shutDown();
}
#if USE_FILTER_EVENT_SOURCES
txDMAInterruptSource = IOFilterInterruptEventSource::filterInterruptEventSource(this, (IOInterruptEventAction) &AppleRS232Serial::interruptHandler,
(IOFilterInterruptAction) &AppleRS232Serial::interruptFilter, provider, kIntTxDMA);
#else
txDMAInterruptSource = IOInterruptEventSource::interruptEventSource(this, (IOInterruptEventAction)&AppleRS232Serial::interruptHandler, provider, kIntTxDMA);
#endif
if (!txDMAInterruptSource)
{
ALERT(0, 0, "AppleRS232Serial::start - TX DMA interrupt event source failed");
shutDown();
return false;
}
if (fWorkLoop->addEventSource(txDMAInterruptSource) != kIOReturnSuccess)
{
ALERT(0, 0, "AppleRS232Serial::start - Add TX DMA interrupt event source to work loop failed");
shutDown();
return false;
}
#if USE_FILTER_EVENT_SOURCES
rxDMAInterruptSource = IOFilterInterruptEventSource::filterInterruptEventSource(this, (IOInterruptEventAction) &AppleRS232Serial::interruptHandler,
(IOFilterInterruptAction) &AppleRS232Serial::interruptFilter, provider, kIntRxDMA);
#else
rxDMAInterruptSource = IOInterruptEventSource::interruptEventSource(this, (IOInterruptEventAction)&AppleRS232Serial::interruptHandler, provider, kIntRxDMA);
#endif
if (!rxDMAInterruptSource)
{
ALERT(0, 0, "AppleRS232Serial::start - RX DMA interrupt event source failed");
shutDown();
return false;
}
if (fWorkLoop->addEventSource(rxDMAInterruptSource) != kIOReturnSuccess)
{
ALERT(0, 0, "AppleRS232Serial::start - Add RX DMA interrupt event source to work loop failed");
shutDown();
return false;
}
fPort.rxTimer = IOTimerEventSource::timerEventSource(this, rxTimeoutHandler);
if( !fPort.rxTimer )
{
ALERT(0, 0, "AppleRS232Serial::start - Timer event source failed");
shutDown();
return false;
}
if (fWorkLoop->addEventSource(fPort.rxTimer) != kIOReturnSuccess)
{
ALERT(0, 0, "AppleRS232Serial::start - Add timer event source to work loop failed");
shutDown();
return false;
}
if (!allocateRingBuffer(&(fPort.TX), fPort.TXStats.BufferSize) || !allocateRingBuffer(&(fPort.RX), fPort.RXStats.BufferSize))
{
ELG(0, 0, "AppleRS232Serial::start - Allocate for ring buffers failed");
shutDown();
return false;
}
callPlatformFunction("EnableSCC", false, (void *)true, 0, 0, 0);
if (!createSerialStream(provider))
{
ALERT(0, 0, "AppleRS232Serial::start - Create serial stream failed");
shutDown();
return false;
}
fCurrentPowerState = 1; if (!initForPM(provider)) {
ALERT(0, 0, "AppleRS232Serial::start - failed to init for power management");
shutDown();
return false;
}
ELG(0, 0, "AppleRS232Serial::start - Successful");
return true;
}
void AppleRS232Serial::stop(IOService *provider)
{
ELG(0, 0, "AppleRS232Serial::stop");
PMstop();
shutDown();
super::stop(provider);
}
IOReturn AppleRS232Serial::acquirePort(bool sleep, void *refCon)
{
IOReturn ret;
ELG(0, sleep, "AppleRS232Serial::acquirePort");
retain();
ret = fCommandGate->runAction(acquirePortAction, (void *)sleep);
release();
return ret;
}
IOReturn AppleRS232Serial::acquirePortAction(OSObject *owner, void *arg0, void *, void *, void *)
{
return ((AppleRS232Serial *)owner)->acquirePortGated((bool)arg0);
}
IOReturn AppleRS232Serial::acquirePortGated(bool sleep)
{
UInt32 busyState = 0;
IOReturn rtn = kIOReturnSuccess;
ELG(0, sleep, "AppleRS232Serial::acquirePortGated");
retain(); while (true)
{
busyState = fPort.State & PD_S_ACQUIRED;
if (!busyState)
{
setStateGated((UInt32)PD_S_ACQUIRED | DEFAULT_STATE, (UInt32)STATE_ALL);
break;
} else {
if (!sleep)
{
ELG(0, 0, "AppleRS232Serial::acquirePortGated - Busy exclusive access");
release();
return kIOReturnExclusiveAccess;
} else {
busyState = 0;
rtn = watchStateGated(&busyState, PD_S_ACQUIRED);
if ((rtn == kIOReturnIOError) || (rtn == kIOReturnSuccess))
{
continue;
} else {
ELG( 0, 0, "AppleRS232Serial::acquirePortGated - Interrupted!" );
release();
return rtn;
}
}
}
}
do
{
if (!fProvider->open(this))
{
rtn = kIOReturnBusy;
ELG(0, rtn, "AppleRS232Serial::acquirePortGated - Open for provider failed");
break;
}
setStructureDefaults(&fPort);
ResetQueue(&fPort.TX);
ResetQueue(&fPort.RX);
OpenScc(&fPort);
SccSetupReceptionChannel(&fPort);
SccdbdmaDefineReceptionCommands(&fPort);
SccSetupTansmissionChannel(&fPort);
SccdbdmaDefineTansmissionCommands(&fPort);
sccInterruptSource->enable();
txDMAInterruptSource->enable();
rxDMAInterruptSource->enable();
SccdbdmaStartReception(&fPort);
portOpened = true;
clock_get_uptime(&startingTime);
ELG(0, 0, "AppleRS232Serial::acquirePortGated - Successful");
return kIOReturnSuccess;
} while (0);
fProvider->close(this);
setStateGated(0, STATE_ALL); release();
ELG(0, rtn, "AppleRS232Serial::acquirePortGated - failed");
return rtn;
}
IOReturn AppleRS232Serial::releasePort(void *refCon)
{
IOReturn ret;
ELG(0, 0, "AppleRS232Serial::releasePort");
retain();
ret = fCommandGate->runAction(releasePortAction);
release();
return ret;
}
IOReturn AppleRS232Serial::releasePortAction(OSObject *owner, void *, void *, void *, void *)
{
return ((AppleRS232Serial *)owner)->releasePortGated();
}
IOReturn AppleRS232Serial::releasePortGated()
{
UInt32 busyState = 0;
int i;
ELG(0, 0, "AppleRS232Serial::releasePortGated");
busyState = fPort.State & PD_S_ACQUIRED;
if (!busyState)
{
ELG( 0, 0, "AppleRS232Serial::releasePortGated - NOT OPEN" );
return kIOReturnNotOpen;
}
for (i=0; i<(256>>SPECIAL_SHIFT); i++)
{
fPort.SWspecial[i] = 0;
}
fPort.CharLength = 8;
fPort.BreakLength = 1;
fPort.XONchar = '\x11';
fPort.XOFFchar = '\x13';
fPort.StopBits = 1<<1;
fPort.TX_Parity = PD_RS232_PARITY_NONE;
fPort.RX_Parity = PD_RS232_PARITY_DEFAULT;
fPort.RXOstate = IDLE_XO;
fPort.BaudRate = kDefaultBaudRate;
fPort.FlowControl = DEFAULT_NOTIFY;
fPort.FlowControlState = CONTINUE_SEND;
fPort.DCDState = false;
fPort.BreakState = false;
SccCloseChannel(&fPort);
sccInterruptSource->disable();
txDMAInterruptSource->disable();
rxDMAInterruptSource->disable();
fProvider->close(this);
setStateGated(0, STATE_ALL);
portOpened = false;
release();
ELG( 0, 0, "AppleRS232Serial::releasePortGated - OK" );
return kIOReturnSuccess;
}
UInt32 AppleRS232Serial::getState(void *refCon)
{
UInt32 currState;
ELG(0, 0, "AppleRS232Serial::getState");
retain();
currState = fCommandGate->runAction(getStateAction);
release();
return currState;
}
IOReturn AppleRS232Serial::getStateAction(OSObject *owner, void *, void *, void *, void *)
{
UInt32 newState;
newState = ((AppleRS232Serial *)owner)->getStateGated();
return newState;
}
UInt32 AppleRS232Serial::getStateGated()
{
UInt32 state;
ELG(0, 0, "AppleRS232Serial::getStateGated");
CheckQueues(&fPort);
state = fPort.State;
ELG(0, state, "AppleRS232Serial::getStateGated - Exit");
return state;
}
IOReturn AppleRS232Serial::setState(UInt32 state, UInt32 mask, void *refCon)
{
IOReturn ret;
ELG(state, mask, "AppleRS232Serial::setState");
if (mask & (PD_S_ACQUIRED | PD_S_ACTIVE | (~EXTERNAL_MASK)))
{
return kIOReturnBadArgument;
}
mask &= (~fPort.FlowControl & PD_RS232_A_MASK) | PD_S_MASK;
if (mask)
{
retain();
ret = fCommandGate->runAction(setStateAction, (void *)state, (void *)mask);
release();
return ret;
}
return kIOReturnSuccess;
}
IOReturn AppleRS232Serial::setStateAction(OSObject *owner, void *arg0, void *arg1, void *, void *)
{
return ((AppleRS232Serial *)owner)->setStateGated((UInt32)arg0, (UInt32)arg1);
}
IOReturn AppleRS232Serial::setStateGated(UInt32 state, UInt32 mask)
{
UInt32 delta;
if ((state & PD_S_ACQUIRED) || (fPort.State & PD_S_ACQUIRED))
{
if ((mask & PD_RS232_S_DTR) && ((fPort.FlowControl & PD_RS232_A_DTR) != PD_RS232_A_DTR))
{
if ((state & PD_RS232_S_DTR) != (fPort.State & PD_RS232_S_DTR))
{
if (state & PD_RS232_S_DTR)
{
SccSetDTR(&fPort, true);
} else {
SccSetDTR(&fPort, false);
}
}
}
state = (fPort.State & ~mask) | (state & mask); delta = state ^ fPort.State; fPort.State = state;
if (delta & fPort.WatchStateMask)
{
fCommandGate->commandWakeup((void *)&fPort.State);
}
return kIOReturnSuccess;
}
return kIOReturnNotOpen;
}
IOReturn AppleRS232Serial::watchState(UInt32 *state, UInt32 mask, void *refCon)
{
IOReturn ret;
ELG(*state, mask, "AppleRS232Serial::watchState");
if (!state)
return kIOReturnBadArgument;
if (!mask)
return kIOReturnSuccess;
retain();
ret = fCommandGate->runAction(watchStateAction, (void *)state, (void *)mask);
release();
return ret;
}
IOReturn AppleRS232Serial::watchStateAction(OSObject *owner, void *arg0, void *arg1, void *, void *)
{
return ((AppleRS232Serial *)owner)->watchStateGated((UInt32 *)arg0, (UInt32)arg1);
}
IOReturn AppleRS232Serial::watchStateGated(UInt32 *state, UInt32 mask)
{
unsigned watchState, foundStates;
bool autoActiveBit = false;
IOReturn ret = kIOReturnNotOpen;
ELG(*state, mask, "AppleRS232Serial::watchStateGated");
if (fPort.State & PD_S_ACQUIRED)
{
ret = kIOReturnSuccess;
mask &= EXTERNAL_MASK;
watchState = *state;
if (!(mask & (PD_S_ACQUIRED | PD_S_ACTIVE)))
{
watchState &= ~PD_S_ACTIVE; mask |= PD_S_ACTIVE; autoActiveBit = true;
}
while (true)
{
foundStates = (watchState ^ ~fPort.State) & mask;
if (foundStates)
{
*state = fPort.State;
if (autoActiveBit && (foundStates & PD_S_ACTIVE))
{
ret = kIOReturnIOError;
} else {
ret = kIOReturnSuccess;
}
break;
}
fPort.WatchStateMask |= mask;
retain(); fCommandGate->retain();
ret = fCommandGate->commandSleep((void *)&fPort.State);
fCommandGate->retain();
if (ret == THREAD_TIMED_OUT)
{
ret = kIOReturnTimeout;
break;
} else {
if (ret == THREAD_INTERRUPTED)
{
ret = kIOReturnAborted;
break;
}
}
release();
}
fPort.WatchStateMask = 0;
fCommandGate->commandWakeup((void *)&fPort.State);
*state &= EXTERNAL_MASK;
}
ELG(0, ret, "AppleRS232Serial::watchStateGated - Return code on exit" );
return ret;
}
UInt32 AppleRS232Serial::nextEvent(void *refCon)
{
UInt32 ret = kIOReturnSuccess;
ELG( 0, 0, "AppleRS232Serial::nextEvent" );
return ret;
}
IOReturn AppleRS232Serial::executeEvent(UInt32 event, UInt32 data, void *refCon)
{
IOReturn ret;
ELG(event, data, "AppleRS232Serial::executeEvent");
retain();
ret = fCommandGate->runAction(executeEventAction, (void *)event, (void *)data);
release();
return ret;
}
IOReturn AppleRS232Serial::executeEventAction(OSObject *owner, void *arg0, void *arg1, void *, void *)
{
return ((AppleRS232Serial *)owner)->executeEventGated((UInt32)arg0, (UInt32)arg1);
}
IOReturn AppleRS232Serial::executeEventGated(UInt32 event, UInt32 data)
{
IOReturn ret = kIOReturnSuccess;
UInt32 state, delta, tmp;
delta = 0;
state = fPort.State;
ELG(0, state, "AppleRS232Serial::executeEventGated");
if ((state & PD_S_ACQUIRED) == 0)
return kIOReturnNotOpen;
switch ( event )
{
case PD_RS232_E_XON_BYTE:
ELG(data, event, "AppleRS232Serial::executeEventGated - PD_RS232_E_XON_BYTE");
fPort.XONchar = data;
break;
case PD_RS232_E_XOFF_BYTE:
ELG(data, event, "AppleRS232Serial::executeEventGated - PD_RS232_E_XOFF_BYTE");
fPort.XOFFchar = data;
break;
case PD_E_SPECIAL_BYTE:
ELG(data, event, "AppleRS232Serial::executeEventGated - PD_E_SPECIAL_BYTE");
fPort.SWspecial[data >> SPECIAL_SHIFT] |= (1 << (data & SPECIAL_MASK));
break;
case PD_E_VALID_DATA_BYTE:
ELG(data, event, "AppleRS232Serial::executeEventGated - PD_E_VALID_DATA_BYTE");
fPort.SWspecial[data >> SPECIAL_SHIFT] &= ~(1 << (data & SPECIAL_MASK));
break;
case PD_E_FLOW_CONTROL:
ELG(data, event, "AppleRS232Serial::executeEventGated - PD_E_FLOW_CONTROL");
tmp = FLOW_RX_AUTO & (data ^ fPort.FlowControl);
fPort.FlowControl = data & (CAN_BE_AUTO | CAN_NOTIFY);
if (tmp)
{
if (tmp & PD_RS232_A_RXO)
{
fPort.RXOstate = NEEDS_XOFF;
}
}
break;
case PD_E_ACTIVE:
ELG( data, event, "AppleRS232Serial::executeEventGated - PD_E_ACTIVE");
if ((bool)data)
{
if (!(fPort.State & PD_S_ACTIVE))
{
setStructureDefaults(&fPort);
setStateGated(PD_S_ACTIVE, PD_S_ACTIVE);
}
} else {
setStateGated(0, PD_S_ACTIVE); SccCloseChannel(&fPort); }
break;
case PD_E_DATA_LATENCY:
ELG(data, event, "AppleRS232Serial::executeEventGated - PD_E_DATA_LATENCY");
fPort.DataLatInterval = long2tval(data * 1000);
break;
case PD_RS232_E_MIN_LATENCY:
ELG(data, event, "AppleRS232Serial::executeEventGated - PD_RS232_E_MIN_LATENCY");
fPort.MinLatency = bool(data);
fPort.DLRimage = 0x0000;
break;
case PD_E_DATA_INTEGRITY:
ELG(data, event, "AppleRS232Serial::executeEventGated - PD_E_DATA_INTEGRITY");
if ((data < PD_RS232_PARITY_NONE) || (data > PD_RS232_PARITY_SPACE))
{
ret = kIOReturnBadArgument;
} else {
fPort.TX_Parity = data;
fPort.RX_Parity = PD_RS232_PARITY_DEFAULT;
if (!SccSetParity(&fPort, (ParityType)data))
{
ret = kIOReturnBadArgument;
ELG(0, 0, "AppleRS232Serial::executeEventGated - SccSetParity failed");
}
}
break;
case PD_E_DATA_RATE:
ELG(data, event, "AppleRS232Serial::executeEventGated - PD_E_DATA_RATE");
data >>= 1; ELG(0, data, "AppleRS232Serial::executeEventGated - actual data rate");
if ((data < MIN_BAUD) || (data > kMaxBaudRate))
{
ret = kIOReturnBadArgument;
} else {
fPort.BaudRate = data;
if (!SccSetBaud(&fPort, data))
{
ret = kIOReturnBadArgument;
ELG(0, 0, "AppleRS232Serial::executeEventGated - SccSetBaud failed");
}
}
break;
case PD_E_DATA_SIZE:
ELG(data, event, "AppleRS232Serial::executeEventGated - PD_E_DATA_SIZE");
data >>= 1; ELG(0, data, "AppleRS232Serial::executeEventGated - actual data size");
if ((data < 5) || (data > 8))
{
ret = kIOReturnBadArgument;
} else {
fPort.CharLength = data;
if (!SccSetDataBits(&fPort, data))
{
ret = kIOReturnBadArgument;
ELG(0, 0, "AppleRS232Serial::executeEventGated - SccSetDataBits failed");
}
}
break;
case PD_RS232_E_STOP_BITS:
ELG(data, event, "AppleRS232Serial::executeEventGated - PD_RS232_E_STOP_BITS");
if ((data < 0) || (data > 20))
{
ret = kIOReturnBadArgument;
} else {
fPort.StopBits = data;
if (!SccSetStopBits(&fPort, data))
{
ret = kIOReturnBadArgument;
ELG(0, 0, "AppleRS232Serial::executeEventGated - SccSetStopBits failed");
}
}
break;
case PD_E_RXQ_FLUSH:
ELG(data, event, "AppleRS232Serial::executeEventGated - PD_E_RXQ_FLUSH");
break;
case PD_E_RX_DATA_INTEGRITY:
ELG(data, event, "AppleRS232Serial::executeEventGated - PD_E_RX_DATA_INTEGRITY");
if ((data != PD_RS232_PARITY_DEFAULT) && (data != PD_RS232_PARITY_ANY))
{
ret = kIOReturnBadArgument;
} else {
fPort.RX_Parity = data;
}
break;
case PD_E_RX_DATA_RATE:
ELG(data, event, "AppleRS232Serial::executeEventGated - PD_E_RX_DATA_RATE");
if (data)
{
ret = kIOReturnBadArgument;
}
break;
case PD_E_RX_DATA_SIZE:
ELG(data, event, "AppleRS232Serial::executeEventGated - PD_E_RX_DATA_SIZE");
if (data)
{
ret = kIOReturnBadArgument;
}
break;
case PD_RS232_E_RX_STOP_BITS:
ELG(data, event, "AppleRS232Serial::executeEventGated - PD_RS232_E_RX_STOP_BITS");
if (data)
{
ret = kIOReturnBadArgument;
}
break;
case PD_E_TXQ_FLUSH:
ELG(data, event, "AppleRS232Serial::executeEventGated - PD_E_TXQ_FLUSH");
break;
case PD_RS232_E_LINE_BREAK:
ELG(data, event, "AppleRS232Serial::executeEventGated - PD_RS232_E_LINE_BREAK");
state &= ~PD_RS232_S_BRK;
delta |= PD_RS232_S_BRK;
if (data)
{
fPort.BreakState = true;
} else {
fPort.BreakState = false;
}
SccSetBreak(&fPort, data);
setStateGated(state, delta);
break;
case PD_E_DELAY:
ELG(data, event, "AppleRS232Serial::executeEventGated - PD_E_DELAY");
if (fPort.BreakState) {
IOSleep(data/1000);
} else {
fPort.CharLatInterval = long2tval(data * 1000);
}
break;
case PD_E_RXQ_SIZE:
ELG( 0, event, "AppleRS232Serial::executeEventGated - PD_E_RXQ_SIZE" );
break;
case PD_E_TXQ_SIZE:
ELG( 0, event, "AppleRS232Serial::executeEventGated - PD_E_TXQ_SIZE" );
break;
case PD_E_RXQ_HIGH_WATER:
ELG( data, event, "AppleRS232Serial::executeEventGated - PD_E_RXQ_HIGH_WATER" );
break;
case PD_E_RXQ_LOW_WATER:
ELG( data, event, "AppleRS232Serial::executeEventGated - PD_E_RXQ_LOW_WATER" );
break;
case PD_E_TXQ_HIGH_WATER:
ELG( data, event, "AppleRS232Serial::executeEventGated - PD_E_TXQ_HIGH_WATER" );
break;
case PD_E_TXQ_LOW_WATER:
ELG( data, event, "AppleRS232Serial::executeEventGated - PD_E_TXQ_LOW_WATER" );
break;
default:
ELG( data, event, "AppleRS232Serial::executeEventGated - unrecognized event" );
ret = kIOReturnBadArgument;
break;
}
return ret;
}
IOReturn AppleRS232Serial::requestEvent(UInt32 event, UInt32 *data, void *refCon)
{
IOReturn returnValue = kIOReturnSuccess;
ELG(0, 0, "AppleRS232Serial::requestEvent");
if (data == NULL)
{
ELG(0, event, "AppleRS232Serial::requestEvent - Invalid parameter, data is null");
returnValue = kIOReturnBadArgument;
} else {
switch (event)
{
case PD_E_ACTIVE:
ELG(0, event, "AppleRS232Serial::requestEvent - PD_E_ACTIVE");
*data = bool(getState(&fPort) & PD_S_ACTIVE);
break;
case PD_E_FLOW_CONTROL:
ELG(fPort.FlowControl, event, "AppleRS232Serial::requestEvent - PD_E_FLOW_CONTROL");
*data = fPort.FlowControl;
break;
case PD_E_DELAY:
ELG(0, event, "AppleRS232Serial::requestEvent - PD_E_DELAY");
*data = tval2long(fPort.CharLatInterval) / 1000;
break;
case PD_E_DATA_LATENCY:
ELG(0, event, "AppleRS232Serial::requestEvent - PD_E_DATA_LATENCY");
*data = tval2long(fPort.DataLatInterval) / 1000;
break;
case PD_E_TXQ_SIZE:
ELG(0, event, "AppleRS232Serial::requestEvent - PD_E_TXQ_SIZE");
*data = GetQueueSize(&fPort.TX);
break;
case PD_E_RXQ_SIZE:
ELG(0, event, "AppleRS232Serial::requestEvent - PD_E_RXQ_SIZE");
*data = GetQueueSize(&fPort.RX);
break;
case PD_E_TXQ_LOW_WATER:
ELG(0, event, "AppleRS232Serial::requestEvent - PD_E_TXQ_LOW_WATER");
*data = 0;
returnValue = kIOReturnBadArgument;
break;
case PD_E_RXQ_LOW_WATER:
ELG(0, event, "AppleRS232Serial::requestEvent - PD_E_RXQ_LOW_WATER");
*data = 0;
returnValue = kIOReturnBadArgument;
break;
case PD_E_TXQ_HIGH_WATER:
ELG(0, event, "AppleRS232Serial::requestEvent - PD_E_TXQ_HIGH_WATER");
*data = 0;
returnValue = kIOReturnBadArgument;
break;
case PD_E_RXQ_HIGH_WATER:
ELG(0, event, "AppleRS232Serial::requestEvent - PD_E_RXQ_HIGH_WATER");
*data = 0;
returnValue = kIOReturnBadArgument;
break;
case PD_E_TXQ_AVAILABLE:
ELG(0, event, "AppleRS232Serial::requestEvent - PD_E_TXQ_AVAILABLE");
*data = FreeSpaceinQueue(&fPort.TX);
break;
case PD_E_RXQ_AVAILABLE:
ELG(0, event, "AppleRS232Serial::requestEvent - PD_E_RXQ_AVAILABLE");
*data = UsedSpaceinQueue(&fPort.RX);
break;
case PD_E_DATA_RATE:
ELG(0, event, "AppleRS232Serial::requestEvent - PD_E_DATA_RATE");
*data = fPort.BaudRate << 1;
break;
case PD_E_RX_DATA_RATE:
ELG(0, event, "AppleRS232Serial::requestEvent - PD_E_RX_DATA_RATE");
*data = 0x00;
break;
case PD_E_DATA_SIZE:
ELG(0, event, "AppleRS232Serial::requestEvent - PD_E_DATA_SIZE");
*data = fPort.CharLength << 1;
break;
case PD_E_RX_DATA_SIZE:
ELG(0, event, "AppleRS232Serial::requestEvent - PD_E_RX_DATA_SIZE");
*data = 0x00;
break;
case PD_E_DATA_INTEGRITY:
ELG(0, event, "AppleRS232Serial::requestEvent - PD_E_DATA_INTEGRITY");
*data = fPort.TX_Parity;
break;
case PD_E_RX_DATA_INTEGRITY:
ELG(0, event, "AppleRS232Serial::requestEvent - PD_E_RX_DATA_INTEGRITY");
*data = fPort.RX_Parity;
break;
case PD_RS232_E_STOP_BITS:
ELG(0, event, "AppleRS232Serial::requestEvent - PD_RS232_E_STOP_BITS");
*data = fPort.StopBits << 1;
break;
case PD_RS232_E_RX_STOP_BITS:
ELG(0, event, "AppleRS232Serial::requestEvent - PD_RS232_E_RX_STOP_BITS");
*data = 0x00;
break;
case PD_RS232_E_XON_BYTE:
ELG(0, event, "AppleRS232Serial::requestEvent - PD_RS232_E_XON_BYTE");
*data = fPort.XONchar;
break;
case PD_RS232_E_XOFF_BYTE:
ELG(0, event, "AppleRS232Serial::requestEvent - PD_RS232_E_XOFF_BYTE");
*data = fPort.XOFFchar;
break;
case PD_RS232_E_LINE_BREAK:
ELG(0, event, "AppleRS232Serial::requestEvent - PD_RS232_E_LINE_BREAK");
*data = bool(getState(&fPort) & PD_RS232_S_BRK);
break;
case PD_RS232_E_MIN_LATENCY:
ELG(0, event, "AppleRS232Serial::requestEvent - PD_RS232_E_MIN_LATENCY");
*data = bool(fPort.MinLatency);
break;
default:
ELG(0, event, "AppleRS232Serial::requestEvent - unrecognized event");
returnValue = kIOReturnBadArgument;
break;
}
}
return kIOReturnSuccess;
}
IOReturn AppleRS232Serial::enqueueEvent(UInt32 event, UInt32 data, bool sleep, void *refCon)
{
IOReturn ret;
ELG(data, event, "AppleRS232Serial::enqueueEvent");
retain();
ret = fCommandGate->runAction(enqueueEventAction, (void *)event, (void *)data);
release();
return ret;
}
IOReturn AppleRS232Serial::enqueueEventAction(OSObject *owner, void *arg0, void *arg1, void *, void *)
{
return ((AppleRS232Serial *)owner)->executeEventGated((UInt32)arg0, (UInt32)arg1);
}
IOReturn AppleRS232Serial::dequeueEvent(UInt32 *event, UInt32 *data, bool sleep, void *refCon)
{
ELG(0, 0, "AppleRS232Serial::dequeueEvent");
if ((event == NULL) || (data == NULL))
return kIOReturnBadArgument;
return kIOReturnSuccess;
}
IOReturn AppleRS232Serial::enqueueData(UInt8 *buffer, UInt32 size, UInt32 *count, bool sleep, void *refCon)
{
IOReturn ret;
ELG(0, sleep, "AppleRS232Serial::enqueueData");
if (count == NULL || buffer == NULL)
return kIOReturnBadArgument;
retain();
ret = fCommandGate->runAction(enqueueDataAction, (void *)buffer, (void *)size, (void *)count, (void *)sleep);
release();
return ret;
}
IOReturn AppleRS232Serial::enqueueDataAction(OSObject *owner, void *arg0, void *arg1, void *arg2, void *arg3)
{
return ((AppleRS232Serial *)owner)->enqueueDataGated((UInt8 *)arg0, (UInt32)arg1, (UInt32 *)arg2, (bool)arg3);
}
IOReturn AppleRS232Serial::enqueueDataGated(UInt8 *buffer, UInt32 size, UInt32 *count, bool sleep)
{
UInt32 state = PD_S_TXQ_LOW_WATER;
IOReturn rtn = kIOReturnSuccess;
ELG(0, sleep, "AppleRS232Serial::enqueueDataGated");
*count = 0;
if (!(fPort.State & PD_S_ACTIVE))
return kIOReturnNotOpen;
*count = AddtoQueue(&fPort.TX, buffer, size);
CheckQueues(&fPort);
if (fPort.FlowControlState == PAUSE_SEND)
{
return kIOReturnSuccess;
}
SetUpTransmit(&fPort);
while ((*count < size) && sleep)
{
state = PD_S_TXQ_LOW_WATER;
rtn = watchStateGated(&state, PD_S_TXQ_LOW_WATER);
if ( rtn != kIOReturnSuccess )
{
ELG( 0, rtn, "AppleRS232Serial::enqueueDataGated - interrupted" );
return rtn;
}
*count += AddtoQueue(&fPort.TX, buffer + *count, size - *count);
CheckQueues(&fPort);
SetUpTransmit(&fPort);
}
ELG(*count, size, "AppleRS232Serial::enqueueDataGated - Count on exit");
return kIOReturnSuccess;
}
IOReturn AppleRS232Serial::dequeueData(UInt8 *buffer, UInt32 size, UInt32 *count, UInt32 min, void *refCon)
{
IOReturn ret;
ELG(0, 0, "AppleRS232Serial::dequeueData");
if ((count == NULL) || (buffer == NULL) || (min > size))
return kIOReturnBadArgument;
retain();
ret = fCommandGate->runAction(dequeueDataAction, (void *)buffer, (void *)size, (void *)count, (void *)min);
release();
return ret;
}
IOReturn AppleRS232Serial::dequeueDataAction(OSObject *owner, void *arg0, void *arg1, void *arg2, void *arg3)
{
return ((AppleRS232Serial *)owner)->dequeueDataGated((UInt8 *)arg0, (UInt32)arg1, (UInt32 *)arg2, (UInt32)arg3);
}
IOReturn AppleRS232Serial::dequeueDataGated(UInt8 *buffer, UInt32 size, UInt32 *count, UInt32 min)
{
IOReturn rtn = kIOReturnSuccess;
UInt32 state = 0;
ELG(size, min, "AppleRS232Serial::dequeueDataGated");
*count = 0;
if (!(fPort.State & PD_S_ACTIVE))
return kIOReturnNotOpen;
*count = RemovefromQueue(&fPort.RX, buffer, size);
CheckQueues(&fPort);
while ((min > 0) && (*count < min))
{
state = 0;
rtn = watchStateGated(&state, PD_S_RXQ_EMPTY);
if (rtn != kIOReturnSuccess)
{
ELG(0, rtn, "AppleRS232Serial::dequeueData - Interrupted!");
return rtn;
}
*count += RemovefromQueue(&fPort.RX, buffer + *count, (size - *count));
CheckQueues(&fPort);
}
LogData(kSerialIn, *count, buffer);
ELG(*count, size, "AppleRS232Serial::dequeueData - Count on exit");
return rtn;
}
void AppleRS232Serial::CheckQueues(PortInfo_t *port)
{
UInt32 Used;
UInt32 Free;
UInt32 OldState;
UInt32 DeltaState;
UInt32 SW_FlowControl;
UInt32 CTS_FlowControl;
UInt32 DTR_FlowControl;
OldState = port->State;
Used = UsedSpaceinQueue(&(port->TX));
Free = FreeSpaceinQueue(&(port->TX));
if (Free == 0) {
OldState |= PD_S_TXQ_FULL;
OldState &= ~PD_S_TXQ_EMPTY;
} else {
if (Used == 0)
{
OldState &= ~PD_S_TXQ_FULL;
OldState |= PD_S_TXQ_EMPTY;
} else {
OldState &= ~PD_S_TXQ_FULL;
OldState &= ~PD_S_TXQ_EMPTY;
}
}
if (Used < port->TXStats.LowWater)
{
OldState |= PD_S_TXQ_LOW_WATER;
} else {
OldState &= ~PD_S_TXQ_LOW_WATER;
}
if (Used > port->TXStats.HighWater)
{
OldState |= PD_S_TXQ_HIGH_WATER;
} else {
OldState &= ~PD_S_TXQ_HIGH_WATER;
}
Used = UsedSpaceinQueue(&(port->RX));
Free = FreeSpaceinQueue(&(port->RX));
if (Free == 0)
{
OldState |= PD_S_RXQ_FULL;
OldState &= ~PD_S_RXQ_EMPTY;
} else {
if (Used == 0)
{
OldState &= ~PD_S_RXQ_FULL;
OldState |= PD_S_RXQ_EMPTY;
} else {
OldState &= ~PD_S_RXQ_FULL;
OldState &= ~PD_S_RXQ_EMPTY;
}
}
SW_FlowControl = port->FlowControl & PD_RS232_A_RXO;
CTS_FlowControl = port->FlowControl & PD_RS232_A_CTS;
DTR_FlowControl = port->FlowControl & PD_RS232_A_DTR;
if (Used < port->RXStats.LowWater)
{
if ((SW_FlowControl) && (port->xOffSent))
{
port->xOffSent = false;
AddBytetoQueue(&(port->TX), port->XONchar);
SetUpTransmit(port);
}
OldState |= PD_S_RXQ_LOW_WATER;
} else {
OldState &= ~PD_S_RXQ_LOW_WATER;
}
if (Used > port->RXStats.HighWater)
{
if ((SW_FlowControl) && (!port->xOffSent))
{
port->xOffSent = true;
AddBytetoQueue(&(port->TX), port->XOFFchar);
SetUpTransmit(port);
}
if (CTS_FlowControl)
{
}
if (DTR_FlowControl && port->DTRAsserted)
{
port->DTRAsserted = false;
SccSetDTR(port, false);
}
} else {
if (DTR_FlowControl && !port->DTRAsserted)
{
port->DTRAsserted = true;
SccSetDTR(port, true);
}
OldState &= ~PD_S_RXQ_HIGH_WATER;
if (port->aboveRxHighWater)
{
port->aboveRxHighWater = false;
}
}
DeltaState = OldState ^ port->State;
setStateGated(OldState, DeltaState);
}
bool AppleRS232Serial::createSerialStream(IOService *provider)
{
IORS232SerialStreamSync *pNub = new IORS232SerialStreamSync;
bool ret;
ELG(0, 0, "AppleRS232Serial::createSerialStream");
if (!pNub)
{
ELG( 0, 0, "AppleRS232Serial::createSerialStream - Create nub failed" );
return false;
}
ret = (pNub->init(0, &fPort) && pNub->attach(this));
pNub->release();
if (!ret)
{
ALERT( ret, 0, "AppleRS232Serial::createSerialStream - Didn't attach to the nub properly" );
return false;
}
pNub->setProperty(kIOTTYBaseNameKey, "serial");
pNub->registerService();
return true;
}
bool AppleRS232Serial::initializePort(PortInfo_t *port)
{
SerialDBDMAStatusInfo *dmaInfo;
UInt32 descsize;
ELG(0, sizeof(IODBDMADescriptor), "AppleRS232Serial::initializePort");
dmaInfo = &port->TxDBDMAChannel;
ELG(0, dmaInfo, "AppleRS232Serial::initializePort - dmaInfo for TX");
#if NEWPHYS
dmaInfo->dmaTransferBufferMDP = IOBufferMemoryDescriptor::withOptions(0, PAGE_SIZE, PAGE_SIZE);
if (dmaInfo->dmaTransferBufferMDP == NULL)
{
ALERT(0, 0, "AppleRS232Serial::initializePort - TX DMA Transfer buffer descriptor not allocated");
return false;
}
ELG(0, dmaInfo->dmaTransferBufferMDP, "AppleRS232Serial::initializePort - TX DMA transfer buffer MDP");
dmaInfo->dmaTransferBufferMDP->prepare();
dmaInfo->dmaTransferBuffer = (UInt8 *)dmaInfo->dmaTransferBufferMDP->getBytesNoCopy();
bzero(dmaInfo->dmaTransferBuffer, PAGE_SIZE);
dmaInfo->dmaTransferSize = 0;
ELG(dmaInfo->dmaTransferBuffer, PAGE_SIZE, "AppleRS232Serial::initializePort - TX DMA transfer buffer and size");
#else
dmaInfo->dmaTransferBuffer = (UInt8 *)IOMallocContiguous(PAGE_SIZE, PAGE_SIZE, NULL);
if (dmaInfo->dmaTransferBuffer == NULL)
{
ALERT(0, 0, "AppleRS232Serial::initializePort - TX DMA Transfer buffer not allocated");
return false;
} else {
ELG(dmaInfo->dmaTransferBuffer, PAGE_SIZE, "AppleRS232Serial::initializePort - TX DMA transfer buffer and size");
bzero(dmaInfo->dmaTransferBuffer, PAGE_SIZE);
}
#endif
dmaInfo->dmaNumberOfDescriptors = 2;
#if NEWPHYS
dmaInfo->dmaChannelCommandAreaMDP = IOBufferMemoryDescriptor::withOptions(0, PAGE_SIZE, PAGE_SIZE);
if (dmaInfo->dmaChannelCommandAreaMDP == NULL)
{
dmaInfo->dmaNumberOfDescriptors = 0;
ALERT(0, 0, "AppleRS232Serial::initializePort - TX DMA Command Area descriptor not allocated");
return false;
}
dmaInfo->dmaChannelCommandAreaMDP->prepare();
dmaInfo->dmaChannelCommandArea = (IODBDMADescriptor *)dmaInfo->dmaChannelCommandAreaMDP->getBytesNoCopy();
bzero(dmaInfo->dmaChannelCommandArea, sizeof(IODBDMADescriptor) * dmaInfo->dmaNumberOfDescriptors);
ELG(dmaInfo->dmaNumberOfDescriptors, PAGE_SIZE, "AppleRS232Serial::initializePort - TX DMA Channel Command number of descriptors and size");
#else
dmaInfo->dmaChannelCommandArea = (IODBDMADescriptor *)IOMallocContiguous(PAGE_SIZE, PAGE_SIZE, NULL);
if (dmaInfo->dmaChannelCommandArea == NULL)
{
dmaInfo->dmaNumberOfDescriptors = 0;
ALERT(0, 0, "AppleRS232Serial::initializePort - TX DMA Channel Command Area not allocated");
return false;
} else {
ELG(dmaInfo->dmaNumberOfDescriptors, PAGE_SIZE, "AppleRS232Serial::initializePort - TX DMA Channel Command number of descriptors and size");
bzero(dmaInfo->dmaChannelCommandArea, sizeof(IODBDMADescriptor) * dmaInfo->dmaNumberOfDescriptors);
}
#endif
dmaInfo = &port->RxDBDMAChannel;
ELG(0, dmaInfo, "AppleRS232Serial::initializePort - dmaInfo for RX");
dmaInfo->dmaNumberOfDescriptors = PAGE_SIZE / sizeof(IODBDMADescriptor);
descsize = sizeof(IODBDMADescriptor) * dmaInfo->dmaNumberOfDescriptors;
#if NEWPHYS
dmaInfo->dmaChannelCommandAreaMDP = IOBufferMemoryDescriptor::withOptions(0, descsize, PAGE_SIZE);
if (dmaInfo->dmaChannelCommandAreaMDP == NULL)
{
dmaInfo->dmaNumberOfDescriptors = 0;
ALERT(0, 0, "AppleRS232Serial::initializePort - RX DMA Command Area descriptor not allocated");
return false;
}
dmaInfo->dmaChannelCommandAreaMDP->prepare();
dmaInfo->dmaChannelCommandArea = (IODBDMADescriptor *)dmaInfo->dmaChannelCommandAreaMDP->getBytesNoCopy();
bzero(dmaInfo->dmaChannelCommandArea, sizeof(IODBDMADescriptor) * dmaInfo->dmaNumberOfDescriptors);
ELG(dmaInfo->dmaNumberOfDescriptors, descsize, "AppleRS232Serial::initializePort - RX DMA Channel Command number of descriptors and size");
#else
dmaInfo->dmaChannelCommandArea = (IODBDMADescriptor *)IOMallocContiguous(descsize, PAGE_SIZE, NULL);
if (dmaInfo->dmaChannelCommandArea == NULL)
{
ALERT(0, 0, "AppleRS232Serial::initializePort - RX DMA Channel Command Area not allocated");
dmaInfo->dmaNumberOfDescriptors = 0;
return false;
} else {
ELG(dmaInfo->dmaNumberOfDescriptors, descsize, "AppleRS232Serial::initializePort - RX DMA Channel Command number of descriptors and size");
bzero(dmaInfo->dmaChannelCommandArea, sizeof(IODBDMADescriptor) * dmaInfo->dmaNumberOfDescriptors);
}
#endif
dmaInfo->dmaTransferSize = dmaInfo->dmaNumberOfDescriptors;
#if NEWPHYS
dmaInfo->dmaTransferBufferMDP = IOBufferMemoryDescriptor::withOptions(0, dmaInfo->dmaNumberOfDescriptors, PAGE_SIZE);
if (dmaInfo->dmaTransferBufferMDP == NULL)
{
ALERT(0, 0, "AppleRS232Serial::initializePort - RX DMA Transfer buffer descriptor not allocated");
return false;
}
ELG(0, dmaInfo->dmaTransferBufferMDP, "AppleRS232Serial::initializePort - RX DMA transfer buffer MDP");
dmaInfo->dmaTransferBufferMDP->prepare();
dmaInfo->dmaTransferBuffer = (UInt8 *)dmaInfo->dmaTransferBufferMDP->getBytesNoCopy();
bzero(dmaInfo->dmaTransferBuffer, dmaInfo->dmaNumberOfDescriptors);
ELG(dmaInfo->dmaTransferBuffer, dmaInfo->dmaNumberOfDescriptors, "AppleRS232Serial::initializePort - RX DMA transfer buffer and size");
#else
dmaInfo->dmaTransferBuffer = (UInt8*)IOMallocContiguous(dmaInfo->dmaNumberOfDescriptors, PAGE_SIZE, NULL);
if (dmaInfo->dmaTransferBuffer == NULL)
{
ALERT(0, 0, "AppleRS232Serial::initializePort - RX DMA Transfer buffer not allocated");
return false;
} else {
ELG(dmaInfo->dmaTransferBuffer, dmaInfo->dmaNumberOfDescriptors, "AppleRS232Serial::initializePort - RX DMA transfer buffer and size");
bzero(dmaInfo->dmaTransferBuffer, PAGE_SIZE);
}
#endif
port->Instance = 0;
port->PortName = NULL;
port->MasterClock = CHIP_CLOCK_DEFAULT;
port->DLRimage = 0x0000;
port->LCRimage = 0x00;
port->FCRimage = 0x00;
port->IERmask = 0x00;
port->RBRmask = 0x00;
port->Base = 0x0000;
port->DataLatInterval.tv_sec = 0;
port->DataLatInterval.tv_nsec = 0;
port->CharLatInterval.tv_sec = 0;
port->CharLatInterval.tv_nsec = 0;
port->State = (PD_S_TXQ_EMPTY | PD_S_TXQ_LOW_WATER | PD_S_RXQ_EMPTY | PD_S_RXQ_LOW_WATER);
port->WatchStateMask = 0x00000000;
return true;
}
void AppleRS232Serial::setStructureDefaults(PortInfo_t *port)
{
UInt32 tmp;
ELG(0, 0, "AppleRS232Serial::setStructureDefaults");
port->BreakLength = 0;
port->BaudRate = 0;
port->CharLength = 0;
port->BreakLength = 0;
port->StopBits = 0;
port->TX_Parity = 0;
port->RX_Parity = 0;
port->WaitingForTXIdle = false;
port->MinLatency = false;
port->XONchar = '\x11';
port->XOFFchar = '\x13';
port->FlowControl = 0x00000000;
port->FlowControlState = CONTINUE_SEND;
port->RXOstate = IDLE_XO;
port->TXOstate = IDLE_XO;
port->RXStats.BufferSize = BUFFER_SIZE_DEFAULT;
port->RXStats.HighWater = (port->RXStats.BufferSize << 1) / 3;
port->RXStats.LowWater = port->RXStats.HighWater >> 1;
port->TXStats.BufferSize = BUFFER_SIZE_DEFAULT;
port->TXStats.HighWater = (port->RXStats.BufferSize << 1) / 3;
port->TXStats.LowWater = port->RXStats.HighWater >> 1;
port->FlowControl = DEFAULT_NOTIFY;
port->AreTransmitting = FALSE;
for (tmp=0; tmp<(256>>SPECIAL_SHIFT); tmp++)
{
port->SWspecial[tmp] = 0;
}
port->Stats.ints = 0;
port->Stats.txInts = 0;
port->Stats.rxInts = 0;
port->Stats.mdmInts = 0;
port->Stats.txChars = 0;
port->Stats.rxChars = 0;
port->DCDState = false;
port->BreakState = false;
port->lastCTSTime = 0;
port->ctsTransitionCount = 0;
}
void AppleRS232Serial::freeRingBuffer(CirQueue *Queue)
{
ELG(0, Queue, "AppleRS232Serial::freeRingBuffer");
if (Queue->Start)
{
IOFree(Queue->Start, Queue->Size);
CloseQueue(Queue);
}
}
bool AppleRS232Serial::allocateRingBuffer(CirQueue *Queue, size_t BufferSize)
{
UInt8 *Buffer;
ELG(0, BufferSize, "AppleRS232Serial::allocateRingBuffer");
Buffer = (UInt8*)IOMalloc(BufferSize);
InitQueue(Queue, Buffer, BufferSize);
if (Buffer)
return true;
return false;
}
void AppleRS232Serial::shutDown()
{
ELG(0, 0, "AppleRS232Serial::shutDown");
SccFreeReceptionChannel(&fPort);
SccFreeTansmissionChannel(&fPort);
if (txDMAInterruptSource)
{
fWorkLoop->removeEventSource(txDMAInterruptSource);
txDMAInterruptSource->release();
txDMAInterruptSource = 0;
}
if (rxDMAInterruptSource)
{
fWorkLoop->removeEventSource(rxDMAInterruptSource);
rxDMAInterruptSource->release();
rxDMAInterruptSource = 0;
}
if (sccInterruptSource)
{
fWorkLoop->removeEventSource(sccInterruptSource);
sccInterruptSource->release();
sccInterruptSource = 0;
}
if(fPort.rxTimer)
{
fPort.rxTimer->cancelTimeout(); fWorkLoop->removeEventSource(fPort.rxTimer ); fPort.rxTimer->release(); fPort.rxTimer = NULL;
}
#if USE_TIMER_EVENT_SOURCE_DEBUGGING
if (fTimer)
{
fTimer->cancelTimeout(); fWorkLoop->removeEventSource(fTimer); fTimer->release(); fTimer = NULL;
}
#endif
if (fPort.ControlRegister != NULL)
{
SccCloseChannel(&fPort);
}
if (fPort.IODBDMARxLock)
{
IOLockFree(fPort.IODBDMARxLock);
fPort.IODBDMARxLock = NULL;
}
if (fPort.IODBDMATrLock)
{
IOLockFree(fPort.IODBDMATrLock);
fPort.IODBDMATrLock = NULL;
}
if (fPort.SCCAccessLock)
{
IOLockFree(fPort.SCCAccessLock);
fPort.SCCAccessLock = NULL;
}
freeRingBuffer(&(fPort.TX));
freeRingBuffer(&(fPort.RX));
if (fCommandGate)
{
fCommandGate->release();
fCommandGate = NULL;
}
if (fWorkLoop)
{
fWorkLoop->release();
fWorkLoop = NULL;
}
}
IOReturn AppleRS232Serial::sleepThread(void *event)
{
IOReturn stat;
ELG(0, event, "AppleRS232Serial::sleepThread");
retain();
fCommandGate->retain();
stat = fCommandGate->commandSleep((void*)&event);
fCommandGate->release();
release();
ELG(0, stat, "AppleRS232Serial::sleepThread - Exit");
return stat;
}
bool AppleRS232Serial::interruptFilter(OSObject* obj, IOFilterInterruptEventSource *source)
{
UInt16 interruptIndex;
interruptIndex = source->getIntIndex();
if (interruptIndex == kIntRxDMA)
{
return true; }
if (interruptIndex == kIntTxDMA)
{
return true; }
return false;
}
void AppleRS232Serial::interruptHandler(OSObject* obj, IOInterruptEventSource *source, int count)
{
UInt16 interruptIndex;
ELG(0, obj, "AppleRS232Serial::interruptHandler");
interruptIndex = source->getIntIndex();
if (interruptIndex == kIntChipSet)
{
ELG(0, 0, "AppleRS232Serial::interruptHandler - SCC interrupt");
handleInterrupt(obj, 0, NULL, 0);
}
if (interruptIndex == kIntRxDMA)
{
ELG(0, 0, "AppleRS232Serial::interruptHandler - RX DMA interrupt");
handleDBDMARxInterrupt(obj, 0, NULL, 0);
}
if (interruptIndex == kIntTxDMA)
{
ELG(0, 0, "AppleRS232Serial::interruptHandler - TX DMA interrupt");
handleDBDMATxInterrupt(obj, 0, NULL, 0);
}
}
void AppleRS232Serial::handleInterrupt(OSObject *target, void *refCon, IOService *nub, int source)
{
AppleRS232Serial *serialPortPtr = (AppleRS232Serial *)target;
ELG(0, 0, "AppleRS232Serial::handleInterrupt");
if (serialPortPtr != NULL)
{
PPCSerialISR(target, refCon, &serialPortPtr->fPort);
}
}
void AppleRS232Serial::handleDBDMATxInterrupt(OSObject *target, void *refCon, IOService *nub, int source)
{
AppleRS232Serial *serialPortPtr = OSDynamicCast(AppleRS232Serial, target);
ELG(0, target, "AppleRS232Serial::handleDBDMATxInterrupt");
if (serialPortPtr != NULL)
{
PPCSerialTxDMAISR(NULL, NULL, &serialPortPtr->fPort);
}
}
void AppleRS232Serial::handleDBDMARxInterrupt(OSObject *target, void *refCon, IOService *nub, int source)
{
AppleRS232Serial *serialPortPtr = OSDynamicCast(AppleRS232Serial, target);
ELG(0, target, "AppleRS232Serial::handleDBDMARxInterrupt");
if (serialPortPtr != NULL)
{
#if USE_TIMER_EVENT_SOURCE_DEBUGGING
serialPortPtr->myTimer->cancelTimeout();
serialPortPtr->myTimer->setTimeoutMS( kTimerTimeout ); #endif
PPCSerialRxDMAISR(NULL, NULL, &serialPortPtr->fPort);
}
}
#if USE_TIMER_EVENT_SOURCE_DEBUGGING
void AppleRS232Serial::timeoutHandler(OSObject *owner, IOTimerEventSource *sender)
{
AppleRS232Serial *serialPortPtr;
serialPortPtr = OSDynamicCast(AppleRS232Serial, owner);
if(serialPortPtr)
{
serialPortPtr->fCounter++; HandleRxIntTimeout(serialPortPtr->fPort);
sender->setTimeoutMS(kTimerTimeout); }
}
#endif