AppleRS232Serial.h [plain text]
#ifndef __AppleRS232Serial__
#define __AppleRS232Serial__
#define LDEBUG 0 // for debugging
#define USE_ELG 1 // to event log - LDEBUG must also be set
#define LOG_DATA 0 // logs data to the IOLog - LDEBUG must also be set
#define DUMPALL 0 // Dumps all the data to the log - LOG_DATA must also be set
#define Sleep_Time 300 // 20 ms per iolog
#if LDEBUG
#if USE_ELG
#include "XTrace.h"
#define XTRACE(x, y, msg) \
do \
{ \
if (gXTrace) \
{ \
static char *__xtrace = 0; \
if (__xtrace) \
gXTrace->LogAdd(gTraceID, (UInt32)(x), (UInt32)(y), __xtrace); \
else \
__xtrace = gXTrace->LogAdd(gTraceID, (UInt32)(x), (UInt32)(y), msg, false); \
} \
} while(0)
#define ELG(x, y, msg) XTRACE(x, y, msg)
#define XTRACE2(x, y, msg) XTRACE_HELPER(gXTrace, gTraceID, x, y, "AppleRS232Serial: " msg, true)
#else
#define ELG(A,B,STRING) {IOLog( "AppleRS232Serial: %8x %8x " STRING "\n", (unsigned int)(A), (unsigned int)(B) );IOSleep(Sleep_Time);}
#endif
#if LOG_DATA
#define LogData(D, C, b) SerialLogData((UInt8)D, (UInt32)C, (char *)b)
#else
#define LogData(D, C, b)
#endif
#else
#define ELG(A,B,S)
#define LogData(D, C, b)
#undef USE_ELG
#undef LOG_DATA
#endif
#if LDEBUG && USE_ELG
#define ALERT(A,B,STRING) do { \
IOLog( "AppleRS232Serial: %8x %8x " STRING "\n", (unsigned int)(A), (unsigned int)(B) );\
ELG(A,B,STRING);\
} while(0)
#else
#define ALERT(A,B,STRING) IOLog( "AppleRS232Serial: %8x %8x " STRING "\n", (unsigned int)(A), (unsigned int)(B) )
#endif
#define getDebugFlags() (getDebugFlagsTable(getPropertyTable()))
#include <IOKit/IOLib.h>
#include <IOKit/IOService.h>
#include <IOKit/IOTimerEventSource.h>
#include <IOKit/IOWorkLoop.h>
#include <IOKit/IOCommandGate.h>
#include <IOKit/IOConditionLock.h>
#include <IOKit/IOInterruptEventSource.h>
#include <IOKit/platform/AppleMacIODevice.h>
#include <IOKit/serial/IOSerialDriverSync.h>
#include <IOKit/serial/IORS232SerialStreamSync.h>
#include <IOKit/IOWorkLoop.h>
#include <IOKit/IOInterruptEventSource.h>
#include <IOKit/IOFilterInterruptEventSource.h>
#include <IOKit/IOBufferMemoryDescriptor.h>
#include <IOKit/ppc/IODBDMA.h>
#include "SccQueue.h"
#include "Z85C30.h"
enum
{
kSerialOut = 0, kSerialIn = 1,
kSerialOther = 2
};
enum
{
R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15
};
#define USE_FILTER_EVENT_SOURCES 0
#define BUFFER_SIZE_DEFAULT (16*1024) // tx and rx queues are always this big
#define SPECIAL_SHIFT (5)
#define SPECIAL_MASK ((1<<SPECIAL_SHIFT) - 1)
#define STATE_ALL (PD_RS232_S_MASK | PD_S_MASK )
#define FLOW_RX_AUTO (PD_RS232_A_RFR | PD_RS232_A_DTR | PD_RS232_A_RXO )
#define FLOW_TX_AUTO (PD_RS232_A_CTS | PD_RS232_A_DSR | PD_RS232_A_TXO | PD_RS232_A_DCD )
#define CAN_BE_AUTO (FLOW_RX_AUTO | FLOW_TX_AUTO )
#define CAN_NOTIFY (PD_RS232_N_MASK )
#define EXTERNAL_MASK (PD_S_MASK | (PD_RS232_S_MASK & ~PD_RS232_S_LOOP) )
#define INTERNAL_DELAY (PD_RS232_S_LOOP )
#define DEFAULT_AUTO (PD_RS232_A_DTR | PD_RS232_A_RFR | PD_RS232_A_CTS | PD_RS232_A_DSR )
#define DEFAULT_NOTIFY (0x00 )
#define DEFAULT_STATE (PD_S_TX_ENABLE | PD_S_RX_ENABLE | PD_RS232_A_TXO | PD_RS232_A_RXO )
#define IDLE_XO 0
#define NEEDS_XOFF 1
#define SENT_XOFF -1
#define NEEDS_XON 2
#define SENT_XON -2
#define CONTINUE_SEND 1
#define PAUSE_SEND 2
typedef enum InterruptTypes
{
kTxInterrupts = 4, kRxInterrupts = 5,
kSccInterrupts = 6, } InterruptTypes;
#define channelControlOffsetRISC 0x000
enum InterruptAssignments
{
kIntChipSet = 0,
kIntTxDMA,
kIntRxDMA
};
enum ParityType
{
NoParity = 0,
OddParity,
EvenParity
};
enum SerialPortSelector
{
serialPortA = 0,
serialPortB = 1
};
#define MIN_BAUD (50 << 1)
#define kDefaultBaudRate 9600
#define kMaxBaudRate 230400
typedef struct SerialDBDMAStatusInfo
{
IODBDMAChannelRegisters *dmaBase; IODBDMADescriptor *dmaChannelCommandArea; IODBDMADescriptor *dmaChannelCommandAreaPhysical; UInt32 dmaNumberOfDescriptors; UInt8 *dmaTransferBuffer; UInt32 dmaTransferSize; IOBufferMemoryDescriptor *dmaTransferBufferMDP; } SerialDBDMAStatusInfo;
typedef struct BufferMarks { UInt32 BufferSize; UInt32 HighWater; UInt32 LowWater; } BufferMarks;
enum { kRxDBDMACmd_First_Read = 0, kRxDBDMACmd_Main_Read, kRxDBDMACmd_Stop, kNumberOfRxDBDMACommands,
kTxDBDMACmd_Write = 0, kTxDBDMACmd_Stop,
kNumberOfTxDBDMACommands
};
enum { kRxDBDMABufferSize = 4096, kTxDBDMABufferSize = 4096 };
class AppleRS232Serial;
typedef struct
{
UInt32 State;
UInt32 WatchStateMask;
AppleRS232Serial *RS232;
CirQueue RX;
CirQueue TX;
BufferMarks RXStats;
BufferMarks TXStats;
UInt32 CharLength; UInt32 StopBits; UInt32 TX_Parity;
UInt32 RX_Parity;
UInt32 BaudRate; bool MinLatency;
UInt8 XONchar; UInt8 XOFFchar; UInt32 SWspecial[(0x100)>>SPECIAL_SHIFT]; UInt32 FlowControl; UInt32 FlowControlState; bool DCDState;
bool CTSState;
int RXOstate; int TXOstate; bool xOffSent; bool DTRAsserted; bool RTSAsserted; bool aboveRxHighWater;
bool BreakState;
mach_timespec DataLatInterval;
mach_timespec CharLatInterval;
bool AreTransmitting;
UInt8 baudRateGeneratorLo;
UInt8 baudRateGeneratorHi;
UInt32 rtxcFrequency;
UInt8 lastWR[kNumSCCWR];
IOVirtualAddress ChipBaseAddress; IOPhysicalAddress ChipBaseAddressPhysical; IOVirtualAddress ControlRegister; SerialPortSelector whichPort;
IOBufferMemoryDescriptor *dmaChannelCommandAreaMDP; SerialDBDMAStatusInfo TxDBDMAChannel; SerialDBDMAStatusInfo rxDBDMAChannels[2]; int activeRxChannelIndex;
bool lastCTSState; UInt32 lastCTSTime;
UInt32 ctsTransitionCount;
IOTimerEventSource *rxTimer;
} PortInfo_t, SccChannel;
static inline UInt32 tval2long(mach_timespec val)
{
return ((val.tv_sec *NSEC_PER_SEC) + val.tv_nsec);
}
static inline mach_timespec long2tval(UInt32 val)
{
mach_timespec tval;
tval.tv_sec = val / NSEC_PER_SEC;
tval.tv_nsec = val % NSEC_PER_SEC;
return tval;
}
#include "SccChip.h"
#if LOG_DATA
UInt8 Asciify(UInt8 i);
void SerialLogData(UInt8 Dir, UInt32 Count, char *buf);
#endif
class AppleRS232Serial : public IOSerialDriverSync
{
OSDeclareDefaultStructors(AppleRS232Serial)
protected:
bool portOpened;
AbsoluteTime startingTime;
public:
IOWorkLoop *fWorkLoop; IOCommandGate *fCommandGate;
PortInfo_t fPort;
IOService *fProvider;
thread_call_t fdmaStartTransmissionThread;
thread_call_t dmaRxHandleCurrentPositionThread;
IOInterruptEventSource *sccInterruptSource;
#if USE_FILTER_EVENT_SOURCES
IOFilterInterruptEventSource *txDMAInterruptSource;
IOFilterInterruptEventSource *rxDMAInterruptSource;
#else
IOInterruptEventSource *txDMAInterruptSource;
IOInterruptEventSource *rxDMAInterruptSource;
#endif
virtual IOReturn acquirePort(bool sleep, void *refCon);
virtual IOReturn releasePort(void *refCon);
virtual UInt32 getState(void *refCon);
virtual IOReturn setState(UInt32 state, UInt32 mask, void *refCon);
virtual IOReturn watchState(UInt32 *state, UInt32 mask, void *refCon);
virtual UInt32 nextEvent(void *refCon);
virtual IOReturn executeEvent(UInt32 event, UInt32 data, void *refCon);
virtual IOReturn requestEvent(UInt32 event, UInt32 *data, void *refCon);
virtual IOReturn enqueueEvent(UInt32 event, UInt32 data, bool sleep, void *refCon);
virtual IOReturn dequeueEvent(UInt32 *event, UInt32 *data, bool sleep, void *refCon);
virtual IOReturn enqueueData(UInt8 *buffer, UInt32 size, UInt32 *count, bool sleep, void *refCon);
virtual IOReturn dequeueData(UInt8 *buffer, UInt32 size, UInt32 *count, UInt32 min, void *refCon);
virtual IOWorkLoop *getWorkLoop() const;
static IOReturn acquirePortAction(OSObject *owner, void *arg0, void *, void *, void *);
static IOReturn releasePortAction(OSObject *owner, void *, void *, void *, void *);
static IOReturn getStateAction(OSObject *owner, void *, void *, void *, void *);
static IOReturn setStateAction(OSObject *owner, void *arg0, void *arg1, void *, void *);
static IOReturn watchStateAction(OSObject *owner, void *arg0, void *arg1, void *, void *);
static IOReturn executeEventAction(OSObject *owner, void *arg0, void *arg1, void *, void *);
static IOReturn requestEventAction(OSObject *owner, void *arg0, void *arg1, void *, void *);
static IOReturn enqueueEventAction(OSObject *owner, void *arg0, void *arg1, void *, void *);
static IOReturn enqueueDataAction(OSObject *owner, void *arg0, void *arg1, void *arg2, void *arg3);
static IOReturn dequeueDataAction(OSObject *owner, void *arg0, void *arg1, void *arg2, void *arg3);
virtual IOReturn acquirePortGated(bool sleep);
virtual IOReturn releasePortGated(void);
virtual UInt32 getStateGated(void);
virtual IOReturn setStateGated(UInt32 state, UInt32 mask);
virtual IOReturn watchStateGated(UInt32 *state, UInt32 mask);
virtual IOReturn executeEventGated(UInt32 event, UInt32 data);
virtual IOReturn requestEventGated(UInt32 event, UInt32 *data);
virtual IOReturn enqueueDataGated(UInt8 *buffer, UInt32 size, UInt32 *count, bool sleep);
virtual IOReturn dequeueDataGated(UInt8 *buffer, UInt32 size, UInt32 *count, UInt32 min);
virtual bool start(IOService *provider);
virtual void stop(IOService *provider);
void shutDown();
static void interruptOccurred(OSObject *obj, IOInterruptEventSource *src, int count);
bool createSerialStream(IOService *provider);
static bool allocateRingBuffer(CirQueue *Queue, size_t BufferSize, IOWorkLoop *workloop);
static void freeRingBuffer(CirQueue *Queue);
bool initializePort(PortInfo_t *port);
static void setStructureDefaults(PortInfo_t *port);
void CheckQueues(PortInfo_t *port);
static void handleInterrupt(OSObject *target, void *refCon, IOService *nub, int source);
static void handleDBDMATxInterrupt(OSObject *target, void *refCon, IOService *nub, int source);
static void handleDBDMARxInterrupt(OSObject *target, void *refCon, IOService *nub, int source);
static void timeoutHandler(OSObject *owner, IOTimerEventSource *sender);
static bool interruptFilter(OSObject *owner, IOFilterInterruptEventSource *source);
static void interruptHandler(OSObject *owner, IOInterruptEventSource *source, int count);
bool initForPM(IOService *policyMaker);
IOReturn setPowerState(unsigned long powerStateOrdinal, IOService *whatDevice);
unsigned long powerStateForDomainState(IOPMPowerFlags domainState );
unsigned long maxCapabilityForDomainState(IOPMPowerFlags domainState);
unsigned long initialPowerStateForDomainState(IOPMPowerFlags domainState);
static void handleSetPowerState(thread_call_param_t param0, thread_call_param_t param1);
static IOReturn setPowerStateGated(OSObject *owner, void *arg0, void *arg1, void *arg2, void *arg3);
thread_call_t fPowerThreadCall;
bool fWaitForGatedCmd;
unsigned int fCurrentPowerState;
};
#endif