#ifndef PPC_Serial_Port_h
#define PPC_Serial_Port_h
#include <IOKit/IOLib.h>
#include <IOKit/IOService.h>
#include <IOKit/IOTimerEventSource.h>
#include <IOKit/IOWorkLoop.h>
#include <IOKit/IOConditionLock.h>
#include <IOKit/IOInterruptEventSource.h>
#include <IOKit/platform/AppleMacIODevice.h>
#include <IOKit/serial/IOSerialDriverSync.h>
#include <IOKit/IOWorkLoop.h>
#include <IOKit/IOInterruptEventSource.h>
#include <IOKit/IOFilterInterruptEventSource.h>
#include <IOKit/IOBufferMemoryDescriptor.h>
#include "SccTypes.h"
#include "HardwareDefs.h"
#include "SccQueuePrimatives.h"
#define DCPFunction_ParseData 1
#define DCPFunction_SetDCD 2
#define DCPFunction_QuitDCP 3
#define kOff 0
#define kOn 1
#define USE_WORK_LOOPS 1
#define USE_FILTER_EVENT_SOURCES 0
#define BIGGEST_EVENT 3
#define BUFFER_SIZE_MINIMUM (BIGGEST_EVENT*6)
#define BUFFER_SIZE_DEFAULT (16*1024)
#define BUFFER_SIZE_MAXIMUM (256<<10)
#define TX_BUFFER_SIZE_KEY "TX Buffer Size"
#define RX_BUFFER_SIZE_KEY "RX Buffer Size"
#define CHIP_TYPE_KEY "Chip Type"
#define INSTANCE_KEY "Instance"
#define CHIP_CLOCK_KEY "Chip Clock"
#define CHIP_CLOCK_DEFAULT (1843200l)
#define HEART_BEAT_KEY "Heart Beat Interval"
#define HEART_BEAT_DEFAULT (11000l)
#define MSR_INTERRUPT_KEY "Enable MSR Interrupts"
#define BUS_TYPE_KEY "Bus Type"
#define BUS_EISA_VAL "EISA"
#define BUS_PCMCIA_VAL "PCMCIA"
#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 UInt32 CalloutTime;
#define calloutEntryAllocate thread_call_allocate
#define calloutEntryRemove thread_call_cancel
#define calloutEntryFree thread_call_free
#define calloutEntryDispatch thread_call_enter
#define calloutEntryDispatchDelayed thread_call_enter_delayed
#define kX1UserClockMode 0x00 // for MIDI devices
#define kX16UserClockMode 0x0b
#define kX32UserClockMode 0x19
#define kX64UserClockMode 0x32
#include <IOKit/ppc/IODBDMA.h>
#define MAX_BLOCK_SIZE PAGE_SIZE
#define kDCPModem 0x0a
class DCPModemSupport : public IOService
{
OSDeclareDefaultStructors( DCPModemSupport );
private:
UInt32 gDCPBufferSize;
void * userClientPtr;
public:
virtual bool start ( IOService *provider );
virtual void stop ( IOService *provider );
virtual IOService* probe ( IOService *provider, SInt32 *pScore );
virtual IOReturn callPlatformFunction ( const OSSymbol * functionName,
bool waitForFunction,
void *param1, void *param2,
void *param3, void *param4 );
virtual void setUserClientPtr (void * ptr);
virtual void setDCPBufferSize (UInt32 size);
virtual bool callDCPModemSupportFunctions (UInt32 functionIndex, UInt8 data, bool * checkByte, bool * addByte);
};
typedef struct SerialDBDMAStatusInfo
{
IODBDMAChannelRegisters *dmaBase;
IODBDMAChannelRegisters *dmaChannelAddress;
IODBDMADescriptor *dmaChannelCommandArea;
UInt32 dmaNumberOfDescriptors;
IOBufferMemoryDescriptor *dmaChannelCommandAreaMDP;
UInt8 *dmaTransferBuffer;
UInt32 dmaTransferSize;
IOBufferMemoryDescriptor *dmaTransferBufferMDP;
UInt32 lastPosition;
} SerialDBDMAStatusInfo;
typedef struct {
UInt32 ints;
UInt32 txInts;
UInt32 rxInts;
UInt32 mdmInts;
UInt32 txChars;
UInt32 rxChars;
} Stats_t;
typedef struct BufferMarks {
UInt32 BufferSize;
UInt32 HighWater;
UInt32 LowWater;
bool OverRun;
} BufferMarks;
typedef struct {
UInt32 Instance;
unsigned const char *PortName;
UInt32 State;
UInt32 WatchStateMask;
IOLock * WatchLock;
IORecursiveLock *serialRequestLock;
CirQueue RX;
CirQueue TX;
BufferMarks RXStats;
BufferMarks TXStats;
IOLock *IODBDMARxLock;
IOLock *IODBDMATrLock;
IOLock *SCCAccessLock;
UInt32 Base;
UInt32 CharLength;
UInt32 StopBits;
UInt32 TX_Parity;
UInt32 RX_Parity;
UInt32 BreakLength;
UInt32 BaudRate;
unsigned short DLRimage;
UInt8 LCRimage;
UInt8 FCRimage;
UInt8 IERmask;
UInt8 RBRmask;
UInt32 MasterClock;
bool MinLatency;
bool WaitingForTXIdle;
UInt8 XONchar;
UInt8 XOFFchar;
UInt32 SWspecial[(0x100)>>SPECIAL_SHIFT];
UInt32 FlowControl; UInt32 FlowControlState;
bool DCDState;
bool CTSState;
int RXOstate;
int TXOstate;
UInt8 xOffSent;
UInt32 GlobalRecvChars;
UInt32 OverRunChars;
IOThread FrameTOEntry;
IOThread DataLatTOEntry;
IOThread DelayTOEntry;
IOThread HeartBeatTOEntry;
mach_timespec FrameInterval;
mach_timespec DataLatInterval;
mach_timespec CharLatInterval;
mach_timespec HeartBeatInterval;
Stats_t Stats;
bool AreTransmitting;
bool GotTXInterrupt;
bool baudRateGeneratorEnable;
UInt8 baudRateGeneratorLo;
UInt8 baudRateGeneratorHi;
UInt32 rtxcFrequency;
UInt8 lastWR[ kNumSCCWR ];
UInt8 *ControlRegister;
UInt8 *DataRegister;
IOPhysicalAddress ChipBaseAddress;
UInt32 ConfigWriteRegister;
SerialPortSelector whichPort;
IOPhysicalAddress TxDMABase;
UInt32 TxDMALength;
IOPhysicalAddress RxDMABase;
UInt32 RxDMALength;
UInt8 InterruptNumbers[MaxInterrupts];
UInt8 ourReceiveBits;
UInt8 ourTransmitBits;
UInt8 ourClockSource;
bool haveQueuedRxSIH;
bool haveQueuedTxSIH;
SerialDBDMAStatusInfo TxDBDMAChannel;
SerialDBDMAStatusInfo RxDBDMAChannel;
bool DTRAsserted;
bool aboveRxHighWater;
bool lastCTSState;
UInt32 lastCTSTime;
UInt32 ctsTransitionCount;
IOTimerEventSource* rxTimer;
bool gDCPUserClientSet;
bool gDCPModemFound;
DCPModemSupport *DCPModemSupportPtr;
} PortInfo_t, SccChannel;
extern vm_map_t kernel_map;
void SCC_TRACEMSG(char *msg);
UInt32 SCC_GetSystemTime(void);
static inline UInt32 intToBool(long inIntVal )
{
return inIntVal ? true : false;
}
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;
}
typedef void (*SCCCarrierHack)(OSObject *target, bool carrier);
class AppleSCCSerial : public IOSerialDriverSync
{
OSDeclareDefaultStructors(AppleSCCSerial)
public:
IOWorkLoop* myWorkLoop; IOTimerEventSource* myTimer; UInt32 counter;
PortInfo_t Port;
AppleMacIODevice *fProvider;
SCCCarrierHack modemDCDStateChangeCallback;
thread_call_t fPollingThread;
OSObject *fModemObject;
SInt32 fCarrierHackCount;
#if USE_WORK_LOOPS
IOInterruptEventSource* sccInterruptSource;
#if USE_FILTER_EVENT_SOURCES
IOFilterInterruptEventSource* txDMAInterruptSource;
IOFilterInterruptEventSource* rxDMAInterruptSource;
#else
IOInterruptEventSource* txDMAInterruptSource;
IOInterruptEventSource* rxDMAInterruptSource;
#endif
#endif
SccChannel *portPtr() {return &Port;}
virtual IOReturn acquirePort(bool sleep, void *refCon);
virtual IOReturn releasePort(void *refCon);
virtual IOReturn setState(UInt32 state, UInt32 mask, void *refCon);
UInt32 getState(void *refCon);
virtual IOReturn watchState(UInt32 *state, UInt32 mask, void *refCon);
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 bool start(IOService *provider);
virtual void stop(IOService *provider);
virtual void setPortName(IOService *provider);
static void interruptOccurred(OSObject *obj,
IOInterruptEventSource *src, int count);
bool createSerialStream();
static void deactivatePort(PortInfo_t *port);
static IOReturn activatePort(PortInfo_t *port);
static bool allocateRingBuffer(CirQueue *Queue, size_t BufferSize);
static void freeRingBuffer(CirQueue *Queue);
static void SetStructureDefaults(PortInfo_t *port, bool Init);
static IOReturn watchState(PortInfo_t *port, UInt32 *state, UInt32 mask);
static void changeState(PortInfo_t *port, UInt32 state, UInt32 mask);
static IOReturn executeEvent(PortInfo_t *port, UInt32 event,UInt32 data, UInt32 *state, UInt32 *delta);
static UInt32 readPortState(PortInfo_t *port);
static void CheckQueues(PortInfo_t *port);
static void frameTOHandler(PortInfo_t *port);
static void dataLatTOHandler(PortInfo_t *port);
static void delayTOHandler(PortInfo_t *port);
static void heartBeatTOHandler(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);
void setCarrierHack(OSObject *target, SCCCarrierHack action);
static void callCarrierhack(thread_call_param_t whichDevice, thread_call_param_t carrier);
static bool NonSCCModem();
static bool LookForInternalModem(UInt8 modemID);
};
#endif