Remove gdb-4.17.
This commit is contained in:
parent
e2ba73e2b5
commit
2a57f8214b
|
@ -1,42 +0,0 @@
|
|||
description "GDB debugger stub"
|
||||
version 1,2
|
||||
debug
|
||||
module clib
|
||||
screenname "System Console"
|
||||
input gdbserve.O
|
||||
output gdbserve.nlm
|
||||
start _Prelude
|
||||
exit _Stop
|
||||
import
|
||||
AllocateResourceTag
|
||||
ConsolePrintf
|
||||
GetCurrentScreen
|
||||
GetNLMHandle
|
||||
GetThreadID
|
||||
KillMe
|
||||
LoadModule
|
||||
ReadByteAltDebugger
|
||||
RegisterDebuggerRTag
|
||||
ResumeThread
|
||||
SuspendThread
|
||||
UnRegisterDebugger
|
||||
WriteByteAltDebugger
|
||||
_GetCLibNLMLibHandle
|
||||
_NWRegisterNLMLibraryUser
|
||||
_SetupArgv
|
||||
_StartNLM
|
||||
_TerminateNLM
|
||||
__GetScreenID
|
||||
__get_errno_ptr
|
||||
exit
|
||||
fprintf
|
||||
getcmd
|
||||
memcmp
|
||||
memcpy
|
||||
memset
|
||||
sprintf
|
||||
strcmp
|
||||
strcpy
|
||||
strlen
|
||||
strnicmp
|
||||
strtol
|
|
@ -1,108 +0,0 @@
|
|||
#include <dfs.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
#include <conio.h>
|
||||
#include <advanced.h>
|
||||
#include <debugapi.h>
|
||||
#include <process.h>
|
||||
#include <errno.h>
|
||||
#include "i386.h"
|
||||
|
||||
extern char *mem2hex (void *mem, char *buf, int count, int may_fault);
|
||||
extern char *hex2mem (char *buf, void *mem, int count, int may_fault);
|
||||
extern int computeSignal (int exceptionVector);
|
||||
|
||||
void
|
||||
flush_i_cache()
|
||||
{
|
||||
}
|
||||
|
||||
/* Get the registers out of the frame information. */
|
||||
|
||||
void
|
||||
frame_to_registers (frame, regs)
|
||||
struct StackFrame *frame;
|
||||
char *regs;
|
||||
{
|
||||
/* Copy EAX -> EDI */
|
||||
mem2hex (&frame->ExceptionEAX, ®s[0 * 4 * 2], 4 * 8, 0);
|
||||
|
||||
/* Copy EIP & PS */
|
||||
mem2hex (&frame->ExceptionPC, ®s[8 * 4 * 2], 4 * 2, 0);
|
||||
|
||||
/* Copy CS, SS, DS */
|
||||
mem2hex (&frame->ExceptionCS, ®s[10 * 4 * 2], 4 * 3, 0);
|
||||
|
||||
/* Copy ES */
|
||||
mem2hex (&frame->ExceptionES, ®s[13 * 4 * 2], 4 * 1, 0);
|
||||
|
||||
/* Copy FS & GS */
|
||||
mem2hex (&frame->ExceptionFS, ®s[14 * 4 * 2], 4 * 2, 0);
|
||||
}
|
||||
|
||||
/* Put the registers back into the frame information. */
|
||||
|
||||
void
|
||||
registers_to_frame (regs, frame)
|
||||
char *regs;
|
||||
struct StackFrame *frame;
|
||||
{
|
||||
/* Copy EAX -> EDI */
|
||||
hex2mem (®s[0 * 4 * 2], &frame->ExceptionEAX, 4 * 8, 0);
|
||||
|
||||
/* Copy EIP & PS */
|
||||
hex2mem (®s[8 * 4 * 2], &frame->ExceptionPC, 4 * 2, 0);
|
||||
|
||||
/* Copy CS, SS, DS */
|
||||
hex2mem (®s[10 * 4 * 2], &frame->ExceptionCS, 4 * 3, 0);
|
||||
|
||||
/* Copy ES */
|
||||
hex2mem (®s[13 * 4 * 2], &frame->ExceptionES, 4 * 1, 0);
|
||||
|
||||
/* Copy FS & GS */
|
||||
hex2mem (®s[14 * 4 * 2], &frame->ExceptionFS, 4 * 2, 0);
|
||||
}
|
||||
|
||||
void
|
||||
set_step_traps (frame)
|
||||
struct StackFrame *frame;
|
||||
{
|
||||
frame->ExceptionSystemFlags |= 0x100;
|
||||
}
|
||||
|
||||
void
|
||||
clear_step_traps (frame)
|
||||
struct StackFrame *frame;
|
||||
{
|
||||
frame->ExceptionSystemFlags &= ~0x100;
|
||||
}
|
||||
|
||||
void
|
||||
do_status (ptr, frame)
|
||||
char *ptr;
|
||||
struct StackFrame *frame;
|
||||
{
|
||||
int sigval;
|
||||
|
||||
sigval = computeSignal (frame->ExceptionNumber);
|
||||
|
||||
sprintf (ptr, "T%02x", sigval);
|
||||
ptr += 3;
|
||||
|
||||
sprintf (ptr, "%02x:", PC_REGNUM);
|
||||
ptr = mem2hex (&frame->ExceptionPC, ptr + 3, 4, 0);
|
||||
*ptr++ = ';';
|
||||
|
||||
sprintf (ptr, "%02x:", SP_REGNUM);
|
||||
ptr = mem2hex (&frame->ExceptionESP, ptr + 3, 4, 0);
|
||||
*ptr++ = ';';
|
||||
|
||||
sprintf (ptr, "%02x:", FP_REGNUM);
|
||||
ptr = mem2hex (&frame->ExceptionEBP, ptr + 3, 4, 0);
|
||||
*ptr++ = ';';
|
||||
|
||||
*ptr = '\000';
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
/* Register values. All of these values *MUST* agree with tm.h */
|
||||
#define SP_REGNUM 4 /* Contains address of top of stack */
|
||||
#define PC_REGNUM 8 /* Contains program counter */
|
||||
#define FP_REGNUM 5 /* Virtual frame pointer */
|
||||
#define NUM_REGS 16 /* Number of machine registers */
|
||||
#define REGISTER_BYTES (NUM_REGS * 4) /* Total size of registers array */
|
||||
|
||||
#define ExceptionPC ExceptionEIP
|
||||
#define DECR_PC_AFTER_BREAK 1 /* int 3 leaves PC pointing after insn */
|
||||
#define BREAKPOINT {0xcc}
|
||||
#define BREAKPOINT_SIZE (sizeof breakpoint_insn)
|
||||
|
||||
#define StackFrame T_TSS_StackFrame
|
|
@ -1,257 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nwtypes.h>
|
||||
#include <nwdfs.h>
|
||||
#include <nwconio.h>
|
||||
#include <nwadv.h>
|
||||
#include <nwdbgapi.h>
|
||||
#include <nwthread.h>
|
||||
#include "ppc.h"
|
||||
|
||||
extern char *mem2hex (void *mem, char *buf, int count, int may_fault);
|
||||
extern char *hex2mem (char *buf, void *mem, int count, int may_fault);
|
||||
extern int computeSignal (int exceptionVector);
|
||||
|
||||
void
|
||||
flush_i_cache (void)
|
||||
{
|
||||
}
|
||||
|
||||
/* Get the registers out of the frame information. */
|
||||
|
||||
void
|
||||
frame_to_registers (frame, regs)
|
||||
struct StackFrame *frame;
|
||||
char *regs;
|
||||
{
|
||||
mem2hex (&frame->ExceptionState.CsavedRegs, ®s[GP0_REGNUM * 4 * 2], 4 * 32, 0);
|
||||
|
||||
mem2hex (&frame->ExceptionState.CSavedFPRegs, ®s[FP0_REGNUM * 4 * 2], 4 * 32, 0);
|
||||
|
||||
mem2hex (&frame->ExceptionPC, ®s[PC_REGNUM * 4 * 2], 4 * 1, 0);
|
||||
|
||||
mem2hex (&frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedSRR1, ®s[CR_REGNUM * 4 * 2], 4 * 1, 0);
|
||||
mem2hex (&frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedLR, ®s[LR_REGNUM * 4 * 2], 4 * 1, 0);
|
||||
mem2hex (&frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedCTR, ®s[CTR_REGNUM * 4 * 2], 4 * 1, 0);
|
||||
mem2hex (&frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedXER, ®s[XER_REGNUM * 4 * 2], 4 * 1, 0);
|
||||
mem2hex (&frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedMQ, ®s[MQ_REGNUM * 4 * 2], 4 * 1, 0);
|
||||
}
|
||||
|
||||
/* Put the registers back into the frame information. */
|
||||
|
||||
void
|
||||
registers_to_frame (regs, frame)
|
||||
char *regs;
|
||||
struct StackFrame *frame;
|
||||
{
|
||||
hex2mem (®s[GP0_REGNUM * 4 * 2], &frame->ExceptionState.CsavedRegs, 4 * 32, 0);
|
||||
|
||||
hex2mem (®s[FP0_REGNUM * 4 * 2], &frame->ExceptionState.CSavedFPRegs, 4 * 32, 0);
|
||||
|
||||
hex2mem (®s[PC_REGNUM * 4 * 2], &frame->ExceptionPC, 4 * 1, 0);
|
||||
|
||||
hex2mem (®s[CR_REGNUM * 4 * 2], &frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedSRR1, 4 * 1, 0);
|
||||
hex2mem (®s[LR_REGNUM * 4 * 2], &frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedLR, 4 * 1, 0);
|
||||
hex2mem (®s[CTR_REGNUM * 4 * 2], &frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedCTR, 4 * 1, 0);
|
||||
hex2mem (®s[XER_REGNUM * 4 * 2], &frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedXER, 4 * 1, 0);
|
||||
hex2mem (®s[MQ_REGNUM * 4 * 2], &frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedMQ, 4 * 1, 0);
|
||||
}
|
||||
|
||||
|
||||
extern volatile int mem_err;
|
||||
|
||||
#ifdef ALTERNATE_MEM_FUNCS
|
||||
extern int ReadByteAltDebugger (char* addr, char *theByte);
|
||||
extern int WriteByteAltDebugger (char* addr, char theByte);
|
||||
int
|
||||
get_char (addr)
|
||||
char *addr;
|
||||
{
|
||||
char c;
|
||||
|
||||
if (!ReadByteAltDebugger (addr, &c))
|
||||
mem_err = 1;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void
|
||||
set_char (addr, val)
|
||||
char *addr;
|
||||
int val;
|
||||
{
|
||||
if (!WriteByteAltDebugger (addr, val))
|
||||
mem_err = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
mem_write (dst, src, len)
|
||||
char *dst, *src;
|
||||
int len;
|
||||
{
|
||||
while (len-- && !mem_err)
|
||||
set_char (dst++, *src++);
|
||||
|
||||
return mem_err;
|
||||
}
|
||||
|
||||
union inst
|
||||
{
|
||||
LONG l;
|
||||
|
||||
struct
|
||||
{
|
||||
union
|
||||
{
|
||||
struct /* Unconditional branch */
|
||||
{
|
||||
unsigned opcode : 6; /* 18 */
|
||||
signed li : 24;
|
||||
unsigned aa : 1;
|
||||
unsigned lk : 1;
|
||||
} b;
|
||||
struct /* Conditional branch */
|
||||
{
|
||||
unsigned opcode : 6; /* 16 */
|
||||
unsigned bo : 5;
|
||||
unsigned bi : 5;
|
||||
signed bd : 14;
|
||||
unsigned aa : 1;
|
||||
unsigned lk : 1;
|
||||
} bc;
|
||||
struct /* Conditional branch to ctr or lr reg */
|
||||
{
|
||||
unsigned opcode : 6; /* 19 */
|
||||
unsigned bo : 5;
|
||||
unsigned bi : 5;
|
||||
unsigned type : 15; /* 528 = ctr, 16 = lr */
|
||||
unsigned lk : 1;
|
||||
} bclr;
|
||||
} variant;
|
||||
} inst;
|
||||
};
|
||||
|
||||
static LONG saved_inst;
|
||||
static LONG *saved_inst_pc = 0;
|
||||
static LONG saved_target_inst;
|
||||
static LONG *saved_target_inst_pc = 0;
|
||||
|
||||
void
|
||||
set_step_traps (frame)
|
||||
struct StackFrame *frame;
|
||||
{
|
||||
union inst inst;
|
||||
LONG *target;
|
||||
int opcode;
|
||||
int ra, rb;
|
||||
LONG *pc = (LONG *)frame->ExceptionPC;
|
||||
|
||||
inst.l = *pc++;
|
||||
|
||||
opcode = inst.inst.variant.b.opcode;
|
||||
|
||||
target = pc;
|
||||
|
||||
switch (opcode)
|
||||
{
|
||||
case 18: /* Unconditional branch */
|
||||
|
||||
if (inst.inst.variant.b.aa) /* Absolute? */
|
||||
target = 0;
|
||||
target += inst.inst.variant.b.li;
|
||||
|
||||
break;
|
||||
case 16: /* Conditional branch */
|
||||
|
||||
if (!inst.inst.variant.bc.aa) /* Absolute? */
|
||||
target = 0;
|
||||
target += inst.inst.variant.bc.bd;
|
||||
|
||||
break;
|
||||
case 19: /* Cond. branch via ctr or lr reg */
|
||||
switch (inst.inst.variant.bclr.type)
|
||||
{
|
||||
case 528: /* ctr */
|
||||
target = (LONG *)frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedCTR;
|
||||
break;
|
||||
case 16: /* lr */
|
||||
target = (LONG *)frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedLR;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
saved_inst = *pc;
|
||||
mem_write (pc, breakpoint_insn, BREAKPOINT_SIZE);
|
||||
saved_inst_pc = pc;
|
||||
|
||||
if (target != pc)
|
||||
{
|
||||
saved_target_inst = *target;
|
||||
mem_write (target, breakpoint_insn, BREAKPOINT_SIZE);
|
||||
saved_target_inst_pc = target;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove step breakpoints. Returns non-zero if pc was at a step breakpoint,
|
||||
zero otherwise. This routine works even if there were no step breakpoints
|
||||
set. */
|
||||
|
||||
int
|
||||
clear_step_traps (frame)
|
||||
struct StackFrame *frame;
|
||||
{
|
||||
int retcode;
|
||||
LONG *pc = (LONG *)frame->ExceptionPC;
|
||||
|
||||
if (saved_inst_pc == pc || saved_target_inst_pc == pc)
|
||||
retcode = 1;
|
||||
else
|
||||
retcode = 0;
|
||||
|
||||
if (saved_inst_pc)
|
||||
{
|
||||
mem_write (saved_inst_pc, saved_inst, BREAKPOINT_SIZE);
|
||||
saved_inst_pc = 0;
|
||||
}
|
||||
|
||||
if (saved_target_inst_pc)
|
||||
{
|
||||
mem_write (saved_target_inst_pc, saved_target_inst, BREAKPOINT_SIZE);
|
||||
saved_target_inst_pc = 0;
|
||||
}
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
void
|
||||
do_status (ptr, frame)
|
||||
char *ptr;
|
||||
struct StackFrame *frame;
|
||||
{
|
||||
int sigval;
|
||||
|
||||
sigval = computeSignal (frame->ExceptionNumber);
|
||||
|
||||
sprintf (ptr, "T%02x", sigval);
|
||||
ptr += 3;
|
||||
|
||||
sprintf (ptr, "%02x:", PC_REGNUM);
|
||||
ptr = mem2hex (&frame->ExceptionPC, ptr + 3, 4, 0);
|
||||
*ptr++ = ';';
|
||||
|
||||
sprintf (ptr, "%02x:", SP_REGNUM);
|
||||
ptr = mem2hex (&frame->ExceptionState.CsavedRegs[SP_REGNUM], ptr + 3, 4, 0);
|
||||
*ptr++ = ';';
|
||||
|
||||
sprintf (ptr, "%02x:", LR_REGNUM);
|
||||
ptr = mem2hex (&frame->ExceptionState.CsavedRegs[LR_REGNUM], ptr + 3, 4, 0);
|
||||
*ptr++ = ';';
|
||||
|
||||
*ptr = '\000';
|
||||
}
|
|
@ -1,165 +0,0 @@
|
|||
typedef long Long;
|
||||
|
||||
/* The following enum is used to access the special registers in
|
||||
the saved machine state. */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
kDc_SavedPC = 0, /* really SRR0 */
|
||||
kDc_SavedMSR = 1, /* really SRR1 */
|
||||
kDc_SavedCR = 2,
|
||||
kDc_SavedLR = 3,
|
||||
kDc_SavedDSISR = 4,
|
||||
kDc_SavedDAR = 5,
|
||||
kDc_SavedXER = 6,
|
||||
kDc_SavedCTR = 7,
|
||||
kDc_SavedSDR1 = 8,
|
||||
kDc_SavedRTCU = 9,
|
||||
kDc_SavedRTCL = 10,
|
||||
kDc_SavedDEC = 11,
|
||||
kDc_SavedSR00 = 12, /* The Segement Registers are consecutive */
|
||||
kDc_SavedSR01 = 13, /* kDc_SavedSR00 + n is supported */
|
||||
kDc_SavedSR02 = 14,
|
||||
kDc_SavedSR03 = 15,
|
||||
kDc_SavedSR04 = 16,
|
||||
kDc_SavedSR05 = 17,
|
||||
kDc_SavedSR06 = 18,
|
||||
kDc_SavedSR07 = 19,
|
||||
kDc_SavedSR08 = 20,
|
||||
kDc_SavedSR09 = 21,
|
||||
kDc_SavedSR10 = 22,
|
||||
kDc_SavedSR11 = 23,
|
||||
kDc_SavedSR12 = 24,
|
||||
kDc_SavedSR13 = 25,
|
||||
kDc_SavedSR14 = 26,
|
||||
kDc_SavedSR15 = 27,
|
||||
kDc_SavedFPSCR = 29,
|
||||
kDc_SavedMQ = 30,
|
||||
kDc_SavedBAT0U = 31,
|
||||
kDc_SavedBAT0L = 32,
|
||||
kDc_SavedBAT1U = 33,
|
||||
kDc_SavedBAT1L = 34,
|
||||
kDc_SavedBAT2U = 35,
|
||||
kDc_SavedBAT2L = 36,
|
||||
kDc_SavedBAT3U = 37,
|
||||
kDc_SavedBAT3L = 38,
|
||||
|
||||
kNumberSpecialRegisters = 39
|
||||
} Dc_SavedRegisterName;
|
||||
|
||||
/* Access to floating points is not very easy. This allows the number to be
|
||||
accessed both as a floating number and as a pair of Longs. */
|
||||
|
||||
typedef union
|
||||
{
|
||||
double asfloat; /* access the variable as a floating number */
|
||||
struct
|
||||
{
|
||||
Long high;
|
||||
Long low;
|
||||
}
|
||||
asLONG; /* access the variable as two Longs */
|
||||
} FloatingPoints;
|
||||
|
||||
/* The following is the standard record for Saving a machine state */
|
||||
|
||||
struct SavedMachineState
|
||||
{
|
||||
FloatingPoints CSavedFPRegs[32]; /* The floating point registers [0->31] */
|
||||
/* ***32bit assumption*** */
|
||||
Long CsavedRegs[32]; /* space to save the General Registers */
|
||||
/* These are saved 0->31 */
|
||||
Long CexReason;
|
||||
Long SavedDomainID;
|
||||
union
|
||||
{ /* must be 8-byte aligned, so doubleFPSCR is 8-byte aligned */
|
||||
struct
|
||||
{
|
||||
Long CsavedSRR0; /* Index 0 - The saved PC */
|
||||
Long CsavedSRR1; /* 1 saved MSR */
|
||||
Long CsavedCR; /* 2 */
|
||||
Long CsavedLR; /* 3 */
|
||||
Long CsavedDSISR; /* 4 */
|
||||
Long CsavedDAR; /* 5 */
|
||||
|
||||
Long CsavedXER; /* 6 */
|
||||
Long CsavedCTR; /* 7 */
|
||||
Long CsavedSDR1; /* 8 */
|
||||
Long CsavedRTCU; /* 9 */
|
||||
Long CsavedRTCL; /* 10 */
|
||||
Long CsavedDEC; /* 11 */
|
||||
Long CsavedSR0; /* 12 */
|
||||
Long CsavedSR1; /* 13 */
|
||||
Long CsavedSR2; /* 14 */
|
||||
Long CsavedSR3; /* 15 */
|
||||
Long CsavedSR4; /* 16 */
|
||||
Long CsavedSR5; /* 17 */
|
||||
Long CsavedSR6; /* 18 */
|
||||
Long CsavedSR7; /* 19 */
|
||||
Long CsavedSR8; /* 20 */
|
||||
Long CsavedSR9; /* 21 */
|
||||
Long CsavedSR10; /* 22 */
|
||||
Long CsavedSR11; /* 23 */
|
||||
Long CsavedSR12; /* 24 */
|
||||
Long CsavedSR13; /* 25 */
|
||||
Long CsavedSR14; /* 26 */
|
||||
Long CsavedSR15; /* 27 */
|
||||
/* CdoubleFPSCR must be double word aligned */
|
||||
Long CdoubleFPSCR; /* 28 this is the upper part of the store and has
|
||||
no meaning */
|
||||
Long CsavedFPSCR; /* 29 */
|
||||
Long CsavedMQ; /* 30 */
|
||||
Long CsavedBAT0U; /* 31 */
|
||||
Long CsavedBAT0L; /* 32 */
|
||||
Long CsavedBAT1U; /* 33 */
|
||||
Long CsavedBAT1L; /* 34 */
|
||||
Long CsavedBAT2U; /* 35 */
|
||||
Long CsavedBAT2L; /* 36 */
|
||||
Long CsavedBAT3U; /* 37 */
|
||||
Long CsavedBAT3L; /* 38 */
|
||||
}
|
||||
SpecialRegistersEnumerated;
|
||||
|
||||
Long SpecialRegistersIndexed[kNumberSpecialRegisters];
|
||||
} u;
|
||||
|
||||
Long Padding[3]; /* Needed for quad-word alignment */
|
||||
};
|
||||
|
||||
struct StackFrame
|
||||
{
|
||||
LONG *ExceptionDomainID;
|
||||
/*ProcessorStructure*/ int *ExceptionProcessorID;
|
||||
BYTE *ExceptionDescription;
|
||||
LONG ExceptionFlags;
|
||||
LONG ExceptionErrorCode;
|
||||
LONG ExceptionNumber;
|
||||
struct SavedMachineState ExceptionState;
|
||||
};
|
||||
|
||||
/* Register values. All of these values *MUST* agree with tm.h */
|
||||
#define GP0_REGNUM 0 /* GPR register 0 */
|
||||
#define SP_REGNUM 1 /* Contains address of top of stack */
|
||||
#define FP0_REGNUM 32 /* FPR (Floating point) register 0 */
|
||||
#define PC_REGNUM 64 /* Contains program counter */
|
||||
#define PS_REGNUM 65 /* Processor (or machine) status (%msr) */
|
||||
#define CR_REGNUM 66 /* Condition register */
|
||||
#define LR_REGNUM 67 /* Link register */
|
||||
#define CTR_REGNUM 68 /* Count register */
|
||||
#define XER_REGNUM 69 /* Fixed point exception registers */
|
||||
#define MQ_REGNUM 70 /* Multiply/quotient register */
|
||||
#define NUM_REGS 71 /* Number of machine registers */
|
||||
#define REGISTER_BYTES (420) /* Total size of registers array */
|
||||
|
||||
#define ExceptionPC ExceptionState.u.SpecialRegistersEnumerated.CsavedSRR0
|
||||
#define DECR_PC_AFTER_BREAK 0 /* PPCs get this right! */
|
||||
#define BREAKPOINT {0x7d, 0x82, 0x10, 0x08}
|
||||
extern unsigned char breakpoint_insn[];
|
||||
#define BREAKPOINT_SIZE 4
|
||||
|
||||
#if 0
|
||||
#define ALTERNATE_MEM_FUNCS /* We need our own get_char/set_char */
|
||||
#endif
|
||||
|
||||
extern int get_char (char *addr);
|
||||
extern void set_char (char *addr, int val);
|
|
@ -1,67 +0,0 @@
|
|||
/*===========================================================================
|
||||
= Novell Standard C Library for NetWare Loadable Modules
|
||||
=
|
||||
= Unpublished Copyright (C) 1993 by Novell, Inc. All rights reserved.
|
||||
=
|
||||
= No part of this file may be duplicated, revised, translated, localized or
|
||||
= modified in any manner or compiled, linked or uploaded or downloaded to or
|
||||
= from any computer system without the prior written consent of Novell, Inc.
|
||||
==============================================================================
|
||||
= The object produced by compiling this file is for use by the client of this
|
||||
= library and is not linked in; Prelude.Obj is therefore one of the files to
|
||||
= be distributed with CLib.NLM and its headers.
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#if defined(__netware__) && defined(__i386__)
|
||||
#define TERMINATE_BY_UNLOAD 5
|
||||
#else
|
||||
#include <nwpre.h>
|
||||
#endif
|
||||
/*#include "libhooks.h"*/
|
||||
|
||||
extern int main (int, char **);
|
||||
|
||||
static int NLMID;
|
||||
|
||||
|
||||
void _Stop( void )
|
||||
{
|
||||
_TerminateNLM(NLMID, NULL, TERMINATE_BY_UNLOAD);
|
||||
}
|
||||
|
||||
int _cstart_( void )
|
||||
{
|
||||
return _SetupArgv(main);
|
||||
}
|
||||
|
||||
int _Prelude
|
||||
(
|
||||
int NLMHandle,
|
||||
int initErrorScreenID,
|
||||
char *commandLine,
|
||||
char *loadDirectoryPath,
|
||||
int uninitializedDataLength,
|
||||
int NLMFileHandle,
|
||||
int (*readRoutineP)(),
|
||||
int customDataOffset,
|
||||
int customDataSize
|
||||
)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = _StartNLM(NLMHandle,
|
||||
initErrorScreenID,
|
||||
commandLine,
|
||||
loadDirectoryPath,
|
||||
uninitializedDataLength,
|
||||
NLMFileHandle,
|
||||
readRoutineP,
|
||||
customDataOffset,
|
||||
customDataSize,
|
||||
&NLMID,
|
||||
_cstart_);
|
||||
|
||||
return rc;
|
||||
}
|
|
@ -1,457 +0,0 @@
|
|||
/*
|
||||
* (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
|
||||
* (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
|
||||
* (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
|
||||
* (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
|
||||
* To anyone who acknowledges that this file is provided "AS IS" without
|
||||
* any express or implied warranty: permission to use, copy, modify, and
|
||||
* distribute this file for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notices and this notice appears in
|
||||
* all source code copies, and that none of the names listed above be used
|
||||
* in advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. None of these organizations
|
||||
* makes any representations about the suitability of this software for
|
||||
* any purpose.
|
||||
*/
|
||||
/*
|
||||
* Header file for thread synchrounous I/O
|
||||
*/
|
||||
|
||||
#ifndef CMA_THREAD_IO
|
||||
#define CMA_THREAD_IO
|
||||
|
||||
/*
|
||||
* INCLUDE FILES
|
||||
*/
|
||||
|
||||
#include <cma_config.h>
|
||||
#include <sys/file.h>
|
||||
#include <cma.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <cma_init.h>
|
||||
#include <cma_errors.h>
|
||||
|
||||
/*
|
||||
* CONSTANTS
|
||||
*/
|
||||
|
||||
/*
|
||||
* Define symbols which indicate whether to compile code for obsolete
|
||||
* "non-blocking mode" flags: FNDELAY and FNBLOCK. If the obsolete
|
||||
* symbols are defined, and if their replacement symbols are defined
|
||||
* and are different or if they are undefined, then define a symbol
|
||||
* that says to compile the code in; otherwise no code will be compiled
|
||||
* for these obsolete symbols.
|
||||
*/
|
||||
#ifdef FNDELAY
|
||||
# ifdef O_NDELAY
|
||||
# if O_NDELAY != FNDELAY
|
||||
# define _CMA_FNDELAY_
|
||||
# endif
|
||||
# else
|
||||
# define _CMA_FNDELAY_
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef FNBLOCK
|
||||
# ifdef O_NONBLOCK
|
||||
# if O_NONBLOCK != FNBLOCK
|
||||
# define _CMA_FNBLOCK_
|
||||
# endif
|
||||
# else
|
||||
# define _CMA_FNBLOCK_
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
extern cma_t_boolean cma_is_open(int);
|
||||
/*
|
||||
* Maximum number of files (ie, max_fd+1)
|
||||
*/
|
||||
#define cma__c_mx_file FD_SETSIZE
|
||||
|
||||
/*
|
||||
* Number of bits per file descriptor bit mask (ie number of bytes * bits/byte)
|
||||
*/
|
||||
#define cma__c_nbpm NFDBITS
|
||||
|
||||
/*
|
||||
* TYPE DEFINITIONS
|
||||
*/
|
||||
|
||||
typedef enum CMA__T_IO_TYPE {
|
||||
cma__c_io_read = 0,
|
||||
cma__c_io_write = 1,
|
||||
cma__c_io_except = 2
|
||||
} cma__t_io_type;
|
||||
#define cma__c_max_io_type 2
|
||||
|
||||
/*
|
||||
* From our local <sys/types.h>:
|
||||
*
|
||||
* typedef long fd_mask;
|
||||
*
|
||||
* typedef struct fd_set {
|
||||
* fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)];
|
||||
* } fd_set;
|
||||
*
|
||||
*/
|
||||
typedef fd_mask cma__t_mask;
|
||||
typedef fd_set cma__t_file_mask;
|
||||
|
||||
|
||||
/*
|
||||
* GLOBAL DATA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Maximum number of files (ie, max_fd+1) as determined by getdtablesize().
|
||||
*/
|
||||
extern int cma__g_mx_file;
|
||||
|
||||
/*
|
||||
* Number of submasks (ie "int" sized chunks) per file descriptor mask as
|
||||
* determined by getdtablesize().
|
||||
*/
|
||||
extern int cma__g_nspm;
|
||||
|
||||
/*
|
||||
* MACROS
|
||||
*/
|
||||
|
||||
/*
|
||||
* Define a constant for the errno value which indicates that the requested
|
||||
* operation was not performed because it would block the process.
|
||||
*/
|
||||
# define cma__is_blocking(s) \
|
||||
((s == EAGAIN) || (s == EWOULDBLOCK) || (s == EINPROGRESS) || \
|
||||
(s == EALREADY) || (s == EDEADLK))
|
||||
|
||||
/*
|
||||
* It is necessary to issue an I/O function, before calling cma__io_wait()
|
||||
* in the following cases:
|
||||
*
|
||||
* * This file descriptor has been set non-blocking by CMA
|
||||
* * This file descriptor has been set non-blocking by the user.
|
||||
*/
|
||||
|
||||
#define cma__issue_io_call(fd) \
|
||||
( (cma__g_file[fd]->non_blocking) || \
|
||||
(cma__g_file[fd]->user_fl.user_non_blocking) )
|
||||
|
||||
|
||||
#define cma__set_user_nonblocking(flags) \
|
||||
|
||||
/*
|
||||
* Determine if the file is open
|
||||
*/
|
||||
/*
|
||||
* If the file gets closed while waiting for the mutex cma__g_file[rfd]
|
||||
* gets set to null. This results in a crash if NDEBUG is set to 0
|
||||
* since cma__int_lock tries to dereference it to set the mutex ownership
|
||||
* after it gets the mutex. The following will still set the ownership
|
||||
* in cma__int_lock so we'll set it back to noone if cma__g_file is null
|
||||
* when we come back just in case it matters. It shouldn't since its no
|
||||
* longer in use but.....
|
||||
* Callers of this should recheck cma__g_file after the reservation to
|
||||
* make sure continueing makes sense.
|
||||
*/
|
||||
#define cma__fd_reserve(rfd) \
|
||||
{ \
|
||||
cma__t_int_mutex *__mutex__; \
|
||||
__mutex__ = cma__g_file[rfd]->mutex; \
|
||||
cma__int_lock (__mutex__); \
|
||||
if(cma__g_file[rfd] == (cma__t_file_obj *)cma_c_null_ptr) \
|
||||
cma__int_unlock(__mutex__); \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Unreserve a file descriptor
|
||||
*/
|
||||
#define cma__fd_unreserve(ufd) cma__int_unlock (cma__g_file[ufd]->mutex)
|
||||
|
||||
/*
|
||||
* AND together two select file descriptor masks
|
||||
*/
|
||||
#define cma__fdm_and(target,a,b) \
|
||||
{ \
|
||||
int __i__ = cma__g_nspm; \
|
||||
while (__i__--) \
|
||||
(target)->fds_bits[__i__] = \
|
||||
(a)->fds_bits[__i__] & (b)->fds_bits[__i__]; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear a bit in a select file descriptor mask
|
||||
*
|
||||
* FD_CLR(n, p) := ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
|
||||
*/
|
||||
#define cma__fdm_clr_bit(n,p) FD_CLR (n, p)
|
||||
|
||||
/*
|
||||
* Copy the contents of one file descriptor mask into another. If the
|
||||
* destination operand is null, do nothing; if the source operand is null,
|
||||
* simply zero the destination.
|
||||
*/
|
||||
#define cma__fdm_copy(src,dst,nfds) { \
|
||||
if (dst) \
|
||||
if (src) { \
|
||||
cma__t_mask *__s__ = (cma__t_mask *)(src); \
|
||||
cma__t_mask *__d__ = (cma__t_mask *)(dst); \
|
||||
int __i__; \
|
||||
for (__i__ = 0; __i__ < (nfds); __i__ += cma__c_nbpm) \
|
||||
*__d__++ = *__s__++; \
|
||||
} \
|
||||
else \
|
||||
cma__fdm_zero (dst); \
|
||||
}
|
||||
|
||||
/*
|
||||
* To increment count for each bit set in fd - mask
|
||||
*/
|
||||
#define cma__fdm_count_bits(map,count) \
|
||||
{ \
|
||||
int __i__ = cma__g_nspm; \
|
||||
while (__i__--) { \
|
||||
cma__t_mask __tm__; \
|
||||
__tm__ = (map)->fds_bits[__i__]; \
|
||||
while(__tm__) { \
|
||||
(count)++; \
|
||||
__tm__ &= ~(__tm__ & (-__tm__)); /* Assumes 2's comp */ \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
/*
|
||||
* Test if a bit is set in a select file descriptor mask
|
||||
*
|
||||
* FD_ISSET(n,p) := ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
|
||||
*/
|
||||
#define cma__fdm_is_set(n,p) FD_ISSET (n, p)
|
||||
|
||||
/*
|
||||
* OR together two select file descriptor masks
|
||||
*/
|
||||
#define cma__fdm_or(target,a,b) \
|
||||
{ \
|
||||
int __i__ = cma__g_nspm; \
|
||||
while (__i__--) \
|
||||
(target)->fds_bits[__i__] = \
|
||||
(a)->fds_bits[__i__] | (b)->fds_bits[__i__]; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a bit in a select file descriptor mask
|
||||
*
|
||||
* FD_SET(n,p) := ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
|
||||
*/
|
||||
#define cma__fdm_set_bit(n,p) FD_SET (n, p)
|
||||
|
||||
/*
|
||||
* Clear a select file descriptor mask.
|
||||
*/
|
||||
#define cma__fdm_zero(n) \
|
||||
cma__memset ((char *) n, 0, cma__g_nspm * sizeof(cma__t_mask))
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* CMA "thread-synchronous" I/O read/write operations
|
||||
*/
|
||||
|
||||
/*
|
||||
* Since all CMA "thread-synchronous" I/O (read or write) operations on
|
||||
* U*ix follow the exact same structure, the wrapper routines have been
|
||||
* condensed into a macro.
|
||||
*
|
||||
* The steps performed are as follows:
|
||||
* 1. Check that the file descriptor is a legitimate value.
|
||||
* 2. Check that the entry in the CMA file "database" which corresponds to
|
||||
* the file descriptor indicates that the "file" was "opened" by CMA.
|
||||
* 3. Reserve the file, to serialized access to files. This not only
|
||||
* simplifies things, but also defends against non-reentrancy.
|
||||
* 4. If the "file" is "set" for non-blocking I/O, check if we
|
||||
* have actually set the file non-blocking yet, and if not do so.
|
||||
* Then, issue the I/O operantion.
|
||||
* Success or failure is returned immediately, after unreserving the
|
||||
* file. If the error indicates that the operation would have caused
|
||||
* the process to block, continue to the next step.
|
||||
* 5. The I/O prolog adds this "file" to the global bit mask, which
|
||||
* represents all "files" which have threads waiting to perform I/O on
|
||||
* them, and causes the thread to block on the condition variable for
|
||||
* this "file". Periodically, a select is done on this global bit
|
||||
* mask, and the condition variables corresponding to "files" which
|
||||
* are ready for I/O are signaled, releasing those waiting threads to
|
||||
* perform their I/O.
|
||||
* 6. When the thread returns from the I/O prolog, it can (hopefully)
|
||||
* perform its operation without blocking the process.
|
||||
* 7. The I/O epilog clears the bit in the global mask and/or signals the
|
||||
* the next thread waiting for this "file", as appropriate.
|
||||
* 8. If the I/O failed, continue to loop.
|
||||
* 9. Finally, the "file" is unreserved, as we're done with it, and the
|
||||
* result of the operation is returned.
|
||||
*
|
||||
*
|
||||
* Note: currently, we believe that timeslicing which is based on the
|
||||
* virtual-time timer does not cause system calls to return EINTR.
|
||||
* Threfore, any EINTR returns are relayed directly to the caller.
|
||||
* On platforms which do not support a virtual-time timer, the code
|
||||
* should probably catch EINTR returns and restart the system call.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This macro is used for both read-type and write-type functions.
|
||||
*
|
||||
* Note: the second call to "func" may require being bracketed in a
|
||||
* cma__interrupt_disable/cma__interrupt_enable pair, but we'll
|
||||
* wait and see if this is necessary.
|
||||
*/
|
||||
#define cma__ts_func(func,fd,arglist,type,post_process) { \
|
||||
cma_t_integer __res__; \
|
||||
cma_t_boolean __done__ = cma_c_false; \
|
||||
if ((fd < 0) || (fd >= cma__g_mx_file)) return (cma__set_errno (EBADF), -1); \
|
||||
if (!cma__is_open(fd)) return (cma__set_errno (EBADF), -1); \
|
||||
cma__fd_reserve (fd); \
|
||||
if (!cma__is_open(fd)) return (cma__set_errno (EBADF), -1); \
|
||||
if (cma__issue_io_call(fd)) {\
|
||||
if ((!cma__g_file[fd]->set_non_blocking) && \
|
||||
(cma__g_file[fd]->non_blocking == cma_c_true)) \
|
||||
cma__set_nonblocking(fd); \
|
||||
cma__interrupt_disable (0); \
|
||||
TRY { \
|
||||
__res__ = func arglist; \
|
||||
} \
|
||||
CATCH_ALL { \
|
||||
cma__interrupt_enable (0); \
|
||||
cma__fd_unreserve (fd); \
|
||||
RERAISE; \
|
||||
} \
|
||||
ENDTRY \
|
||||
cma__interrupt_enable (0); \
|
||||
if ((__res__ != -1) \
|
||||
|| (!cma__is_blocking (errno)) \
|
||||
|| (cma__g_file[fd]->user_fl.user_non_blocking)) \
|
||||
__done__ = cma_c_true; \
|
||||
} \
|
||||
if (__done__) { \
|
||||
cma__fd_unreserve (fd); \
|
||||
} \
|
||||
else { \
|
||||
TRY { \
|
||||
cma__io_prolog (type, fd); \
|
||||
while (!__done__) { \
|
||||
cma__io_wait (type, fd); \
|
||||
__res__ = func arglist; \
|
||||
if ((__res__ != -1) \
|
||||
|| (!cma__is_blocking (errno)) \
|
||||
|| (cma__g_file[fd]->user_fl.user_non_blocking)) \
|
||||
__done__ = cma_c_true; \
|
||||
} \
|
||||
} \
|
||||
FINALLY { \
|
||||
cma__io_epilog (type, fd); \
|
||||
cma__fd_unreserve (fd); \
|
||||
} \
|
||||
ENDTRY \
|
||||
} \
|
||||
if (__res__ != -1) post_process; \
|
||||
return __res__; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Since most CMA "thread-synchronous" I/O ("open"-type) operations on
|
||||
* U*ix follow the exact same structure, the wrapper routines have been
|
||||
* condensed into a macro.
|
||||
*
|
||||
* The steps performed are as follows:
|
||||
* 1. Issue the open function.
|
||||
* 2. If the value returned indicates an error, return it to the caller.
|
||||
* 3. If the file descriptor returned is larger than what we think is the
|
||||
* maximum value (ie if it is too big for our database) then bugcheck.
|
||||
* 4. "Open" the "file" in the CMA file database.
|
||||
* 5. Return the file descriptor value to the caller.
|
||||
*
|
||||
* FIX-ME: for the time being, if the I/O operation returns EINTR, we
|
||||
* simply return it to the caller; eventually, we should catch this
|
||||
* and "do the right thing" (if we can figure out what that is).
|
||||
*/
|
||||
|
||||
/*
|
||||
* This macro is used for all "open"-type functions which return a single file
|
||||
* desciptor by immediate value.
|
||||
*/
|
||||
#define cma__ts_open(func,arglist,post_process) { \
|
||||
int __fd__; \
|
||||
TRY { \
|
||||
cma__int_init (); \
|
||||
cma__int_lock (cma__g_io_data_mutex); \
|
||||
__fd__ = func arglist; \
|
||||
cma__int_unlock (cma__g_io_data_mutex); \
|
||||
if (__fd__ >= 0 && __fd__ < cma__g_mx_file) \
|
||||
post_process; \
|
||||
} \
|
||||
CATCH_ALL \
|
||||
{ \
|
||||
cma__set_errno (EBADF); \
|
||||
__fd__ = -1; \
|
||||
} \
|
||||
ENDTRY \
|
||||
if (__fd__ >= cma__g_mx_file) \
|
||||
cma__bugcheck ("cma__ts_open: fd is too large"); \
|
||||
return __fd__; \
|
||||
}
|
||||
/*
|
||||
* This macro is used for all "open"-type functions which return a pair of file
|
||||
* desciptors by reference parameter.
|
||||
*/
|
||||
#define cma__ts_open2(func,fdpair,arglist,post_process) { \
|
||||
int __res__; \
|
||||
TRY { \
|
||||
cma__int_init (); \
|
||||
cma__int_lock (cma__g_io_data_mutex); \
|
||||
__res__ = func arglist; \
|
||||
cma__int_unlock (cma__g_io_data_mutex); \
|
||||
if (__res__ >= 0 && fdpair[0] < cma__g_mx_file \
|
||||
&& fdpair[1] < cma__g_mx_file) \
|
||||
post_process; \
|
||||
} \
|
||||
CATCH_ALL \
|
||||
{ \
|
||||
cma__set_errno (EBADF); \
|
||||
__res__ = -1; \
|
||||
} \
|
||||
ENDTRY \
|
||||
if ((fdpair[0] >= cma__g_mx_file) || (fdpair[1] >= cma__g_mx_file)) \
|
||||
cma__bugcheck ("cma__ts_open2: one of fd's is too large"); \
|
||||
return __res__; \
|
||||
}
|
||||
|
||||
/*
|
||||
* INTERNAL INTERFACES
|
||||
*/
|
||||
extern void cma__close_general (int);
|
||||
|
||||
extern void cma__init_thread_io (void);
|
||||
|
||||
extern cma_t_boolean cma__io_available (cma__t_io_type,int,struct timeval *);
|
||||
|
||||
extern void cma__io_epilog (cma__t_io_type,int);
|
||||
|
||||
extern void cma__io_prolog (cma__t_io_type,int);
|
||||
|
||||
extern void cma__io_wait (cma__t_io_type,int);
|
||||
|
||||
extern void cma__open_general (int);
|
||||
|
||||
extern void cma__reinit_thread_io (int);
|
||||
|
||||
extern void cma__set_nonblocking (int);
|
||||
|
||||
extern void cma__set_user_nonblock_flags (int,int);
|
||||
|
||||
extern cma_t_boolean cma__is_open (int);
|
||||
|
||||
|
||||
#endif
|
|
@ -1,432 +0,0 @@
|
|||
/*
|
||||
* (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
|
||||
* (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
|
||||
* (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
|
||||
* (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
|
||||
* To anyone who acknowledges that this file is provided "AS IS" without
|
||||
* any express or implied warranty: permission to use, copy, modify, and
|
||||
* distribute this file for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notices and this notice appears in
|
||||
* all source code copies, and that none of the names listed above be used
|
||||
* in advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. None of these organizations
|
||||
* makes any representations about the suitability of this software for
|
||||
* any purpose.
|
||||
*/
|
||||
/*
|
||||
*
|
||||
* Header file for thread synchrounous I/O
|
||||
*/
|
||||
|
||||
#ifndef CMA_THREAD_IO
|
||||
#define CMA_THREAD_IO
|
||||
|
||||
/*
|
||||
* INCLUDE FILES
|
||||
*/
|
||||
|
||||
#include <cma_config.h>
|
||||
#include <sys/file.h>
|
||||
#include <cma.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <cma_init.h>
|
||||
#include <cma_errors.h>
|
||||
|
||||
/*
|
||||
* CONSTANTS
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Maximum number of files (ie, max_fd+1)
|
||||
*/
|
||||
#define cma__c_mx_file FD_SETSIZE
|
||||
|
||||
/*
|
||||
* Number of bits per file descriptor bit mask (ie number of bytes * bits/byte)
|
||||
*/
|
||||
#define cma__c_nbpm NFDBITS
|
||||
|
||||
/*
|
||||
* TYPE DEFINITIONS
|
||||
*/
|
||||
|
||||
typedef enum CMA__T_IO_TYPE {
|
||||
cma__c_io_read = 0,
|
||||
cma__c_io_write = 1,
|
||||
cma__c_io_except = 2
|
||||
} cma__t_io_type;
|
||||
#define cma__c_max_io_type 2
|
||||
|
||||
/*
|
||||
* From our local <sys/types.h>:
|
||||
*
|
||||
* typedef long fd_mask;
|
||||
*
|
||||
* typedef struct fd_set {
|
||||
* fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)];
|
||||
* } fd_set;
|
||||
*
|
||||
*/
|
||||
typedef fd_mask cma__t_mask;
|
||||
typedef fd_set cma__t_file_mask;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* GLOBAL DATA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Maximum number of files (ie, max_fd+1) as determined by getdtablesize().
|
||||
*/
|
||||
extern int cma__g_mx_file;
|
||||
|
||||
/*
|
||||
* Number of submasks (ie "int" sized chunks) per file descriptor mask as
|
||||
* determined by getdtablesize().
|
||||
*/
|
||||
extern int cma__g_nspm;
|
||||
|
||||
/*
|
||||
* MACROS
|
||||
*/
|
||||
|
||||
/*
|
||||
* Define a constant for the errno value which indicates that the requested
|
||||
* operation was not performed because it would block the process.
|
||||
*/
|
||||
# define cma__is_blocking(s) \
|
||||
((s == EAGAIN) || (s == EWOULDBLOCK) || (s == EINPROGRESS) || \
|
||||
(s == EALREADY) || (s == EDEADLK))
|
||||
|
||||
/*
|
||||
* It is necessary to issue an I/O function, before calling cma__io_wait()
|
||||
* in the following cases:
|
||||
*
|
||||
* * This file descriptor has been set non-blocking by CMA
|
||||
* * This file descriptor has been set non-blocking by the user.
|
||||
*/
|
||||
|
||||
#define cma__issue_io_call(fd) \
|
||||
( (cma__g_file[fd]->non_blocking) || \
|
||||
(cma__g_file[fd]->user_fl.user_non_blocking) )
|
||||
|
||||
|
||||
#define cma__set_user_nonblocking(flags) \
|
||||
|
||||
/*
|
||||
* Determine if the file is open
|
||||
*/
|
||||
/*
|
||||
* If the file gets closed while waiting for the mutex cma__g_file[rfd]
|
||||
* gets set to null. This results in a crash if NDEBUG is set to 0
|
||||
* since cma__int_lock tries to dereference it to set the mutex ownership
|
||||
* after it gets the mutex. The following will still set the ownership
|
||||
* in cma__int_lock so we'll set it back to noone if cma__g_file is null
|
||||
* when we come back just in case it matters. It shouldn't since its no
|
||||
* longer in use but.....
|
||||
* Callers of this should recheck cma__g_file after the reservation to
|
||||
* make sure continueing makes sense.
|
||||
*/
|
||||
#define cma__fd_reserve(rfd) \
|
||||
{ \
|
||||
cma__t_int_mutex *__mutex__; \
|
||||
__mutex__ = cma__g_file[rfd]->mutex; \
|
||||
cma__int_lock (__mutex__); \
|
||||
if(cma__g_file[rfd] == (cma__t_file_obj *)cma_c_null_ptr) \
|
||||
cma__int_unlock(__mutex__); \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Unreserve a file descriptor
|
||||
*/
|
||||
#define cma__fd_unreserve(ufd) cma__int_unlock (cma__g_file[ufd]->mutex)
|
||||
|
||||
/*
|
||||
* AND together two select file descriptor masks
|
||||
*/
|
||||
#define cma__fdm_and(target,a,b) \
|
||||
{ \
|
||||
int __i__ = cma__g_nspm; \
|
||||
while (__i__--) \
|
||||
(target)->fds_bits[__i__] = \
|
||||
(a)->fds_bits[__i__] & (b)->fds_bits[__i__]; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear a bit in a select file descriptor mask
|
||||
*
|
||||
* FD_CLR(n, p) := ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
|
||||
*/
|
||||
#define cma__fdm_clr_bit(n,p) FD_CLR (n, p)
|
||||
|
||||
/*
|
||||
* Copy the contents of one file descriptor mask into another. If the
|
||||
* destination operand is null, do nothing; if the source operand is null,
|
||||
* simply zero the destination.
|
||||
*/
|
||||
#define cma__fdm_copy(src,dst,nfds) { \
|
||||
if (dst) \
|
||||
if (src) { \
|
||||
cma__t_mask *__s__ = (cma__t_mask *)(src); \
|
||||
cma__t_mask *__d__ = (cma__t_mask *)(dst); \
|
||||
int __i__; \
|
||||
for (__i__ = 0; __i__ < (nfds); __i__ += cma__c_nbpm) \
|
||||
*__d__++ = *__s__++; \
|
||||
} \
|
||||
else \
|
||||
cma__fdm_zero (dst); \
|
||||
}
|
||||
|
||||
/*
|
||||
* To increment count for each bit set in fd - mask
|
||||
*/
|
||||
#define cma__fdm_count_bits(map,count) \
|
||||
{ \
|
||||
int __i__ = cma__g_nspm; \
|
||||
while (__i__--) { \
|
||||
cma__t_mask __tm__; \
|
||||
__tm__ = (map)->fds_bits[__i__]; \
|
||||
while(__tm__) { \
|
||||
(count)++; \
|
||||
__tm__ &= ~(__tm__ & (-__tm__)); /* Assumes 2's comp */ \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
/*
|
||||
* Test if a bit is set in a select file descriptor mask
|
||||
*
|
||||
* FD_ISSET(n,p) := ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
|
||||
*/
|
||||
#define cma__fdm_is_set(n,p) FD_ISSET (n, p)
|
||||
|
||||
/*
|
||||
* OR together two select file descriptor masks
|
||||
*/
|
||||
#define cma__fdm_or(target,a,b) \
|
||||
{ \
|
||||
int __i__ = cma__g_nspm; \
|
||||
while (__i__--) \
|
||||
(target)->fds_bits[__i__] = \
|
||||
(a)->fds_bits[__i__] | (b)->fds_bits[__i__]; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a bit in a select file descriptor mask
|
||||
*
|
||||
* FD_SET(n,p) := ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
|
||||
*/
|
||||
#define cma__fdm_set_bit(n,p) FD_SET (n, p)
|
||||
|
||||
/*
|
||||
* Clear a select file descriptor mask.
|
||||
*/
|
||||
#define cma__fdm_zero(n) \
|
||||
cma__memset ((char *) n, 0, cma__g_nspm * sizeof(cma__t_mask))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* CMA "thread-synchronous" I/O read/write operations
|
||||
*/
|
||||
|
||||
/*
|
||||
* Since all CMA "thread-synchronous" I/O (read or write) operations on
|
||||
* U*ix follow the exact same structure, the wrapper routines have been
|
||||
* condensed into a macro.
|
||||
*
|
||||
* The steps performed are as follows:
|
||||
* 1. Check that the file descriptor is a legitimate value.
|
||||
* 2. Check that the entry in the CMA file "database" which corresponds to
|
||||
* the file descriptor indicates that the "file" was "opened" by CMA.
|
||||
* 3. Reserve the file, to serialized access to files. This not only
|
||||
* simplifies things, but also defends against non-reentrancy.
|
||||
* 4. If the "file" is "set" for non-blocking I/O, check if we
|
||||
* have actually set the file non-blocking yet, and if not do so.
|
||||
* Then, issue the I/O operantion.
|
||||
* Success or failure is returned immediately, after unreserving the
|
||||
* file. If the error indicates that the operation would have caused
|
||||
* the process to block, continue to the next step.
|
||||
* 5. The I/O prolog adds this "file" to the global bit mask, which
|
||||
* represents all "files" which have threads waiting to perform I/O on
|
||||
* them, and causes the thread to block on the condition variable for
|
||||
* this "file". Periodically, a select is done on this global bit
|
||||
* mask, and the condition variables corresponding to "files" which
|
||||
* are ready for I/O are signaled, releasing those waiting threads to
|
||||
* perform their I/O.
|
||||
* 6. When the thread returns from the I/O prolog, it can (hopefully)
|
||||
* perform its operation without blocking the process.
|
||||
* 7. The I/O epilog clears the bit in the global mask and/or signals the
|
||||
* the next thread waiting for this "file", as appropriate.
|
||||
* 8. If the I/O failed, continue to loop.
|
||||
* 9. Finally, the "file" is unreserved, as we're done with it, and the
|
||||
* result of the operation is returned.
|
||||
*
|
||||
*
|
||||
* Note: currently, we believe that timeslicing which is based on the
|
||||
* virtual-time timer does not cause system calls to return EINTR.
|
||||
* Threfore, any EINTR returns are relayed directly to the caller.
|
||||
* On platforms which do not support a virtual-time timer, the code
|
||||
* should probably catch EINTR returns and restart the system call.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This macro is used for both read-type and write-type functions.
|
||||
*
|
||||
* Note: the second call to "func" may require being bracketed in a
|
||||
* cma__interrupt_disable/cma__interrupt_enable pair, but we'll
|
||||
* wait and see if this is necessary.
|
||||
*/
|
||||
#define cma__ts_func(func,fd,arglist,type,post_process) { \
|
||||
cma_t_integer __res__; \
|
||||
cma_t_boolean __done__ = cma_c_false; \
|
||||
if ((fd < 0) || (fd >= cma__g_mx_file)) return (cma__set_errno (EBADF), -1); \
|
||||
if (!cma__is_open(fd)) return (cma__set_errno (EBADF), -1); \
|
||||
cma__fd_reserve (fd); \
|
||||
if (!cma__is_open(fd)) return (cma__set_errno (EBADF), -1); \
|
||||
if (cma__issue_io_call(fd)) {\
|
||||
if ((!cma__g_file[fd]->set_non_blocking) && \
|
||||
(cma__g_file[fd]->non_blocking == cma_c_true)) \
|
||||
cma__set_nonblocking(fd); \
|
||||
cma__interrupt_disable (0); \
|
||||
TRY { \
|
||||
__res__ = func arglist; \
|
||||
} \
|
||||
CATCH_ALL { \
|
||||
cma__interrupt_enable (0); \
|
||||
cma__fd_unreserve (fd); \
|
||||
RERAISE; \
|
||||
} \
|
||||
ENDTRY \
|
||||
cma__interrupt_enable (0); \
|
||||
if ((__res__ != -1) \
|
||||
|| (!cma__is_blocking (errno)) \
|
||||
|| (cma__g_file[fd]->user_fl.user_non_blocking)) \
|
||||
__done__ = cma_c_true; \
|
||||
} \
|
||||
if (__done__) { \
|
||||
cma__fd_unreserve (fd); \
|
||||
} \
|
||||
else { \
|
||||
TRY { \
|
||||
cma__io_prolog (type, fd); \
|
||||
while (!__done__) { \
|
||||
cma__io_wait (type, fd); \
|
||||
__res__ = func arglist; \
|
||||
if ((__res__ != -1) \
|
||||
|| (!cma__is_blocking (errno)) \
|
||||
|| (cma__g_file[fd]->user_fl.user_non_blocking)) \
|
||||
__done__ = cma_c_true; \
|
||||
} \
|
||||
} \
|
||||
FINALLY { \
|
||||
cma__io_epilog (type, fd); \
|
||||
cma__fd_unreserve (fd); \
|
||||
} \
|
||||
ENDTRY \
|
||||
} \
|
||||
if (__res__ != -1) post_process; \
|
||||
return __res__; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Since most CMA "thread-synchronous" I/O ("open"-type) operations on
|
||||
* U*ix follow the exact same structure, the wrapper routines have been
|
||||
* condensed into a macro.
|
||||
*
|
||||
* The steps performed are as follows:
|
||||
* 1. Issue the open function.
|
||||
* 2. If the value returned indicates an error, return it to the caller.
|
||||
* 3. If the file descriptor returned is larger than what we think is the
|
||||
* maximum value (ie if it is too big for our database) then bugcheck.
|
||||
* 4. "Open" the "file" in the CMA file database.
|
||||
* 5. Return the file descriptor value to the caller.
|
||||
*
|
||||
* FIX-ME: for the time being, if the I/O operation returns EINTR, we
|
||||
* simply return it to the caller; eventually, we should catch this
|
||||
* and "do the right thing" (if we can figure out what that is).
|
||||
*/
|
||||
|
||||
/*
|
||||
* This macro is used for all "open"-type functions which return a single file
|
||||
* desciptor by immediate value.
|
||||
*/
|
||||
#define cma__ts_open(func,arglist,post_process) { \
|
||||
int __fd__; \
|
||||
TRY { \
|
||||
cma__int_init (); \
|
||||
cma__int_lock (cma__g_io_data_mutex); \
|
||||
__fd__ = func arglist; \
|
||||
cma__int_unlock (cma__g_io_data_mutex); \
|
||||
if (__fd__ >= 0 && __fd__ < cma__g_mx_file) \
|
||||
post_process; \
|
||||
} \
|
||||
CATCH_ALL \
|
||||
{ \
|
||||
cma__set_errno (EBADF); \
|
||||
__fd__ = -1; \
|
||||
} \
|
||||
ENDTRY \
|
||||
if (__fd__ >= cma__g_mx_file) \
|
||||
cma__bugcheck ("cma__ts_open: fd is too large"); \
|
||||
return __fd__; \
|
||||
}
|
||||
/*
|
||||
* This macro is used for all "open"-type functions which return a pair of file
|
||||
* desciptors by reference parameter.
|
||||
*/
|
||||
#define cma__ts_open2(func,fdpair,arglist,post_process) { \
|
||||
int __res__; \
|
||||
TRY { \
|
||||
cma__int_init (); \
|
||||
cma__int_lock (cma__g_io_data_mutex); \
|
||||
__res__ = func arglist; \
|
||||
cma__int_unlock (cma__g_io_data_mutex); \
|
||||
if (__res__ >= 0 && fdpair[0] < cma__g_mx_file \
|
||||
&& fdpair[1] < cma__g_mx_file) \
|
||||
post_process; \
|
||||
} \
|
||||
CATCH_ALL \
|
||||
{ \
|
||||
cma__set_errno (EBADF); \
|
||||
__res__ = -1; \
|
||||
} \
|
||||
ENDTRY \
|
||||
if ((fdpair[0] >= cma__g_mx_file) || (fdpair[1] >= cma__g_mx_file)) \
|
||||
cma__bugcheck ("cma__ts_open2: one of fd's is too large"); \
|
||||
return __res__; \
|
||||
}
|
||||
|
||||
/*
|
||||
* INTERNAL INTERFACES
|
||||
*/
|
||||
extern void cma__close_general (int);
|
||||
|
||||
extern void cma__init_thread_io (void);
|
||||
|
||||
extern cma_t_boolean cma__io_available (cma__t_io_type,int,struct timeval *);
|
||||
|
||||
extern void cma__io_epilog (cma__t_io_type,int);
|
||||
|
||||
extern void cma__io_prolog (cma__t_io_type,int);
|
||||
|
||||
extern void cma__io_wait (cma__t_io_type,int);
|
||||
|
||||
extern void cma__open_general (int);
|
||||
|
||||
extern void cma__reinit_thread_io (int);
|
||||
|
||||
extern void cma__set_nonblocking (int);
|
||||
|
||||
extern void cma__set_user_nonblock_flags (int,int);
|
||||
|
||||
extern cma_t_boolean cma__is_open (int);
|
||||
|
||||
#endif
|
|
@ -1,8 +0,0 @@
|
|||
This directory contains header files necessary to build a thread-aware GDB on
|
||||
systems based on OSF's CMA threads package.
|
||||
|
||||
The latest version of these header files are available for free from:
|
||||
|
||||
http://www.osf.org/mall/dce/SW-code
|
||||
|
||||
Currently, the only port of GDB which supports CMA threads is HP/UX-10.10.
|
|
@ -1,434 +0,0 @@
|
|||
/*
|
||||
* (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
|
||||
* (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
|
||||
* (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
|
||||
* (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
|
||||
* To anyone who acknowledges that this file is provided "AS IS" without
|
||||
* any express or implied warranty: permission to use, copy, modify, and
|
||||
* distribute this file for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notices and this notice appears in
|
||||
* all source code copies, and that none of the names listed above be used
|
||||
* in advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. None of these organizations
|
||||
* makes any representations about the suitability of this software for
|
||||
* any purpose.
|
||||
*/
|
||||
/*
|
||||
* Header file for thread synchrounous I/O
|
||||
*/
|
||||
|
||||
#ifndef CMA_THREAD_IO
|
||||
#define CMA_THREAD_IO
|
||||
|
||||
/*
|
||||
* INCLUDE FILES
|
||||
*/
|
||||
|
||||
#include <cma_config.h>
|
||||
#include <sys/select.h>
|
||||
#include <cma.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <cma_init.h>
|
||||
#include <cma_errors.h>
|
||||
|
||||
/*
|
||||
* CONSTANTS
|
||||
*/
|
||||
|
||||
/*
|
||||
* Maximum number of files (ie, max_fd+1)
|
||||
*/
|
||||
#define cma__c_mx_file FD_SETSIZE
|
||||
|
||||
/*
|
||||
* Number of bits per file descriptor bit mask (ie number of bytes * bits/byte)
|
||||
*/
|
||||
#define cma__c_nbpm NFDBITS
|
||||
|
||||
/*
|
||||
* TYPE DEFINITIONS
|
||||
*/
|
||||
|
||||
typedef enum CMA__T_IO_TYPE {
|
||||
cma__c_io_read = 0,
|
||||
cma__c_io_write = 1,
|
||||
cma__c_io_except = 2
|
||||
} cma__t_io_type;
|
||||
#define cma__c_max_io_type 2
|
||||
|
||||
/*
|
||||
* From our local <sys/types.h>:
|
||||
*
|
||||
* typedef long fd_mask;
|
||||
*
|
||||
* typedef struct fd_set {
|
||||
* fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)];
|
||||
* } fd_set;
|
||||
*
|
||||
*/
|
||||
typedef fd_mask cma__t_mask;
|
||||
typedef fd_set cma__t_file_mask;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* GLOBAL DATA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Maximum number of files (ie, max_fd+1) as determined by getdtablesize().
|
||||
*/
|
||||
extern int cma__g_mx_file;
|
||||
|
||||
/*
|
||||
* Number of submasks (ie "int" sized chunks) per file descriptor mask as
|
||||
* determined by getdtablesize().
|
||||
*/
|
||||
extern int cma__g_nspm;
|
||||
|
||||
/*
|
||||
* MACROS
|
||||
*/
|
||||
|
||||
/*
|
||||
* Define a constant for the errno value which indicates that the requested
|
||||
* operation was not performed because it would block the process.
|
||||
*/
|
||||
# define cma__is_blocking(s) \
|
||||
((s == EAGAIN) || (s == EWOULDBLOCK) || (s == EINPROGRESS) || \
|
||||
(s == EALREADY) || (s == EDEADLK))
|
||||
|
||||
/*
|
||||
* It is necessary to issue an I/O function, before calling cma__io_wait()
|
||||
* in the following cases:
|
||||
*
|
||||
* * This file descriptor has been set non-blocking by CMA
|
||||
* * This file descriptor has been set non-blocking by the user.
|
||||
*/
|
||||
|
||||
#define cma__issue_io_call(fd) \
|
||||
( (cma__g_file[fd]->non_blocking) || \
|
||||
(cma__g_file[fd]->user_fl.user_non_blocking) )
|
||||
|
||||
|
||||
#define cma__set_user_nonblocking(flags) \
|
||||
|
||||
/*
|
||||
* Determine if the file is open
|
||||
*/
|
||||
/*
|
||||
* If the file gets closed while waiting for the mutex cma__g_file[rfd]
|
||||
* gets set to null. This results in a crash if NDEBUG is set to 0
|
||||
* since cma__int_lock tries to dereference it to set the mutex ownership
|
||||
* after it gets the mutex. The following will still set the ownership
|
||||
* in cma__int_lock so we'll set it back to noone if cma__g_file is null
|
||||
* when we come back just in case it matters. It shouldn't since its no
|
||||
* longer in use but.....
|
||||
* Callers of this should recheck cma__g_file after the reservation to
|
||||
* make sure continueing makes sense.
|
||||
*/
|
||||
#define cma__fd_reserve(rfd) \
|
||||
{ \
|
||||
cma__t_int_mutex *__mutex__; \
|
||||
__mutex__ = cma__g_file[rfd]->mutex; \
|
||||
cma__int_lock (__mutex__); \
|
||||
if(cma__g_file[rfd] == (cma__t_file_obj *)cma_c_null_ptr) \
|
||||
cma__int_unlock(__mutex__); \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Unreserve a file descriptor
|
||||
*/
|
||||
#define cma__fd_unreserve(ufd) cma__int_unlock (cma__g_file[ufd]->mutex)
|
||||
|
||||
/*
|
||||
* AND together two select file descriptor masks
|
||||
*/
|
||||
#define cma__fdm_and(target,a,b) \
|
||||
{ \
|
||||
int __i__ = cma__g_nspm; \
|
||||
while (__i__--) \
|
||||
(target)->fds_bits[__i__] = \
|
||||
(a)->fds_bits[__i__] & (b)->fds_bits[__i__]; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear a bit in a select file descriptor mask
|
||||
*
|
||||
* FD_CLR(n, p) := ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
|
||||
*/
|
||||
#define cma__fdm_clr_bit(n,p) FD_CLR (n, p)
|
||||
|
||||
/*
|
||||
* Copy the contents of one file descriptor mask into another. If the
|
||||
* destination operand is null, do nothing; if the source operand is null,
|
||||
* simply zero the destination.
|
||||
*/
|
||||
#define cma__fdm_copy(src,dst,nfds) { \
|
||||
if (dst) \
|
||||
if (src) { \
|
||||
cma__t_mask *__s__ = (cma__t_mask *)(src); \
|
||||
cma__t_mask *__d__ = (cma__t_mask *)(dst); \
|
||||
int __i__; \
|
||||
for (__i__ = 0; __i__ < (nfds); __i__ += cma__c_nbpm) \
|
||||
*__d__++ = *__s__++; \
|
||||
} \
|
||||
else \
|
||||
cma__fdm_zero (dst); \
|
||||
}
|
||||
|
||||
/*
|
||||
* To increment count for each bit set in fd - mask
|
||||
*/
|
||||
#define cma__fdm_count_bits(map,count) \
|
||||
{ \
|
||||
int __i__ = cma__g_nspm; \
|
||||
while (__i__--) { \
|
||||
cma__t_mask __tm__; \
|
||||
__tm__ = (map)->fds_bits[__i__]; \
|
||||
while(__tm__) { \
|
||||
(count)++; \
|
||||
__tm__ &= ~(__tm__ & (-__tm__)); /* Assumes 2's comp */ \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
/*
|
||||
* Test if a bit is set in a select file descriptor mask
|
||||
*
|
||||
* FD_ISSET(n,p) := ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
|
||||
*/
|
||||
#define cma__fdm_is_set(n,p) FD_ISSET (n, p)
|
||||
|
||||
/*
|
||||
* OR together two select file descriptor masks
|
||||
*/
|
||||
#define cma__fdm_or(target,a,b) \
|
||||
{ \
|
||||
int __i__ = cma__g_nspm; \
|
||||
while (__i__--) \
|
||||
(target)->fds_bits[__i__] = \
|
||||
(a)->fds_bits[__i__] | (b)->fds_bits[__i__]; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a bit in a select file descriptor mask
|
||||
*
|
||||
* FD_SET(n,p) := ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
|
||||
*/
|
||||
#define cma__fdm_set_bit(n,p) FD_SET (n, p)
|
||||
|
||||
/*
|
||||
* Clear a select file descriptor mask.
|
||||
*/
|
||||
#define cma__fdm_zero(n) \
|
||||
cma__memset ((char *) n, 0, cma__g_nspm * sizeof(cma__t_mask))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* CMA "thread-synchronous" I/O read/write operations
|
||||
*/
|
||||
|
||||
/*
|
||||
* Since all CMA "thread-synchronous" I/O (read or write) operations on
|
||||
* U*ix follow the exact same structure, the wrapper routines have been
|
||||
* condensed into a macro.
|
||||
*
|
||||
* The steps performed are as follows:
|
||||
* 1. Check that the file descriptor is a legitimate value.
|
||||
* 2. Check that the entry in the CMA file "database" which corresponds to
|
||||
* the file descriptor indicates that the "file" was "opened" by CMA.
|
||||
* 3. Reserve the file, to serialized access to files. This not only
|
||||
* simplifies things, but also defends against non-reentrancy.
|
||||
* 4. If the "file" is "set" for non-blocking I/O, check if we
|
||||
* have actually set the file non-blocking yet, and if not do so.
|
||||
* Then, issue the I/O operantion.
|
||||
* Success or failure is returned immediately, after unreserving the
|
||||
* file. If the error indicates that the operation would have caused
|
||||
* the process to block, continue to the next step.
|
||||
* 5. The I/O prolog adds this "file" to the global bit mask, which
|
||||
* represents all "files" which have threads waiting to perform I/O on
|
||||
* them, and causes the thread to block on the condition variable for
|
||||
* this "file". Periodically, a select is done on this global bit
|
||||
* mask, and the condition variables corresponding to "files" which
|
||||
* are ready for I/O are signaled, releasing those waiting threads to
|
||||
* perform their I/O.
|
||||
* 6. When the thread returns from the I/O prolog, it can (hopefully)
|
||||
* perform its operation without blocking the process.
|
||||
* 7. The I/O epilog clears the bit in the global mask and/or signals the
|
||||
* the next thread waiting for this "file", as appropriate.
|
||||
* 8. If the I/O failed, continue to loop.
|
||||
* 9. Finally, the "file" is unreserved, as we're done with it, and the
|
||||
* result of the operation is returned.
|
||||
*
|
||||
*
|
||||
* Note: currently, we believe that timeslicing which is based on the
|
||||
* virtual-time timer does not cause system calls to return EINTR.
|
||||
* Threfore, any EINTR returns are relayed directly to the caller.
|
||||
* On platforms which do not support a virtual-time timer, the code
|
||||
* should probably catch EINTR returns and restart the system call.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This macro is used for both read-type and write-type functions.
|
||||
*
|
||||
* Note: the second call to "func" may require being bracketed in a
|
||||
* cma__interrupt_disable/cma__interrupt_enable pair, but we'll
|
||||
* wait and see if this is necessary.
|
||||
*/
|
||||
#define cma__ts_func(func,fd,arglist,type,post_process) { \
|
||||
cma_t_integer __res__; \
|
||||
cma_t_boolean __done__ = cma_c_false; \
|
||||
if ((fd < 0) || (fd >= cma__g_mx_file)) return (cma__set_errno (EBADF), -1); \
|
||||
if (!cma__is_open(fd)) return (cma__set_errno (EBADF), -1); \
|
||||
cma__fd_reserve (fd); \
|
||||
if (!cma__is_open(fd)) return (cma__set_errno (EBADF), -1); \
|
||||
if (cma__issue_io_call(fd)) {\
|
||||
if ((!cma__g_file[fd]->set_non_blocking) && \
|
||||
(cma__g_file[fd]->non_blocking == cma_c_true)) \
|
||||
cma__set_nonblocking(fd); \
|
||||
cma__interrupt_disable (0); \
|
||||
TRY { \
|
||||
__res__ = func arglist; \
|
||||
} \
|
||||
CATCH_ALL { \
|
||||
cma__interrupt_enable (0); \
|
||||
cma__fd_unreserve (fd); \
|
||||
RERAISE; \
|
||||
} \
|
||||
ENDTRY \
|
||||
cma__interrupt_enable (0); \
|
||||
if ((__res__ != -1) \
|
||||
|| (!cma__is_blocking (errno)) \
|
||||
|| (cma__g_file[fd]->user_fl.user_non_blocking)) \
|
||||
__done__ = cma_c_true; \
|
||||
} \
|
||||
if (__done__) { \
|
||||
cma__fd_unreserve (fd); \
|
||||
} \
|
||||
else { \
|
||||
TRY { \
|
||||
cma__io_prolog (type, fd); \
|
||||
while (!__done__) { \
|
||||
cma__io_wait (type, fd); \
|
||||
__res__ = func arglist; \
|
||||
if ((__res__ != -1) \
|
||||
|| (!cma__is_blocking (errno)) \
|
||||
|| (cma__g_file[fd]->user_fl.user_non_blocking)) \
|
||||
__done__ = cma_c_true; \
|
||||
} \
|
||||
} \
|
||||
FINALLY { \
|
||||
cma__io_epilog (type, fd); \
|
||||
cma__fd_unreserve (fd); \
|
||||
} \
|
||||
ENDTRY \
|
||||
} \
|
||||
if (__res__ != -1) post_process; \
|
||||
return __res__; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Since most CMA "thread-synchronous" I/O ("open"-type) operations on
|
||||
* U*ix follow the exact same structure, the wrapper routines have been
|
||||
* condensed into a macro.
|
||||
*
|
||||
* The steps performed are as follows:
|
||||
* 1. Issue the open function.
|
||||
* 2. If the value returned indicates an error, return it to the caller.
|
||||
* 3. If the file descriptor returned is larger than what we think is the
|
||||
* maximum value (ie if it is too big for our database) then bugcheck.
|
||||
* 4. "Open" the "file" in the CMA file database.
|
||||
* 5. Return the file descriptor value to the caller.
|
||||
*
|
||||
* FIX-ME: for the time being, if the I/O operation returns EINTR, we
|
||||
* simply return it to the caller; eventually, we should catch this
|
||||
* and "do the right thing" (if we can figure out what that is).
|
||||
*/
|
||||
|
||||
/*
|
||||
* This macro is used for all "open"-type functions which return a single file
|
||||
* desciptor by immediate value.
|
||||
*/
|
||||
#define cma__ts_open(func,arglist,post_process) { \
|
||||
int __fd__; \
|
||||
TRY { \
|
||||
cma__int_init (); \
|
||||
cma__int_lock (cma__g_io_data_mutex); \
|
||||
__fd__ = func arglist; \
|
||||
cma__int_unlock (cma__g_io_data_mutex); \
|
||||
if (__fd__ >= 0 && __fd__ < cma__g_mx_file) \
|
||||
post_process; \
|
||||
} \
|
||||
CATCH_ALL \
|
||||
{ \
|
||||
cma__set_errno (EBADF); \
|
||||
__fd__ = -1; \
|
||||
} \
|
||||
ENDTRY \
|
||||
if (__fd__ >= cma__g_mx_file) \
|
||||
cma__bugcheck ("cma__ts_open: fd is too large"); \
|
||||
return __fd__; \
|
||||
}
|
||||
/*
|
||||
* This macro is used for all "open"-type functions which return a pair of file
|
||||
* desciptors by reference parameter.
|
||||
*/
|
||||
#define cma__ts_open2(func,fdpair,arglist,post_process) { \
|
||||
int __res__; \
|
||||
TRY { \
|
||||
cma__int_init (); \
|
||||
cma__int_lock (cma__g_io_data_mutex); \
|
||||
__res__ = func arglist; \
|
||||
cma__int_unlock (cma__g_io_data_mutex); \
|
||||
if (__res__ >= 0 && fdpair[0] < cma__g_mx_file \
|
||||
&& fdpair[1] < cma__g_mx_file) \
|
||||
post_process; \
|
||||
} \
|
||||
CATCH_ALL \
|
||||
{ \
|
||||
cma__set_errno (EBADF); \
|
||||
__res__ = -1; \
|
||||
} \
|
||||
ENDTRY \
|
||||
if ((fdpair[0] >= cma__g_mx_file) || (fdpair[1] >= cma__g_mx_file)) \
|
||||
cma__bugcheck ("cma__ts_open2: one of fd's is too large"); \
|
||||
return __res__; \
|
||||
}
|
||||
|
||||
/*
|
||||
* INTERNAL INTERFACES
|
||||
*/
|
||||
extern void cma__close_general (int);
|
||||
|
||||
extern void
|
||||
cma__init_thread_io (void);
|
||||
|
||||
extern cma_t_boolean cma__io_available (cma__t_io_type,int,struct timeval *);
|
||||
|
||||
extern void cma__io_epilog (cma__t_io_type,int);
|
||||
|
||||
extern void cma__io_prolog (cma__t_io_type,int);
|
||||
|
||||
extern void cma__io_wait (cma__t_io_type,int);
|
||||
|
||||
extern void cma__open_general (int);
|
||||
|
||||
extern void cma__reinit_thread_io (int);
|
||||
|
||||
extern void cma__set_nonblocking (int);
|
||||
|
||||
extern void cma__set_user_nonblock_flags (int,int);
|
||||
|
||||
extern cma_t_boolean
|
||||
cma__is_open (int fd);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,341 +0,0 @@
|
|||
/*
|
||||
* (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
|
||||
* (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
|
||||
* (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
|
||||
* (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
|
||||
* To anyone who acknowledges that this file is provided "AS IS" without
|
||||
* any express or implied warranty: permission to use, copy, modify, and
|
||||
* distribute this file for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notices and this notice appears in
|
||||
* all source code copies, and that none of the names listed above be used
|
||||
* in advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. None of these organizations
|
||||
* makes any representations about the suitability of this software for
|
||||
* any purpose.
|
||||
*/
|
||||
/*
|
||||
* Header file for attributes object
|
||||
*/
|
||||
|
||||
#ifndef CMA_ATTR
|
||||
#define CMA_ATTR
|
||||
|
||||
/*
|
||||
* INCLUDE FILES
|
||||
*/
|
||||
|
||||
#include <cma_defs.h>
|
||||
#include <cma_queue.h>
|
||||
#ifdef __hpux
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
#if _CMA_UNIX_TYPE == _CMA__SVR4
|
||||
#include <sys/unistd.h>
|
||||
#endif
|
||||
/*
|
||||
* CONSTANTS AND MACROS
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* FUNCTIONAL DESCRIPTION:
|
||||
*
|
||||
* cma__int_attr_get_priority - Performs the work of cma_attr_get_priority
|
||||
*
|
||||
* FORMAL PARAMETERS:
|
||||
*
|
||||
* cma_t_attr *_att_ - Attribute object to get from
|
||||
* cma_t_priority *_setting_ - Current setting
|
||||
*
|
||||
* IMPLICIT INPUTS:
|
||||
*
|
||||
* none
|
||||
*
|
||||
* IMPLICIT OUTPUTS:
|
||||
*
|
||||
* priority
|
||||
*
|
||||
* FUNCTION VALUE:
|
||||
*
|
||||
* none
|
||||
*
|
||||
* SIDE EFFECTS:
|
||||
*
|
||||
* none
|
||||
*/
|
||||
#define cma__int_attr_get_priority(_att_,_setting_) { \
|
||||
cma__t_int_attr *_int_att_; \
|
||||
(_int_att_) = cma__validate_default_attr (_att_); \
|
||||
cma__int_lock ((_int_att_)->mutex); \
|
||||
(*(_setting_)) = (_int_att_)->priority; \
|
||||
cma__int_unlock ((_int_att_)->mutex); \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* FUNCTIONAL DESCRIPTION:
|
||||
*
|
||||
* cma__int_attr_get_sched - Performs work of cma_attr_get_sched
|
||||
*
|
||||
* FORMAL PARAMETERS:
|
||||
*
|
||||
* cma_t_attr *_att_ _ Attributes object used
|
||||
* cma_t_sched_policy *_setting_ - Current setting
|
||||
*
|
||||
* IMPLICIT INPUTS:
|
||||
*
|
||||
* none
|
||||
*
|
||||
* IMPLICIT OUTPUTS:
|
||||
*
|
||||
* scheduling policy
|
||||
*
|
||||
* FUNCTION VALUE:
|
||||
*
|
||||
* none
|
||||
*
|
||||
* SIDE EFFECTS:
|
||||
*
|
||||
* none
|
||||
*/
|
||||
#define cma__int_attr_get_sched(_att_,_setting_) { \
|
||||
cma__t_int_attr *_int_att_; \
|
||||
(_int_att_) = cma__validate_default_attr (_att_); \
|
||||
cma__int_lock ((_int_att_)->mutex); \
|
||||
(*(_setting_)) = (_int_att_)->policy; \
|
||||
cma__int_unlock ((_int_att_)->mutex); \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* FUNCTIONAL DESCRIPTION:
|
||||
*
|
||||
* cma__int_attr_get_inherit_sched - Performs work of
|
||||
* cma_attr_get_inherit_sched
|
||||
*
|
||||
* FORMAL PARAMETERS:
|
||||
*
|
||||
* cma_t_attr *_att_ - Attributes object to use
|
||||
* cma_t_sched_inherit *_setting_ - Current setting
|
||||
*
|
||||
* IMPLICIT INPUTS:
|
||||
*
|
||||
* none
|
||||
*
|
||||
* IMPLICIT OUTPUTS:
|
||||
*
|
||||
* Inheritable scheduling policy
|
||||
*
|
||||
* FUNCTION VALUE:
|
||||
*
|
||||
* none
|
||||
*
|
||||
* SIDE EFFECTS:
|
||||
*
|
||||
* none
|
||||
*/
|
||||
#define cma__int_attr_get_inherit_sched(_att_,_setting_) { \
|
||||
cma__t_int_attr *_int_att_; \
|
||||
(_int_att_) = cma__validate_default_attr (_att_); \
|
||||
cma__int_lock ((_int_att_)->mutex); \
|
||||
(*(_setting_)) \
|
||||
= ((_int_att_)->inherit_sched ? cma_c_sched_inherit : cma_c_sched_use_default); \
|
||||
cma__int_unlock ((_int_att_)->mutex); \
|
||||
}
|
||||
|
||||
/*
|
||||
* FUNCTIONAL DESCRIPTION:
|
||||
*
|
||||
* cma__int_attr_set_stacksize - Performs work for cma_attr_set_stacksize
|
||||
*
|
||||
* FORMAL PARAMETERS:
|
||||
*
|
||||
* cma_t_attr *_att_ - Attributes object to use
|
||||
* cma_t_natural _setting_ - Setting
|
||||
*
|
||||
* IMPLICIT INPUTS:
|
||||
*
|
||||
* none
|
||||
*
|
||||
* IMPLICIT OUTPUTS:
|
||||
*
|
||||
* none
|
||||
*
|
||||
* FUNCTION VALUE:
|
||||
*
|
||||
* none
|
||||
*
|
||||
* SIDE EFFECTS:
|
||||
*
|
||||
* Change attribute objects stack size setting
|
||||
*/
|
||||
#define cma__int_attr_set_stacksize(_att_,_setting_) { \
|
||||
cma__t_int_attr *_int_att_; \
|
||||
if ((_setting_) <= 0) \
|
||||
cma__error (cma_s_badparam); \
|
||||
_int_att_ = cma__validate_attr (_att_); \
|
||||
cma__int_lock ((_int_att_)->mutex); \
|
||||
_int_att_->stack_size = cma__roundup_chunksize(_setting_); \
|
||||
cma__free_cache (_int_att_, cma__c_obj_tcb); \
|
||||
_int_att_->cache[cma__c_obj_tcb].revision++; \
|
||||
_int_att_->cache[cma__c_obj_stack].revision++; \
|
||||
cma__int_unlock (_int_att_->mutex); \
|
||||
}
|
||||
|
||||
/*
|
||||
* FUNCTIONAL DESCRIPTION:
|
||||
*
|
||||
* cma__int_attr_get_stacksize - Performs work of cma_attr_get_stacksize
|
||||
*
|
||||
* FORMAL PARAMETERS:
|
||||
*
|
||||
* cma_t_attr *_att_ - Attributes object to use
|
||||
* cma_t_natural *_setting_ - Current setting
|
||||
*
|
||||
* IMPLICIT INPUTS:
|
||||
*
|
||||
* none
|
||||
*
|
||||
* IMPLICIT OUTPUTS:
|
||||
*
|
||||
* Attribute objects stack size setting
|
||||
*
|
||||
* FUNCTION VALUE:
|
||||
*
|
||||
* none
|
||||
*
|
||||
* SIDE EFFECTS:
|
||||
*
|
||||
* none
|
||||
*/
|
||||
#define cma__int_attr_get_stacksize(_att_,_setting_) { \
|
||||
cma__t_int_attr *_int_att_; \
|
||||
(_int_att_) = cma__validate_default_attr (_att_); \
|
||||
cma__int_lock ((_int_att_)->mutex); \
|
||||
(*(_setting_)) = (_int_att_)->stack_size; \
|
||||
cma__int_unlock ((_int_att_)->mutex); \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* FUNCTIONAL DESCRIPTION:
|
||||
*
|
||||
* cma__int_attr_set_guardsize - Performs work for cma_attr_set_guardsize
|
||||
*
|
||||
* FORMAL PARAMETERS:
|
||||
*
|
||||
* cma_t_attr *_att_ - Attributes object to use
|
||||
* cma_t_natural _setting_ - Setting
|
||||
*
|
||||
* IMPLICIT INPUTS:
|
||||
*
|
||||
* none
|
||||
*
|
||||
* IMPLICIT OUTPUTS:
|
||||
*
|
||||
* none
|
||||
*
|
||||
* FUNCTION VALUE:
|
||||
*
|
||||
* none
|
||||
*
|
||||
* SIDE EFFECTS:
|
||||
*
|
||||
* Change attribute objects guard size setting
|
||||
*/
|
||||
#define cma__int_attr_set_guardsize(_att_,_setting_) { \
|
||||
cma__t_int_attr *_int_att_; \
|
||||
_int_att_ = cma__validate_attr (_att_); \
|
||||
cma__int_lock ((_int_att_)->mutex); \
|
||||
_int_att_->guard_size = cma__roundup_chunksize(_setting_); \
|
||||
cma__free_cache (_int_att_, cma__c_obj_tcb); \
|
||||
_int_att_->cache[cma__c_obj_tcb].revision++; \
|
||||
_int_att_->cache[cma__c_obj_stack].revision++; \
|
||||
cma__int_unlock (_int_att_->mutex); \
|
||||
}
|
||||
|
||||
/*
|
||||
* FUNCTIONAL DESCRIPTION:
|
||||
*
|
||||
* cma__int_attr_get_guardsize - Performs work of cma_attr_get_guardsize
|
||||
*
|
||||
* FORMAL PARAMETERS:
|
||||
*
|
||||
* cma_t_attr *_att_ - Attributes object to use
|
||||
* cma_t_natural *_setting_ - Current setting
|
||||
*
|
||||
* IMPLICIT INPUTS:
|
||||
*
|
||||
* none
|
||||
*
|
||||
* IMPLICIT OUTPUTS:
|
||||
*
|
||||
* Attribute objects guard size setting
|
||||
*
|
||||
* FUNCTION VALUE:
|
||||
*
|
||||
* none
|
||||
*
|
||||
* SIDE EFFECTS:
|
||||
*
|
||||
* none
|
||||
*/
|
||||
#define cma__int_attr_get_guardsize(_att_,_setting_) { \
|
||||
cma__t_int_attr *_int_att_; \
|
||||
(_int_att_) = cma__validate_default_attr (_att_); \
|
||||
cma__int_lock ((_int_att_)->mutex); \
|
||||
(*(_setting_)) = (_int_att_)->guard_size; \
|
||||
cma__int_unlock ((_int_att_)->mutex); \
|
||||
}
|
||||
|
||||
/*
|
||||
* TYPEDEFS
|
||||
*/
|
||||
#ifndef __STDC__
|
||||
struct CMA__T_INT_MUTEX; /* Avoid circular dependency */
|
||||
#endif
|
||||
|
||||
typedef struct CMA__T_CACHE {
|
||||
cma_t_natural revision; /* Revisions */
|
||||
cma_t_natural count;
|
||||
cma__t_queue queue; /* Cache headers */
|
||||
} cma__t_cache;
|
||||
|
||||
typedef struct CMA__T_INT_ATTR {
|
||||
cma__t_object header; /* Common header */
|
||||
struct CMA__T_INT_ATTR *attributes; /* Point to controlling attr */
|
||||
struct CMA__T_INT_MUTEX *mutex; /* Serialize access to object */
|
||||
cma_t_priority priority; /* Priority of new thread */
|
||||
cma_t_sched_policy policy; /* Sched policy of thread */
|
||||
cma_t_boolean inherit_sched; /* Is scheduling inherited? */
|
||||
cma_t_natural stack_size; /* Size of stack (bytes) */
|
||||
cma_t_natural guard_size; /* Size of guard (bytes) */
|
||||
cma_t_mutex_kind mutex_kind; /* Mutex kind */
|
||||
cma__t_cache cache[cma__c_obj_num]; /* Cache information */
|
||||
cma_t_boolean delete_pending; /* attr. obj. is deleted */
|
||||
cma_t_natural refcnt; /* Number of objects using attr. obj */
|
||||
} cma__t_int_attr;
|
||||
|
||||
/*
|
||||
* GLOBAL DATA
|
||||
*/
|
||||
|
||||
extern cma__t_int_attr cma__g_def_attr;
|
||||
|
||||
/*
|
||||
* INTERNAL INTERFACES
|
||||
*/
|
||||
|
||||
extern void cma__destroy_attributes (cma__t_int_attr *);
|
||||
|
||||
extern void cma__free_attributes (cma__t_int_attr *);
|
||||
|
||||
extern void cma__free_cache (cma__t_int_attr *,cma_t_natural );
|
||||
|
||||
extern cma__t_int_attr *cma__get_attributes (cma__t_int_attr *);
|
||||
|
||||
extern void cma__init_attr (void);
|
||||
|
||||
extern void cma__reinit_attr (cma_t_integer);
|
||||
|
||||
#endif
|
|
@ -1,164 +0,0 @@
|
|||
/*
|
||||
* (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
|
||||
* (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
|
||||
* (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
|
||||
* (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
|
||||
* To anyone who acknowledges that this file is provided "AS IS" without
|
||||
* any express or implied warranty: permission to use, copy, modify, and
|
||||
* distribute this file for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notices and this notice appears in
|
||||
* all source code copies, and that none of the names listed above be used
|
||||
* in advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. None of these organizations
|
||||
* makes any representations about the suitability of this software for
|
||||
* any purpose.
|
||||
*/
|
||||
/*
|
||||
* This file defines the internal interface to the core of CMA
|
||||
* debugging services. (The client interface to debugging services
|
||||
* is provided by cma_debug_client.h).
|
||||
*/
|
||||
|
||||
#ifndef CMA_DEB_CORE
|
||||
#define CMA_DEB_CORE
|
||||
|
||||
/*
|
||||
* INCLUDE FILES
|
||||
*/
|
||||
#include <cma.h>
|
||||
#include <cma_mutex.h>
|
||||
#include <cma_queue.h>
|
||||
#include <cma_tcb_defs.h>
|
||||
#include <cma_util.h>
|
||||
|
||||
/*
|
||||
* CONSTANTS AND MACROS
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* TYPEDEFS
|
||||
*/
|
||||
|
||||
/*FIX-ME* Need to use sizes that are platform specific */
|
||||
typedef long int cma___t_debug_ctx[17];
|
||||
|
||||
/*
|
||||
* Type defing the format of known object lists
|
||||
*/
|
||||
typedef struct CMA__T_KNOWN_OBJECT {
|
||||
cma__t_queue queue; /* Queue header for known objects */
|
||||
cma__t_int_mutex *mutex; /* Mutex to control access to queue */
|
||||
} cma__t_known_object;
|
||||
|
||||
|
||||
/*
|
||||
* Type defining the registration for one debug client (e.g. Ada)
|
||||
*/
|
||||
typedef struct CMA__T_DEB_REGISTRY {
|
||||
cma_t_address entry; /* Client's debug entry point */
|
||||
cma_t_key key; /* Client's context key */
|
||||
cma_t_integer fac; /* Client's debug facility number */
|
||||
cma_t_boolean has_prolog; /* Client's TCBs have std prolog */
|
||||
} cma__t_deb_registry;
|
||||
|
||||
#define cma__c_deb_max_clients 10
|
||||
|
||||
/*
|
||||
* Type defining the global debugging state for all threads.
|
||||
*/
|
||||
typedef struct CMA__T_DEBUG_STATE {
|
||||
/*
|
||||
* The following flag is set if changes were made while in the
|
||||
* debugger that may make the ready lists inconsistent. For
|
||||
* example, if a thread priority is changed in the debugger, the
|
||||
* thread is not moved between queues. Making things consistent
|
||||
* is deferred to when the dispatcher is next invoked -- which we
|
||||
* try to make very soon.
|
||||
*/
|
||||
cma_t_boolean is_inconsistency; /* Ready lists are inconsistent */
|
||||
|
||||
|
||||
cma_t_boolean events_enabled; /* Set if _any_ event is enabled */
|
||||
cma_t_boolean flags[cma__c_debevt__dim];
|
||||
/* Which events are enabled */
|
||||
cma__t_int_tcb *next_to_run; /* TCB of thread to run next */
|
||||
|
||||
cma__t_int_mutex *mutex; /* Mutex for registering clients */
|
||||
cma_t_integer client_count; /* Count of debug clients */
|
||||
cma__t_deb_registry clients[cma__c_deb_max_clients+1];
|
||||
/* Array of current debug clients */
|
||||
} cma__t_debug_state;
|
||||
|
||||
|
||||
/*
|
||||
* Routine that will symbolize and address and print it.
|
||||
*/
|
||||
typedef void (*cma__t_print_symbol) (cma_t_address);
|
||||
|
||||
|
||||
/*
|
||||
* GLOBAL DATA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Variable holding the global debugging state
|
||||
*
|
||||
* (This is primarily written by the debugger interface and read
|
||||
* by the thread dispatcher).
|
||||
*/
|
||||
extern cma__t_debug_state cma__g_debug_state;
|
||||
|
||||
/*
|
||||
* Known object queues
|
||||
*/
|
||||
extern cma__t_known_object cma__g_known_atts;
|
||||
extern cma__t_known_object cma__g_known_cvs;
|
||||
extern cma__t_known_object cma__g_known_mutexes;
|
||||
extern cma__t_known_object cma__g_known_threads;
|
||||
|
||||
/*
|
||||
* INTERNAL INTERFACES
|
||||
*/
|
||||
|
||||
/* Get information while in debugger context */
|
||||
extern void cma__deb_get
|
||||
(cma__t_int_tcb *,cma_t_debug_get,cma_t_address,cma_t_integer,cma_t_integer);
|
||||
|
||||
/* Set information while in debugger context */
|
||||
extern void cma__deb_set (cma__t_int_tcb *,cma_t_debug_set,cma_t_address,cma_t_integer);
|
||||
|
||||
extern void cma__init_debug (void);
|
||||
|
||||
extern void cma__reinit_debug (cma_t_integer);
|
||||
|
||||
extern void cma__deb_anytcb_to_tcb (cma_t_tcb_header *,cma__t_int_tcb **);
|
||||
|
||||
extern void cma__deb_fac_to_client (cma_t_integer,cma_t_key *);
|
||||
|
||||
extern void cma__deb_get_client_info (cma_t_key,cma_t_address *,cma_t_boolean *);
|
||||
|
||||
extern void cma__deb_get_context (cma__t_int_tcb *,cma_t_key,cma_t_address *);
|
||||
|
||||
extern cma__t_int_tcb *cma__deb_get_self_tcb (void);
|
||||
|
||||
extern void cma__deb_get_time_slice (cma_t_interval *);
|
||||
|
||||
extern cma__t_int_tcb *cma__deb_next_tcb
|
||||
(cma__t_int_tcb *,cma_t_integer *,cma_t_integer *,cma_t_boolean *);
|
||||
|
||||
extern cma_t_boolean cma__deb_set_alert (cma__t_int_tcb *);
|
||||
|
||||
extern void cma__deb_set_next_thread (cma__t_int_tcb *);
|
||||
|
||||
extern void cma__deb_set_force_dispatch (cma_t_address );
|
||||
|
||||
extern void cma__deb_set_time_slice (cma_t_interval);
|
||||
|
||||
extern void cma__deb_show_thread
|
||||
(cma__t_int_tcb *,cma_t_boolean,cma_t_boolean,cma___t_debug_ctx,cma__t_eol_routine,
|
||||
cma__t_eol_routine,cma__t_print_symbol);
|
||||
|
||||
extern void
|
||||
cma__deb_show_stats (cma__t_int_tcb *,cma_t_boolean,cma_t_boolean,cma__t_eol_routine,cma__t_eol_routine,cma__t_print_symbol);
|
||||
#endif
|
|
@ -1,195 +0,0 @@
|
|||
/*
|
||||
* (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
|
||||
* (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
|
||||
* (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
|
||||
* (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
|
||||
* To anyone who acknowledges that this file is provided "AS IS" without
|
||||
* any express or implied warranty: permission to use, copy, modify, and
|
||||
* distribute this file for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notices and this notice appears in
|
||||
* all source code copies, and that none of the names listed above be used
|
||||
* in advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. None of these organizations
|
||||
* makes any representations about the suitability of this software for
|
||||
* any purpose.
|
||||
*/
|
||||
/*
|
||||
* Header file providing access to CMA clients that implement
|
||||
* language run-times to the CMA debugger capabilities.
|
||||
*
|
||||
* NOTE: the clients that are able to use this interface is
|
||||
* very limited because clients needing task debugging must have
|
||||
* support in the system debugger as well as here (at present).
|
||||
* The following are the only legitimate clients of this interface:
|
||||
* ADA runtime, C++ tasking library, and CMA.
|
||||
*
|
||||
*FIX-ME* We shall endeavor to extend these capabilities so that the
|
||||
* all-platform CMA debugger CMA_DEBUG and any client can layer
|
||||
* on thread debugging. But that is still an open design problem.
|
||||
* The design here does not preclude that extension (for example,
|
||||
* the identity of the debug-client is indicated in an "open"
|
||||
* manner by using the CMA context key as the identifier.
|
||||
*/
|
||||
|
||||
#ifndef CMA_DEBUG_CLIENT
|
||||
#define CMA_DEBUG_CLIENT
|
||||
|
||||
/*
|
||||
* INCLUDE FILES
|
||||
*/
|
||||
#include <cma.h>
|
||||
|
||||
/*
|
||||
* CONSTANTS AND MACROS
|
||||
*/
|
||||
|
||||
/*
|
||||
* TYPEDEFS
|
||||
*/
|
||||
|
||||
/*
|
||||
* Type describing constants for a valid TCB sentinel.
|
||||
* Exactly one value is valid, but we provide a symbolic name for
|
||||
* at least one invalid sentinel as a convenience.
|
||||
*/
|
||||
typedef enum CMA_T_TCB_SENTINEL {
|
||||
cma_c_tcb_sentinel_nogood = 0, /* Invalid sentinel constant */
|
||||
cma_c_tcb_sentinel = 0x0ACEFACE /* Valid TCB sentinel */
|
||||
} cma_t_tcb_sentinel;
|
||||
|
||||
/*
|
||||
* Type describing pad fields needed to align the "standard prolog"
|
||||
* to the right byte at the front of each TCB. These fields are
|
||||
* free to be put to any use by the client.
|
||||
*
|
||||
* This is 32 bytes long and is fixed at this size for all clients
|
||||
* and CMA, for all time.
|
||||
*/
|
||||
typedef struct CMA_T_TCB_PRIVATE {
|
||||
cma_t_integer pad1;
|
||||
cma_t_integer pad2;
|
||||
cma_t_integer pad3;
|
||||
cma_t_integer pad4;
|
||||
cma_t_integer pad5;
|
||||
cma_t_integer pad6;
|
||||
cma_t_integer pad7;
|
||||
cma_t_integer pad8;
|
||||
} cma_t_tcb_private;
|
||||
|
||||
/*
|
||||
* Type describing the "standard prolog" that clients should use
|
||||
* within their task control blocks. We assume that the client will
|
||||
* store their "task control block" as a per-thread context under
|
||||
* the context key specified here.
|
||||
*/
|
||||
typedef struct CMA_T_TCB_PROLOG {
|
||||
cma_t_tcb_sentinel sentinel; /* Validity sentinel */
|
||||
cma_t_thread client_thread; /* Thread corresonding to task */
|
||||
cma_t_key client_key; /* Context key this is stored under */
|
||||
cma_t_address reserved1; /* Must be zero, reserved to CMA */
|
||||
} cma_t_tcb_prolog;
|
||||
|
||||
/*
|
||||
* Type defining the layout of all TCBs and TASKS. This format
|
||||
* ensures that tasks will be self-identifying to the debugger.
|
||||
* this layout must never change as the CMA DEBUG Clients cannot
|
||||
* be changed after CMA ships.
|
||||
*/
|
||||
typedef struct CMA_T_TCB_HEADER {
|
||||
cma_t_tcb_private IGNORED; /* TCB fields private to the client */
|
||||
cma_t_tcb_prolog prolog; /* The standard prolog goes here */
|
||||
} cma_t_tcb_header;
|
||||
|
||||
|
||||
/*
|
||||
* Type describing the kinds of information that a CMA debug
|
||||
* client can GET about a thread.
|
||||
*/
|
||||
typedef enum CMA_T_DEBUG_GET {
|
||||
/*
|
||||
* All of the following items use a buffer whose size is
|
||||
* four bytes. (That is four must be passed as the buffer_size
|
||||
* parameter to cma_debug_get.)
|
||||
*/
|
||||
cma_c_debget_guardsize = 1, /* Current guard size (bytes) */
|
||||
cma_c_debget_is_held = 2, /* Is it on hold? */
|
||||
cma_c_debget_is_initial = 3, /* Is it the initial thread? */
|
||||
cma_c_debget_number = 4, /* Thread's number */
|
||||
cma_c_debget_stack_ptr = 5, /* Current stack pointer */
|
||||
cma_c_debget_stack_base = 6, /* Stack base address */
|
||||
cma_c_debget_stack_top = 7, /* Stack top address */
|
||||
cma_c_debget_sched_state = 8, /* Scheduler state
|
||||
* 0 - run
|
||||
* 1 - ready
|
||||
* 2 - blocked
|
||||
* 3 - terminated
|
||||
*/
|
||||
cma_c_debget_reserve_size = 9, /* Size of stack reserve (bytes) */
|
||||
cma_c_debget_base_prio = 10, /* Base priority */
|
||||
cma_c_debget_priority = 11, /* Current priority */
|
||||
cma_c_debget_regs = 12, /* Register set (and proc. state) */
|
||||
cma_c_debget_alt_pending = 13, /* Alert is pending */
|
||||
cma_c_debget_alt_a_enable = 14, /* Asynch alert delivery enabled */
|
||||
cma_c_debget_alt_g_enable = 15, /* General alert delivery enabled */
|
||||
cma_c_debget_substate = 16, /* Substate (or wait state) */
|
||||
cma_c_debget_object_addr = 17, /* Address of thread object */
|
||||
cma_c_debget_thkind = 18, /* Kind of thread */
|
||||
cma_c_debget_detached = 19, /* Thread is detached */
|
||||
cma_c_debget_tcb_size = 20, /* TCB size */
|
||||
cma_c_debget_start_pc = 21, /* Start address */
|
||||
cma_c_debget_next_pc = 22, /* Next instruction */
|
||||
cma_c_debget_policy = 23, /* Sched policy */
|
||||
cma_c_debget_stack_yellow = 24, /* Addr of start of guard area */
|
||||
cma_c_debget_stack_default = 25 /* True if on default stack */
|
||||
|
||||
} cma_t_debug_get;
|
||||
|
||||
/*
|
||||
* Type describing the kinds of information that a CMA debug
|
||||
* client can SET (or change) about a thread using cma_debug_set.
|
||||
*/
|
||||
typedef enum CMA_T_DEBUG_SET {
|
||||
/*
|
||||
* All of the following items use a buffer whose size is
|
||||
* four bytes. (That is four must be passed as the buffer_size
|
||||
* parameter to cma_debug_set.)
|
||||
*/
|
||||
cma_c_debset_priority = 1, /* Set the priority */
|
||||
cma_c_debset_policy = 2, /* Set the sched policy */
|
||||
cma_c_debset_hold = 3, /* Put thread on hold */
|
||||
cma_c_debset_regs = 4 /* Set the regs and proc. state */
|
||||
|
||||
} cma_t_debug_set;
|
||||
|
||||
|
||||
/*
|
||||
* GLOBAL DATA
|
||||
*
|
||||
* none
|
||||
*/
|
||||
|
||||
/*
|
||||
* EXTERNAL INTERFACES
|
||||
*/
|
||||
|
||||
/*
|
||||
* Routine to register with the CMA debug dispatcher.
|
||||
*/
|
||||
extern void cma_debug_register (cma_t_address,cma_t_key,cma_t_integer,cma_t_boolean);
|
||||
|
||||
/*
|
||||
* Routine to get get thread state needed by the CMA debug client.
|
||||
*/
|
||||
extern void cma_debug_get (cma_t_thread *,cma_t_debug_get,cma_t_address,cma_t_integer);
|
||||
|
||||
/*
|
||||
* Get thread context given an sp and a key
|
||||
*/
|
||||
extern void cma_debug_get_sp_context (cma_t_address,cma_t_key,cma_t_address *);
|
||||
|
||||
/*
|
||||
* Routine to set thread state as needed by the CMA debug client.
|
||||
*/
|
||||
extern void cma_debug_set (cma_t_thread *,cma_t_debug_set,cma_t_address,cma_t_integer);
|
||||
|
||||
#endif
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
|
||||
* (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
|
||||
* (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
|
||||
* (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
|
||||
* To anyone who acknowledges that this file is provided "AS IS" without
|
||||
* any express or implied warranty: permission to use, copy, modify, and
|
||||
* distribute this file for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notices and this notice appears in
|
||||
* all source code copies, and that none of the names listed above be used
|
||||
* in advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. None of these organizations
|
||||
* makes any representations about the suitability of this software for
|
||||
* any purpose.
|
||||
*/
|
||||
/*
|
||||
* This module is the interface between CMA services and
|
||||
* the platform-specific error reporting mechanism.
|
||||
*/
|
||||
|
||||
#ifndef CMA_ERRORS
|
||||
#define CMA_ERRORS
|
||||
|
||||
/*
|
||||
* INCLUDE FILES
|
||||
*/
|
||||
|
||||
/*
|
||||
* CONSTANTS AND MACROS
|
||||
*/
|
||||
|
||||
/*
|
||||
* TYPEDEFS
|
||||
*/
|
||||
|
||||
/*
|
||||
* GLOBAL DATA
|
||||
*/
|
||||
|
||||
/*
|
||||
* INTERNAL INTERFACES
|
||||
*/
|
||||
|
||||
/*
|
||||
* The cma__bugcheck function will print information to stderr (or sys$error
|
||||
* on VMS), and more extensive information to the file cma_dump.log in the
|
||||
* current working directory.
|
||||
*/
|
||||
extern void cma__bugcheck (char *,...);
|
||||
|
||||
extern void cma__error (int);
|
||||
|
||||
extern void cma__unimplemented (void);
|
||||
|
||||
#endif
|
|
@ -1,182 +0,0 @@
|
|||
/*
|
||||
* (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
|
||||
* (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
|
||||
* (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
|
||||
* (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
|
||||
* To anyone who acknowledges that this file is provided "AS IS" without
|
||||
* any express or implied warranty: permission to use, copy, modify, and
|
||||
* distribute this file for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notices and this notice appears in
|
||||
* all source code copies, and that none of the names listed above be used
|
||||
* in advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. None of these organizations
|
||||
* makes any representations about the suitability of this software for
|
||||
* any purpose.
|
||||
*/
|
||||
/*
|
||||
* Header file for handles
|
||||
*/
|
||||
|
||||
#ifndef CMA_HANDLE
|
||||
#define CMA_HANDLE
|
||||
|
||||
/*
|
||||
* INCLUDE FILES
|
||||
*/
|
||||
|
||||
#include <cma_defs.h>
|
||||
#include <cma_attr.h>
|
||||
|
||||
/*
|
||||
* CONSTANTS AND MACROS
|
||||
*/
|
||||
|
||||
#define cma__validate_attr(handle) \
|
||||
((cma__t_int_attr *)cma__validate_handle ( \
|
||||
(cma_t_handle *)(handle), \
|
||||
cma__c_obj_attr))
|
||||
|
||||
#define cma__validate_cv(handle) \
|
||||
((cma__t_int_cv *)cma__validate_handle ( \
|
||||
(cma_t_handle *)(handle), \
|
||||
cma__c_obj_cv))
|
||||
|
||||
#define cma__validate_mutex(handle) \
|
||||
((cma__t_int_mutex *)cma__validate_handle ( \
|
||||
(cma_t_handle *)(handle), \
|
||||
cma__c_obj_mutex))
|
||||
|
||||
#define cma__validate_tcb(handle) \
|
||||
((cma__t_int_tcb *)cma__validate_handle ( \
|
||||
(cma_t_handle *)(handle), \
|
||||
cma__c_obj_tcb))
|
||||
|
||||
#define cma__validate_stack(handle) \
|
||||
((cma__t_int_stack *)cma__validate_handle ( \
|
||||
(cma_t_handle *)(handle), \
|
||||
cma__c_obj_stack))
|
||||
|
||||
#define cma__validate_null_attr(handle) \
|
||||
((cma__t_int_attr *)cma__validate_handle_null ( \
|
||||
(cma_t_handle *)(handle), \
|
||||
cma__c_obj_attr))
|
||||
|
||||
#define cma__validate_null_cv(handle) \
|
||||
((cma__t_int_cv *)cma__validate_handle_null ( \
|
||||
(cma_t_handle *)(handle), \
|
||||
cma__c_obj_cv))
|
||||
|
||||
#define cma__validate_null_mutex(handle) \
|
||||
((cma__t_int_mutex *)cma__validate_handle_null ( \
|
||||
(cma_t_handle *)(handle), \
|
||||
cma__c_obj_mutex))
|
||||
|
||||
#define cma__validate_null_tcb(handle) \
|
||||
((cma__t_int_tcb *)cma__validate_handle_null ( \
|
||||
(cma_t_handle *)(handle), \
|
||||
cma__c_obj_tcb))
|
||||
|
||||
#define cma__validate_null_stack(handle) \
|
||||
((cma__t_int_stack *)cma__validate_handle_null ( \
|
||||
(cma_t_handle *)(handle), \
|
||||
cma__c_obj_stack))
|
||||
|
||||
#define cma__val_attr_stat(handle,obj) \
|
||||
cma__val_hand_stat ( \
|
||||
(cma_t_handle *)(handle), \
|
||||
cma__c_obj_attr, \
|
||||
(cma__t_object **)obj)
|
||||
|
||||
#define cma__val_cv_stat(handle,obj) \
|
||||
cma__val_hand_stat ( \
|
||||
(cma_t_handle *)(handle), \
|
||||
cma__c_obj_cv, \
|
||||
(cma__t_object **)obj)
|
||||
|
||||
#define cma__val_mutex_stat(handle,obj) \
|
||||
cma__val_hand_stat ( \
|
||||
(cma_t_handle *)(handle), \
|
||||
cma__c_obj_mutex, \
|
||||
(cma__t_object **)obj)
|
||||
|
||||
#define cma__val_tcb_stat(handle) \
|
||||
cma__val_hand_stat ( \
|
||||
(cma_t_handle *)(handle), \
|
||||
cma__c_obj_tcb, \
|
||||
(cma__t_object **)obj)
|
||||
|
||||
#define cma__val_stack_stat(handle,obj) \
|
||||
cma__val_hand_stat ( \
|
||||
(cma_t_handle *)(handle), \
|
||||
cma__c_obj_stack, \
|
||||
(cma__t_object **)obj)
|
||||
|
||||
#define cma__val_nullattr_stat(handle,obj) \
|
||||
cma__val_handnull_stat ( \
|
||||
(cma_t_handle *)(handle), \
|
||||
cma__c_obj_attr, \
|
||||
(cma__t_object **)obj)
|
||||
|
||||
#define cma__val_nullcv_stat(handle,obj) \
|
||||
cma__val_handnull_stat ( \
|
||||
(cma_t_handle *)(handle), \
|
||||
cma__c_obj_cv, \
|
||||
(cma__t_object **)obj)
|
||||
|
||||
#define cma__val_nullmutex_stat(handle,obj) \
|
||||
cma__val_handnull_stat ( \
|
||||
(cma_t_handle *)(handle), \
|
||||
cma__c_obj_mutex, \
|
||||
(cma__t_object **)obj)
|
||||
|
||||
#define cma__val_nulltcb_stat(handle,obj) \
|
||||
cma__val_handnull_stat ( \
|
||||
(cma_t_handle *)(handle), \
|
||||
cma__c_obj_tcb, \
|
||||
(cma__t_object **)obj)
|
||||
|
||||
#define cma__val_nullstack_stat(handle) \
|
||||
cma__val_handnull_stat ( \
|
||||
(cma_t_handle *)(handle), \
|
||||
cma__c_obj_stack, \
|
||||
(cma__t_object **)obj)
|
||||
|
||||
/*
|
||||
* TYPEDEFS
|
||||
*/
|
||||
|
||||
/*
|
||||
* Internal format of a handle (to the outside world it's an array of two
|
||||
* addresses, but we know better).
|
||||
*/
|
||||
typedef struct CMA__T_INT_HANDLE {
|
||||
cma__t_object *pointer; /* Address of internal structure */
|
||||
cma__t_short sequence; /* Sequence number of object */
|
||||
cma__t_short type; /* Type code of object */
|
||||
} cma__t_int_handle;
|
||||
|
||||
/*
|
||||
* GLOBAL DATA
|
||||
*/
|
||||
|
||||
/*
|
||||
* INTERNAL INTERFACES
|
||||
*/
|
||||
|
||||
extern void cma__clear_handle (cma_t_handle *);
|
||||
|
||||
extern void cma__object_to_handle (cma__t_object *,cma_t_handle *);
|
||||
|
||||
extern cma__t_int_attr * cma__validate_default_attr (cma_t_handle *);
|
||||
|
||||
extern cma_t_status cma__val_defattr_stat (cma_t_handle *,cma__t_int_attr **);
|
||||
|
||||
extern cma__t_object * cma__validate_handle (cma_t_handle *,cma_t_natural );
|
||||
|
||||
extern cma_t_status cma__val_hand_stat (cma_t_handle *,cma_t_natural,cma__t_object **);
|
||||
|
||||
extern cma__t_object *cma__validate_handle_null (cma_t_handle *,cma_t_natural);
|
||||
|
||||
extern cma_t_status cma__val_handnull_stat (cma_t_handle *,cma_t_natural,cma__t_object **);
|
||||
|
||||
#endif
|
|
@ -1,114 +0,0 @@
|
|||
/*
|
||||
* (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
|
||||
* (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
|
||||
* (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
|
||||
* (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
|
||||
* To anyone who acknowledges that this file is provided "AS IS" without
|
||||
* any express or implied warranty: permission to use, copy, modify, and
|
||||
* distribute this file for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notices and this notice appears in
|
||||
* all source code copies, and that none of the names listed above be used
|
||||
* in advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. None of these organizations
|
||||
* makes any representations about the suitability of this software for
|
||||
* any purpose.
|
||||
*/
|
||||
/*
|
||||
* Header file for CMA initialization
|
||||
*/
|
||||
|
||||
#ifndef CMA_INIT
|
||||
#define CMA_INIT
|
||||
|
||||
/*
|
||||
* INCLUDE FILES
|
||||
*/
|
||||
#include <dce/cma_host.h>
|
||||
#include <cma_errors.h>
|
||||
|
||||
/*
|
||||
* CONSTANTS AND MACROS
|
||||
*/
|
||||
|
||||
#define cma__c_env_maxattr 0
|
||||
#define cma__c_env_minattr 1
|
||||
#define cma__c_env_maxcond 2
|
||||
#define cma__c_env_mincond 3
|
||||
#define cma__c_env_maxmutex 4
|
||||
#define cma__c_env_minmutex 5
|
||||
#define cma__c_env_maxthread 6
|
||||
#define cma__c_env_minthread 7
|
||||
#define cma__c_env_maxcluster 8
|
||||
#define cma__c_env_mincluster 9
|
||||
#define cma__c_env_maxvp 10
|
||||
#define cma__c_env_multiplex 11
|
||||
#define cma__c_env_trace 12
|
||||
#define cma__c_env_trace_file 13
|
||||
|
||||
#define cma__c_env_count 13
|
||||
|
||||
|
||||
/*
|
||||
* cma__int_init
|
||||
*
|
||||
* Initialize the main body of CMA exactly once.
|
||||
*
|
||||
* We raise an exception if, for some odd reason, there are already threads
|
||||
* in the environment (e.g. kernel threads), and one of them is trying to
|
||||
* initialize CMA before the first thread got all the way through the actual
|
||||
* initialization. This code maintains the invariants: "after successfully
|
||||
* calling CMA_INIT, you can call any CMA function", and "CMA is actually
|
||||
* initialized at most once".
|
||||
*/
|
||||
/*#ifndef _HP_LIBC_R */
|
||||
|
||||
#if defined _HP_LIBC_R ||(defined(SNI_SVR4) && !defined(CMA_INIT_NEEDED))
|
||||
# define cma__int_init()
|
||||
#else
|
||||
# define cma__int_init() { \
|
||||
if (!cma__tac_isset(&cma__g_init_started)) { \
|
||||
if (!cma__test_and_set (&cma__g_init_started)) { \
|
||||
cma__init_static (); \
|
||||
cma__test_and_set (&cma__g_init_done); \
|
||||
} \
|
||||
else if (!cma__tac_isset (&cma__g_init_done)) { \
|
||||
cma__error (cma_s_inialrpro); \
|
||||
}}}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* TYPEDEFS
|
||||
*/
|
||||
|
||||
typedef enum CMA__T_ENV_TYPE {
|
||||
cma__c_env_type_int,
|
||||
cma__c_env_type_file
|
||||
} cma__t_env_type;
|
||||
|
||||
typedef struct CMA__T_ENV {
|
||||
char *name; /* Name of environment variable */
|
||||
cma__t_env_type type; /* Type of variable */
|
||||
cma_t_integer value; /* Numeric value of the variable */
|
||||
} cma__t_env;
|
||||
|
||||
/*
|
||||
* GLOBAL DATA
|
||||
*/
|
||||
|
||||
extern cma__t_env cma__g_env[cma__c_env_count];
|
||||
extern cma__t_atomic_bit cma__g_init_started;
|
||||
extern cma__t_atomic_bit cma__g_init_done;
|
||||
extern char *cma__g_version;
|
||||
|
||||
/*
|
||||
* INTERNAL INTERFACES
|
||||
*/
|
||||
|
||||
extern void
|
||||
cma__init_static (void); /* Initialize static data */
|
||||
|
||||
#if _CMA_OS_ != _CMA__VMS
|
||||
extern void cma__init_atfork (void);
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,84 +0,0 @@
|
|||
/*
|
||||
* (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
|
||||
* (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
|
||||
* (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
|
||||
* (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
|
||||
* To anyone who acknowledges that this file is provided "AS IS" without
|
||||
* any express or implied warranty: permission to use, copy, modify, and
|
||||
* distribute this file for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notices and this notice appears in
|
||||
* all source code copies, and that none of the names listed above be used
|
||||
* in advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. None of these organizations
|
||||
* makes any representations about the suitability of this software for
|
||||
* any purpose.
|
||||
*/
|
||||
/*
|
||||
* Header file for generic list functions operating on singly linked
|
||||
* null-terminated lists. Items may not be REMOVED from the list! The
|
||||
* intent is that the list can be traversed (for read-only operations)
|
||||
* without locking, since insertion is "safe" (though not truely
|
||||
* atomic). THIS ASSUMES THAT THE HARDWARE MAKES WRITES VISIBLE TO READS
|
||||
* IN THE ORDER IN WHICH THEY OCCURRED! WITHOUT SUCH READ/WRITE
|
||||
* ORDERING, IT MAY BE NECESSARY TO INSERT "BARRIERS" TO PRODUCE THE
|
||||
* REQUIRED VISIBILITY!
|
||||
*/
|
||||
|
||||
#ifndef CMA_LIST
|
||||
#define CMA_LIST
|
||||
|
||||
/*
|
||||
* INCLUDE FILES
|
||||
*/
|
||||
|
||||
#include <cma.h>
|
||||
|
||||
/*
|
||||
* CONSTANTS AND MACROS
|
||||
*/
|
||||
|
||||
#define cma__c_null_list ((cma__t_list *)cma_c_null_ptr)
|
||||
|
||||
/*
|
||||
* Test whether a list is empty. Return cma_c_true if so, else
|
||||
* cma_c_false.
|
||||
*/
|
||||
#define cma__list_empty(head) ((head)->link == cma__c_null_list)
|
||||
|
||||
/*
|
||||
* Initialize a queue header to empty.
|
||||
*/
|
||||
#define cma__list_init(head) (void)((head)->link = cma__c_null_list)
|
||||
|
||||
/*
|
||||
* Insert an element in a list following the specified item (or at the
|
||||
* beginning of the list if "list" is the list head). NOTE: insertion
|
||||
* operations should be interlocked by the caller!
|
||||
*/
|
||||
#define cma__list_insert(element,list) (void)( \
|
||||
(element)->link = (list)->link, \
|
||||
(list)->link = (element))
|
||||
|
||||
/*
|
||||
* Return the next item in a list (or the first, if the address is of the
|
||||
* list header)
|
||||
*/
|
||||
#define cma__list_next(element) ((element)->link)
|
||||
|
||||
/*
|
||||
* TYPEDEFS
|
||||
*/
|
||||
|
||||
typedef struct CMA__T_LIST {
|
||||
struct CMA__T_LIST *link; /* Forward link */
|
||||
} cma__t_list;
|
||||
|
||||
/*
|
||||
* GLOBAL DATA
|
||||
*/
|
||||
|
||||
/*
|
||||
* INTERNAL INTERFACES
|
||||
*/
|
||||
|
||||
#endif
|
|
@ -1,230 +0,0 @@
|
|||
/*
|
||||
* (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
|
||||
* (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
|
||||
* (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
|
||||
* (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
|
||||
* To anyone who acknowledges that this file is provided "AS IS" without
|
||||
* any express or implied warranty: permission to use, copy, modify, and
|
||||
* distribute this file for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notices and this notice appears in
|
||||
* all source code copies, and that none of the names listed above be used
|
||||
* in advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. None of these organizations
|
||||
* makes any representations about the suitability of this software for
|
||||
* any purpose.
|
||||
*/
|
||||
/*
|
||||
* Header file for mutex operations
|
||||
*/
|
||||
|
||||
#ifndef CMA_MUTEX
|
||||
#define CMA_MUTEX
|
||||
|
||||
/*
|
||||
* INCLUDE FILES
|
||||
*/
|
||||
|
||||
#include <cma.h>
|
||||
#include <cma_attr.h>
|
||||
#include <cma_defs.h>
|
||||
#include <cma_semaphore_defs.h>
|
||||
#include <cma_sequence.h>
|
||||
#include <cma_tcb_defs.h>
|
||||
#include <cma_stack.h>
|
||||
|
||||
/*
|
||||
* CONSTANTS AND MACROS
|
||||
*/
|
||||
|
||||
/*
|
||||
* TYPEDEFS
|
||||
*/
|
||||
|
||||
typedef struct CMA__T_INT_MUTEX {
|
||||
cma__t_object header; /* Common header (sequence, type) */
|
||||
cma__t_int_attr *attributes; /* Back link */
|
||||
cma__t_int_tcb *owner; /* Current owner (if any) */
|
||||
cma_t_integer nest_count; /* Nesting level for recursive mutex */
|
||||
cma__t_atomic_bit *unlock; /* Pointer used for unlock operation */
|
||||
cma__t_atomic_bit lock; /* Set if currently locked */
|
||||
struct CMA__T_INT_MUTEX *int_lock; /* Internal protection for mutex */
|
||||
cma__t_atomic_bit event; /* Clear when unlock requires action */
|
||||
cma__t_atomic_bit waiters; /* Clear when threads are waiting */
|
||||
cma__t_atomic_bit bitbucket; /* Fake bit to keep friendlies locked */
|
||||
cma_t_mutex_kind mutex_kind; /* Kind of mutex */
|
||||
cma__t_semaphore semaphore; /* Semaphore for low-level wait */
|
||||
} cma__t_int_mutex;
|
||||
|
||||
|
||||
/*
|
||||
* FUNCTIONAL DESCRIPTION:
|
||||
*
|
||||
* Lock a mutex (internal)
|
||||
*
|
||||
* FORMAL PARAMETERS:
|
||||
*
|
||||
* mutex Pointer to mutex object to lock
|
||||
*
|
||||
* IMPLICIT INPUTS:
|
||||
*
|
||||
* none
|
||||
*
|
||||
* IMPLICIT OUTPUTS:
|
||||
*
|
||||
* none
|
||||
*
|
||||
* FUNCTION VALUE:
|
||||
*
|
||||
* none
|
||||
*
|
||||
* SIDE EFFECTS:
|
||||
*
|
||||
* none
|
||||
*/
|
||||
#ifdef NDEBUG
|
||||
# define cma__int_lock(mutex) { \
|
||||
if (cma__test_and_set (&((cma__t_int_mutex *)mutex)->lock)) { \
|
||||
cma_t_status res;\
|
||||
res = cma__int_mutex_block ((cma__t_int_mutex *)mutex); \
|
||||
if (res != cma_s_normal) cma__error (res); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
# define cma__int_lock(mutex) { \
|
||||
cma__t_int_tcb *__ltcb__; \
|
||||
__ltcb__ = cma__get_self_tcb (); \
|
||||
if (cma__test_and_set (&((cma__t_int_mutex *)mutex)->lock)) { \
|
||||
cma_t_status res;\
|
||||
res = cma__int_mutex_block ((cma__t_int_mutex *)mutex); \
|
||||
if (res != cma_s_normal) cma__error (res); \
|
||||
} \
|
||||
((cma__t_int_mutex *)mutex)->owner = __ltcb__; \
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* FUNCTIONAL DESCRIPTION:
|
||||
*
|
||||
* Unlock a mutex (internal)
|
||||
*
|
||||
* FORMAL PARAMETERS:
|
||||
*
|
||||
* mutex Pointer to mutex object to unlock
|
||||
*
|
||||
* IMPLICIT INPUTS:
|
||||
*
|
||||
* none
|
||||
*
|
||||
* IMPLICIT OUTPUTS:
|
||||
*
|
||||
* none
|
||||
*
|
||||
* FUNCTION VALUE:
|
||||
*
|
||||
* none
|
||||
*
|
||||
* SIDE EFFECTS:
|
||||
*
|
||||
* none
|
||||
*/
|
||||
#ifdef NDEBUG
|
||||
# define cma__int_unlock(mutex) { \
|
||||
cma__unset (((cma__t_int_mutex *)mutex)->unlock); \
|
||||
if (!cma__test_and_set (&((cma__t_int_mutex *)mutex)->event)) { \
|
||||
cma_t_status res;\
|
||||
res = cma__int_mutex_unblock ((cma__t_int_mutex *)mutex); \
|
||||
if (res != cma_s_normal) cma__error (res); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
# define cma__int_unlock(mutex) { \
|
||||
cma__t_int_tcb *__utcb__; \
|
||||
__utcb__ = cma__get_self_tcb (); \
|
||||
if (((cma__t_int_mutex *)mutex)->mutex_kind == cma_c_mutex_fast) { \
|
||||
cma__assert_warn ( \
|
||||
(__utcb__ == ((cma__t_int_mutex *)mutex)->owner), \
|
||||
"attempt to release mutx owned by another thread"); \
|
||||
((cma__t_int_mutex *)mutex)->owner = (cma__t_int_tcb *)cma_c_null_ptr; \
|
||||
} \
|
||||
cma__unset (((cma__t_int_mutex *)mutex)->unlock); \
|
||||
if (!cma__test_and_set (&((cma__t_int_mutex *)mutex)->event)) { \
|
||||
cma_t_status res;\
|
||||
res = cma__int_mutex_unblock ((cma__t_int_mutex *)mutex); \
|
||||
if (res != cma_s_normal) cma__error (res); \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* FUNCTIONAL DESCRIPTION:
|
||||
*
|
||||
* cma__int_mutex_delete - Performs work for cma_mutex_delete
|
||||
*
|
||||
* FORMAL PARAMETERS:
|
||||
*
|
||||
* cma__t_mutex _mutex_ - Mutex to be deleted
|
||||
*
|
||||
* IMPLICIT INPUTS:
|
||||
*
|
||||
* none
|
||||
*
|
||||
* IMPLICIT OUTPUTS:
|
||||
*
|
||||
* none
|
||||
*
|
||||
* FUNCTION VALUE:
|
||||
*
|
||||
* none
|
||||
*
|
||||
* SIDE EFFECTS:
|
||||
*
|
||||
* none
|
||||
*/
|
||||
#define cma__int_mutex_delete(_mutex_) { \
|
||||
cma__t_int_mutex *_int_mutex_; \
|
||||
_int_mutex_ = cma__validate_null_mutex (_mutex_); \
|
||||
if (_int_mutex_ == (cma__t_int_mutex *)cma_c_null_ptr) \
|
||||
return; \
|
||||
if (cma__int_mutex_locked (_int_mutex_)) \
|
||||
cma__error (cma_s_in_use); \
|
||||
cma__free_mutex (_int_mutex_); \
|
||||
cma__clear_handle (_mutex_); \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* GLOBAL DATA
|
||||
*/
|
||||
|
||||
extern cma__t_sequence cma__g_mutex_seq;
|
||||
extern cma__t_int_mutex *cma__g_global_lock;
|
||||
|
||||
/*
|
||||
* INTERNAL INTERFACES
|
||||
*/
|
||||
|
||||
extern void cma__destroy_mutex (cma__t_int_mutex *);
|
||||
|
||||
extern void cma__free_mutex (cma__t_int_mutex *);
|
||||
|
||||
extern void cma__free_mutex_nolock (cma__t_int_mutex *);
|
||||
|
||||
extern cma__t_int_mutex * cma__get_first_mutex (cma__t_int_attr *);
|
||||
|
||||
extern cma__t_int_mutex * cma__get_mutex (cma__t_int_attr *);
|
||||
|
||||
extern void cma__init_mutex (void);
|
||||
|
||||
extern cma_t_status cma__int_mutex_block (cma__t_int_mutex *);
|
||||
|
||||
extern cma_t_boolean cma__int_mutex_locked (cma__t_int_mutex *);
|
||||
|
||||
extern cma_t_boolean cma__int_try_lock (cma__t_int_mutex *);
|
||||
|
||||
extern cma_t_status cma__int_mutex_unblock (cma__t_int_mutex *);
|
||||
|
||||
extern cma_t_boolean cma__mutex_locked (cma_t_mutex);
|
||||
|
||||
extern void cma__reinit_mutex (cma_t_integer);
|
||||
|
||||
#endif
|
|
@ -1,279 +0,0 @@
|
|||
/*
|
||||
* (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
|
||||
* (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
|
||||
* (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
|
||||
* (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
|
||||
* To anyone who acknowledges that this file is provided "AS IS" without
|
||||
* any express or implied warranty: permission to use, copy, modify, and
|
||||
* distribute this file for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notices and this notice appears in
|
||||
* all source code copies, and that none of the names listed above be used
|
||||
* in advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. None of these organizations
|
||||
* makes any representations about the suitability of this software for
|
||||
* any purpose.
|
||||
*/
|
||||
/*
|
||||
* Header file for priority scheduling
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CMA_SCHED
|
||||
#define CMA_SCHED
|
||||
|
||||
/*
|
||||
* INCLUDE FILES
|
||||
*/
|
||||
|
||||
/*
|
||||
* CONSTANTS AND MACROS
|
||||
*/
|
||||
|
||||
/*
|
||||
* Scaling factor for integer priority calculations
|
||||
*/
|
||||
#define cma__c_prio_scale 8
|
||||
|
||||
#if _CMA_VENDOR_ == _CMA__APOLLO
|
||||
/*
|
||||
* FIX-ME: Apollo cc 6.8 blows contant folded "<<" and ">>"
|
||||
*/
|
||||
# define cma__scale_up(exp) ((exp) * 256)
|
||||
# define cma__scale_dn(exp) ((exp) / 256)
|
||||
#else
|
||||
# define cma__scale_up(exp) ((exp) << cma__c_prio_scale)
|
||||
# define cma__scale_dn(exp) ((exp) >> cma__c_prio_scale)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Min. num. of ticks between self-adjustments for priority adjusting policies.
|
||||
*/
|
||||
#define cma__c_prio_interval 10
|
||||
|
||||
|
||||
/*
|
||||
* Number of queues in each class of queues
|
||||
*/
|
||||
#define cma__c_prio_n_id 1 /* Very-low-priority class threads */
|
||||
#define cma__c_prio_n_bg 8 /* Background class threads */
|
||||
#define cma__c_prio_n_0 1 /* Very low priority throughput quartile */
|
||||
#define cma__c_prio_n_1 2 /* Low priority throughput quartile */
|
||||
#define cma__c_prio_n_2 3 /* Medium priority throughput quartile */
|
||||
#define cma__c_prio_n_3 4 /* High priority throughput quartile */
|
||||
#define cma__c_prio_n_rt 1 /* Real Time priority queues */
|
||||
|
||||
/*
|
||||
* Number of queues to skip (offset) to get to the queues in this section of LA
|
||||
*/
|
||||
#define cma__c_prio_o_id 0
|
||||
#define cma__c_prio_o_bg cma__c_prio_o_id + cma__c_prio_n_id
|
||||
#define cma__c_prio_o_0 cma__c_prio_o_bg + cma__c_prio_n_bg
|
||||
#define cma__c_prio_o_1 cma__c_prio_o_0 + cma__c_prio_n_0
|
||||
#define cma__c_prio_o_2 cma__c_prio_o_1 + cma__c_prio_n_1
|
||||
#define cma__c_prio_o_3 cma__c_prio_o_2 + cma__c_prio_n_2
|
||||
#define cma__c_prio_o_rt cma__c_prio_o_3 + cma__c_prio_n_3
|
||||
|
||||
/*
|
||||
* Ada_low: These threads are queued in the background queues, thus there
|
||||
* must be enough queues to allow one queue for each Ada priority below the
|
||||
* Ada default.
|
||||
*/
|
||||
#define cma__c_prio_o_al cma__c_prio_o_bg
|
||||
|
||||
/*
|
||||
* Total number of ready queues, for declaration purposes
|
||||
*/
|
||||
#define cma__c_prio_n_tot \
|
||||
cma__c_prio_n_id + cma__c_prio_n_bg + cma__c_prio_n_rt \
|
||||
+ cma__c_prio_n_0 + cma__c_prio_n_1 + cma__c_prio_n_2 + cma__c_prio_n_3
|
||||
|
||||
/*
|
||||
* Formulae for determining a thread's priority. Variable priorities (such
|
||||
* as foreground and background) are scaled values.
|
||||
*/
|
||||
#define cma__sched_priority(tcb) \
|
||||
((tcb)->sched.class == cma__c_class_fore ? cma__sched_prio_fore (tcb) \
|
||||
:((tcb)->sched.class == cma__c_class_back ? cma__sched_prio_back (tcb) \
|
||||
:((tcb)->sched.class == cma__c_class_rt ? cma__sched_prio_rt (tcb) \
|
||||
:((tcb)->sched.class == cma__c_class_idle ? cma__sched_prio_idle (tcb) \
|
||||
:(cma__bugcheck ("cma__sched_priority: unrecognized class"), 0) ))))
|
||||
|
||||
#define cma__sched_prio_fore(tcb) cma__sched_prio_fore_var (tcb)
|
||||
#define cma__sched_prio_back(tcb) ((tcb)->sched.fixed_prio \
|
||||
? cma__sched_prio_back_fix (tcb) : cma__sched_prio_back_var (tcb) )
|
||||
#define cma__sched_prio_rt(tcb) ((tcb)->sched.priority)
|
||||
#define cma__sched_prio_idle(tcb) ((tcb)->sched.priority)
|
||||
|
||||
#define cma__sched_prio_back_fix(tcb) \
|
||||
(cma__g_prio_bg_min + (cma__g_prio_bg_max - cma__g_prio_bg_min) \
|
||||
* ((tcb)->sched.priority + cma__c_prio_o_al - cma__c_prio_o_bg) \
|
||||
/ cma__c_prio_n_bg)
|
||||
|
||||
/*
|
||||
* FIX-ME: Enable after modeling (if we like it)
|
||||
*/
|
||||
#if 1
|
||||
# define cma__sched_prio_fore_var(tcb) \
|
||||
((cma__g_prio_fg_max + cma__g_prio_fg_min)/2)
|
||||
# define cma__sched_prio_back_var(tcb) \
|
||||
((cma__g_prio_bg_max + cma__g_prio_bg_min)/2)
|
||||
#else
|
||||
# define cma__sched_prio_back_var(tcb) cma__sched_prio_fore_var (tcb)
|
||||
|
||||
# if 1
|
||||
/*
|
||||
* Re-scale, since the division removes the scale factor.
|
||||
* Scale and multiply before dividing to avoid loss of precision.
|
||||
*/
|
||||
# define cma__sched_prio_fore_var(tcb) \
|
||||
((cma__g_vp_count * cma__scale_up((tcb)->sched.tot_time)) \
|
||||
/ (tcb)->sched.cpu_time)
|
||||
# else
|
||||
/*
|
||||
* Re-scale, since the division removes the scale factor.
|
||||
* Scale and multiply before dividing to avoid loss of precision.
|
||||
* Left shift the numerator to multiply by two.
|
||||
*/
|
||||
# define cma__sched_prio_fore_var(tcb) \
|
||||
(((cma__g_vp_count * cma__scale_up((tcb)->sched.tot_time) \
|
||||
* (tcb)->sched.priority * cma__g_init_frac_sum) << 1) \
|
||||
/ ((tcb)->sched.cpu_time * (tcb)->sched.priority * cma__g_init_frac_sum \
|
||||
+ (tcb)->sched.tot_time))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Update weighted-averaged, scaled tick counters
|
||||
*/
|
||||
#define cma__sched_update_time(ave, new) \
|
||||
(ave) = (ave) - ((cma__scale_dn((ave)) - (new)) << (cma__c_prio_scale - 4))
|
||||
|
||||
#define cma__sched_parameterize(tcb, policy) { \
|
||||
switch (policy) { \
|
||||
case cma_c_sched_fifo : { \
|
||||
(tcb)->sched.rtb = cma_c_true; \
|
||||
(tcb)->sched.spp = cma_c_true; \
|
||||
(tcb)->sched.fixed_prio = cma_c_true; \
|
||||
(tcb)->sched.class = cma__c_class_rt; \
|
||||
break; \
|
||||
} \
|
||||
case cma_c_sched_rr : { \
|
||||
(tcb)->sched.rtb = cma_c_false; \
|
||||
(tcb)->sched.spp = cma_c_true; \
|
||||
(tcb)->sched.fixed_prio = cma_c_true; \
|
||||
(tcb)->sched.class = cma__c_class_rt; \
|
||||
break; \
|
||||
} \
|
||||
case cma_c_sched_throughput : { \
|
||||
(tcb)->sched.rtb = cma_c_false; \
|
||||
(tcb)->sched.spp = cma_c_false; \
|
||||
(tcb)->sched.fixed_prio = cma_c_false; \
|
||||
(tcb)->sched.class = cma__c_class_fore; \
|
||||
break; \
|
||||
} \
|
||||
case cma_c_sched_background : { \
|
||||
(tcb)->sched.rtb = cma_c_false; \
|
||||
(tcb)->sched.spp = cma_c_false; \
|
||||
(tcb)->sched.fixed_prio = cma_c_false; \
|
||||
(tcb)->sched.class = cma__c_class_back; \
|
||||
break; \
|
||||
} \
|
||||
case cma_c_sched_ada_low : { \
|
||||
(tcb)->sched.rtb = cma_c_false; \
|
||||
(tcb)->sched.spp = cma_c_true; \
|
||||
(tcb)->sched.fixed_prio = cma_c_true; \
|
||||
(tcb)->sched.class = cma__c_class_back; \
|
||||
break; \
|
||||
} \
|
||||
case cma_c_sched_idle : { \
|
||||
(tcb)->sched.rtb = cma_c_false; \
|
||||
(tcb)->sched.spp = cma_c_false; \
|
||||
(tcb)->sched.fixed_prio = cma_c_false; \
|
||||
(tcb)->sched.class = cma__c_class_idle; \
|
||||
break; \
|
||||
} \
|
||||
default : { \
|
||||
cma__bugcheck ("cma__sched_parameterize: bad scheduling Policy"); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
/*
|
||||
* TYPEDEFS
|
||||
*/
|
||||
|
||||
/*
|
||||
* Scheduling classes
|
||||
*/
|
||||
typedef enum CMA__T_SCHED_CLASS {
|
||||
cma__c_class_rt,
|
||||
cma__c_class_fore,
|
||||
cma__c_class_back,
|
||||
cma__c_class_idle
|
||||
} cma__t_sched_class;
|
||||
|
||||
/*
|
||||
* GLOBAL DATA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Minimuma and maximum prioirities, for foreground and background threads,
|
||||
* as of the last time the scheduler ran. (Scaled once.)
|
||||
*/
|
||||
extern cma_t_integer cma__g_prio_fg_min;
|
||||
extern cma_t_integer cma__g_prio_fg_max;
|
||||
extern cma_t_integer cma__g_prio_bg_min;
|
||||
extern cma_t_integer cma__g_prio_bg_max;
|
||||
|
||||
/*
|
||||
* The "m" values are the slopes of the four sections of linear approximation.
|
||||
*
|
||||
* cma__g_prio_m_I = 4*N(I)/cma__g_prio_range (Scaled once.)
|
||||
*/
|
||||
extern cma_t_integer cma__g_prio_m_0,
|
||||
cma__g_prio_m_1,
|
||||
cma__g_prio_m_2,
|
||||
cma__g_prio_m_3;
|
||||
|
||||
/*
|
||||
* The "b" values are the intercepts of the four sections of linear approx.
|
||||
* (Not scaled.)
|
||||
*
|
||||
* cma__g_prio_b_I = -N(I)*(I*prio_max + (4-I)*prio_min)/prio_range + prio_o_I
|
||||
*/
|
||||
extern cma_t_integer cma__g_prio_b_0,
|
||||
cma__g_prio_b_1,
|
||||
cma__g_prio_b_2,
|
||||
cma__g_prio_b_3;
|
||||
|
||||
/*
|
||||
* The "p" values are the end points of the four sections of linear approx.
|
||||
*
|
||||
* cma__g_prio_p_I = cma__g_prio_fg_min + (I/4)*cma__g_prio_range
|
||||
*
|
||||
* [cma__g_prio_p_0 is not defined since it is not used (also, it is the same
|
||||
* as cma__g_prio_fg_min).] (Scaled once.)
|
||||
*/
|
||||
extern cma_t_integer cma__g_prio_p_1,
|
||||
cma__g_prio_p_2,
|
||||
cma__g_prio_p_3;
|
||||
|
||||
/*
|
||||
* Points to the next queue for the dispatcher to check for ready threads.
|
||||
*/
|
||||
extern cma_t_integer cma__g_next_ready_queue;
|
||||
|
||||
/*
|
||||
* Points to the queues of virtual processors (for preempt victim search)
|
||||
*/
|
||||
extern cma__t_queue cma__g_run_vps;
|
||||
extern cma__t_queue cma__g_susp_vps;
|
||||
extern cma_t_integer cma__g_vp_count;
|
||||
|
||||
/*
|
||||
* INTERNAL INTERFACES
|
||||
*/
|
||||
|
||||
#endif
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
|
||||
* (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
|
||||
* (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
|
||||
* (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
|
||||
* To anyone who acknowledges that this file is provided "AS IS" without
|
||||
* any express or implied warranty: permission to use, copy, modify, and
|
||||
* distribute this file for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notices and this notice appears in
|
||||
* all source code copies, and that none of the names listed above be used
|
||||
* in advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. None of these organizations
|
||||
* makes any representations about the suitability of this software for
|
||||
* any purpose.
|
||||
*/
|
||||
/*
|
||||
* Header file for semaphore structure definition.
|
||||
*/
|
||||
#ifndef CMA_SEMAPHORE_DEFS
|
||||
#define CMA_SEMAPHORE_DEFS
|
||||
|
||||
/*
|
||||
* INCLUDE FILES
|
||||
*/
|
||||
#include <cma.h>
|
||||
#include <cma_queue.h>
|
||||
#include <cma_defs.h>
|
||||
|
||||
/*
|
||||
* CONSTANTS AND MACROS
|
||||
*/
|
||||
|
||||
#define cma__c_semaphore_timeout 1
|
||||
#define cma__c_semaphore_event 0
|
||||
#define cma__c_select_timeout 2
|
||||
|
||||
/*
|
||||
* TYPEDEFS
|
||||
*/
|
||||
|
||||
typedef struct CMA__T_SEMAPHORE {
|
||||
cma__t_queue queue;
|
||||
cma__t_atomic_bit nopending;
|
||||
} cma__t_semaphore;
|
||||
|
||||
#endif
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
|
||||
* (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
|
||||
* (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
|
||||
* (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
|
||||
* To anyone who acknowledges that this file is provided "AS IS" without
|
||||
* any express or implied warranty: permission to use, copy, modify, and
|
||||
* distribute this file for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notices and this notice appears in
|
||||
* all source code copies, and that none of the names listed above be used
|
||||
* in advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. None of these organizations
|
||||
* makes any representations about the suitability of this software for
|
||||
* any purpose.
|
||||
*/
|
||||
/*
|
||||
* Header file for sequence generator functions
|
||||
*/
|
||||
|
||||
#ifndef CMA_SEQUENCE
|
||||
#define CMA_SEQUENCE
|
||||
|
||||
/*
|
||||
* INCLUDE FILES
|
||||
*/
|
||||
|
||||
/*
|
||||
* CONSTANTS AND MACROS
|
||||
*/
|
||||
|
||||
/*
|
||||
* TYPEDEFS
|
||||
*/
|
||||
|
||||
#ifndef __STDC__
|
||||
struct CMA__T_INT_MUTEX;
|
||||
#endif
|
||||
|
||||
typedef struct CMA__T_SEQUENCE {
|
||||
struct CMA__T_INT_MUTEX *mutex; /* Serialize access to counter */
|
||||
cma_t_natural seq; /* Sequence number for object */
|
||||
} cma__t_sequence;
|
||||
|
||||
/*
|
||||
* GLOBAL DATA
|
||||
*/
|
||||
|
||||
/*
|
||||
* INTERNAL INTERFACES
|
||||
*/
|
||||
|
||||
extern cma_t_natural cma__assign_sequence (cma__t_sequence *);
|
||||
|
||||
extern void cma__init_sequence (cma__t_sequence *);
|
||||
|
||||
#endif
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
|
||||
* (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
|
||||
* (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
|
||||
* (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
|
||||
* To anyone who acknowledges that this file is provided "AS IS" without
|
||||
* any express or implied warranty: permission to use, copy, modify, and
|
||||
* distribute this file for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notices and this notice appears in
|
||||
* all source code copies, and that none of the names listed above be used
|
||||
* in advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. None of these organizations
|
||||
* makes any representations about the suitability of this software for
|
||||
* any purpose.
|
||||
*/
|
||||
/*
|
||||
* Header file for stack management
|
||||
*/
|
||||
#ifndef CMA_STACK
|
||||
#define CMA_STACK
|
||||
|
||||
/*
|
||||
* INCLUDE FILES
|
||||
*/
|
||||
|
||||
#include <cma_tcb_defs.h>
|
||||
#include <cma.h>
|
||||
#include <cma_attr.h>
|
||||
#include <cma_queue.h>
|
||||
#include <cma_stack_int.h>
|
||||
|
||||
/*
|
||||
* CONSTANTS AND MACROS
|
||||
*/
|
||||
|
||||
#if _CMA_UNIPROCESSOR_
|
||||
# define cma__get_self_tcb() (cma__g_current_thread)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Round the given value (a) upto cma__g_chunk_size
|
||||
*/
|
||||
#define cma__roundup_chunksize(a) (cma__roundup(a,cma__g_chunk_size))
|
||||
|
||||
/*
|
||||
* TYPEDEFS
|
||||
*/
|
||||
|
||||
/*
|
||||
* GLOBAL DATA
|
||||
*/
|
||||
|
||||
extern cma__t_list cma__g_stack_clusters;
|
||||
extern cma__t_int_tcb *cma__g_current_thread;
|
||||
extern cma_t_integer cma__g_chunk_size;
|
||||
|
||||
/*
|
||||
* INTERNAL INTERFACES
|
||||
*/
|
||||
|
||||
extern void cma__assign_stack (cma__t_int_stack *,cma__t_int_tcb *);
|
||||
|
||||
extern void cma__free_stack (cma__t_int_stack *);
|
||||
|
||||
extern void cma__free_stack_list (cma__t_queue *);
|
||||
|
||||
#if !_CMA_UNIPROCESSOR_
|
||||
extern cma__t_int_tcb * cma__get_self_tcb (void);
|
||||
#endif
|
||||
|
||||
extern cma__t_int_tcb * cma__get_sp_tcb (cma_t_address);
|
||||
|
||||
extern cma__t_int_stack * cma__get_stack (cma__t_int_attr *);
|
||||
|
||||
extern void cma__init_stack (void);
|
||||
|
||||
extern void cma__reinit_stack (cma_t_integer);
|
||||
|
||||
#if _CMA_PROTECT_MEMORY_
|
||||
extern void cma__remap_stack_holes (void);
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,136 +0,0 @@
|
|||
/*
|
||||
* (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
|
||||
* (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
|
||||
* (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
|
||||
* (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
|
||||
* To anyone who acknowledges that this file is provided "AS IS" without
|
||||
* any express or implied warranty: permission to use, copy, modify, and
|
||||
* distribute this file for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notices and this notice appears in
|
||||
* all source code copies, and that none of the names listed above be used
|
||||
* in advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. None of these organizations
|
||||
* makes any representations about the suitability of this software for
|
||||
* any purpose.
|
||||
*/
|
||||
/*
|
||||
* Header file for stack management (internal to cma_stack.c, but
|
||||
* separate for convenience, and unit testing).
|
||||
*/
|
||||
|
||||
#ifndef CMA_STACK_INT
|
||||
#define CMA_STACK_INT
|
||||
|
||||
/*
|
||||
* INCLUDE FILES
|
||||
*/
|
||||
|
||||
#include <cma.h>
|
||||
#include <cma_queue.h>
|
||||
#include <cma_list.h>
|
||||
#include <cma_tcb_defs.h>
|
||||
|
||||
/*
|
||||
* CONSTANTS AND MACROS
|
||||
*/
|
||||
|
||||
#define cma___c_first_free_chunk 0
|
||||
#define cma___c_min_count 2 /* Smallest number of chunks to leave */
|
||||
#define cma___c_end (-1) /* End of free list (flag) */
|
||||
#define cma__c_yellow_size 0
|
||||
|
||||
/*
|
||||
* Cluster types
|
||||
*/
|
||||
#define cma___c_cluster 0 /* Default cluster */
|
||||
#define cma___c_bigstack 1 /* Looks like a cluster, but it's a stack */
|
||||
|
||||
|
||||
#define cma___c_null_cluster (cma___t_cluster *)cma_c_null_ptr
|
||||
|
||||
|
||||
/*
|
||||
* TYPEDEFS
|
||||
*/
|
||||
|
||||
#ifndef __STDC__
|
||||
struct CMA__T_INT_STACK;
|
||||
#endif
|
||||
|
||||
typedef cma_t_natural cma___t_index; /* Type for chunk index */
|
||||
|
||||
typedef struct CMA___T_CLU_DESC {
|
||||
cma__t_list list; /* Queue element for cluster list */
|
||||
cma_t_integer type; /* Type of cluster */
|
||||
cma_t_address stacks;
|
||||
cma_t_address limit;
|
||||
} cma___t_clu_desc;
|
||||
|
||||
typedef union CMA___T_MAP_ENTRY {
|
||||
struct {
|
||||
cma__t_int_tcb *tcb; /* TCB associated with stack chunk */
|
||||
struct CMA__T_INT_STACK *stack; /* Stack desc. ass. with stack chunk */
|
||||
} mapped;
|
||||
struct {
|
||||
cma___t_index size; /* Number of chunks in block */
|
||||
cma___t_index next; /* Next free block */
|
||||
} free;
|
||||
} cma___t_map_entry;
|
||||
|
||||
/*
|
||||
* NOTE: It is VERY IMPORTANT that both cma___t_cluster and cma___t_bigstack
|
||||
* begin with the cma___t_clu_desc structure, as there is some code in the
|
||||
* stack manager that relies on being able to treat both as equivalent!
|
||||
*/
|
||||
typedef struct CMA___T_CLUSTER {
|
||||
cma___t_clu_desc desc; /* Describe this cluster */
|
||||
cma___t_map_entry map[cma__c_chunk_count]; /* thread map */
|
||||
cma___t_index free; /* First free chunk index */
|
||||
} cma___t_cluster;
|
||||
|
||||
/*
|
||||
* NOTE: It is VERY IMPORTANT that both cma___t_cluster and cma___t_bigstack
|
||||
* begin with the cma___t_clu_desc structure, as there is some code in the
|
||||
* stack manager that relies on being able to treat both as equivalent!
|
||||
*/
|
||||
typedef struct CMA___T_BIGSTACK {
|
||||
cma___t_clu_desc desc; /* Describe this cluster */
|
||||
cma__t_int_tcb *tcb; /* TCB associated with stack */
|
||||
struct CMA__T_INT_STACK *stack; /* Stack desc. ass. with stack */
|
||||
cma_t_natural size; /* Size of big stack */
|
||||
cma_t_boolean in_use; /* Set if allocated */
|
||||
} cma___t_bigstack;
|
||||
|
||||
#if _CMA_PROTECT_MEMORY_
|
||||
typedef struct CMA___T_INT_HOLE {
|
||||
cma__t_queue link; /* Link holes together */
|
||||
cma_t_boolean protected; /* Set when pages are protected */
|
||||
cma_t_address first; /* First protected byte */
|
||||
cma_t_address last; /* Last protected byte */
|
||||
} cma___t_int_hole;
|
||||
#endif
|
||||
|
||||
typedef struct CMA__T_INT_STACK {
|
||||
cma__t_object header; /* Common header (sequence, type info */
|
||||
cma__t_int_attr *attributes; /* Backpointer to attr obj */
|
||||
cma___t_cluster *cluster; /* Stack's cluster */
|
||||
cma_t_address stack_base; /* base address of stack */
|
||||
cma_t_address yellow_zone; /* first address of yellow zone */
|
||||
cma_t_address last_guard; /* last address of guard pages */
|
||||
cma_t_natural first_chunk; /* First chunk allocated */
|
||||
cma_t_natural chunk_count; /* Count of chunks allocated */
|
||||
cma__t_int_tcb *tcb; /* TCB backpointer */
|
||||
#if _CMA_PROTECT_MEMORY_
|
||||
cma___t_int_hole hole; /* Description of hole */
|
||||
#endif
|
||||
} cma__t_int_stack;
|
||||
|
||||
/*
|
||||
* GLOBAL DATA
|
||||
*/
|
||||
|
||||
/*
|
||||
* INTERNAL INTERFACES
|
||||
*/
|
||||
|
||||
#endif
|
|
@ -1,269 +0,0 @@
|
|||
/*
|
||||
* (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
|
||||
* (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
|
||||
* (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
|
||||
* (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
|
||||
* To anyone who acknowledges that this file is provided "AS IS" without
|
||||
* any express or implied warranty: permission to use, copy, modify, and
|
||||
* distribute this file for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notices and this notice appears in
|
||||
* all source code copies, and that none of the names listed above be used
|
||||
* in advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. None of these organizations
|
||||
* makes any representations about the suitability of this software for
|
||||
* any purpose.
|
||||
*/
|
||||
/*
|
||||
* TCB-related type definitions.
|
||||
*/
|
||||
|
||||
#ifndef CMA_TCB_DEFS
|
||||
#define CMA_TCB_DEFS
|
||||
|
||||
/*
|
||||
* INCLUDE FILES
|
||||
*/
|
||||
# if !_CMA_THREAD_SYNC_IO_
|
||||
# include <cma_thread_io.h>
|
||||
# endif
|
||||
#include <cma.h>
|
||||
#include <cma_debug_client.h>
|
||||
#include <cma_attr.h>
|
||||
#include <cma_defs.h>
|
||||
#include <cma_handle.h>
|
||||
#include <cma_queue.h>
|
||||
#if _CMA_OS_ == _CMA__UNIX
|
||||
# if defined(SNI_DCOSX)
|
||||
# include <sys/ucontext.h>
|
||||
# endif
|
||||
# include <signal.h>
|
||||
#endif
|
||||
#include <cma_sched.h>
|
||||
|
||||
/*
|
||||
* CONSTANTS AND MACROS
|
||||
*/
|
||||
|
||||
#if _CMA_PLATFORM_ == _CMA__IBMR2_UNIX
|
||||
# define cma__c_ibmr2_ctx_stack_size 2048
|
||||
# define cma__c_ibmr2_ctx_stack_top (cma__c_ibmr2_ctx_stack_size - 1)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* TYPEDEFS
|
||||
*/
|
||||
|
||||
#ifndef __STDC__
|
||||
# if _CMA_HARDWARE_ != _CMA__HPPA
|
||||
struct CMA__T_SEMAPHORE;
|
||||
# endif
|
||||
struct CMA__T_INT_CV;
|
||||
struct CMA__T_INT_MUTEX;
|
||||
struct CMA__T_INT_TCB;
|
||||
#endif
|
||||
|
||||
typedef cma_t_address *cma__t_context_list;
|
||||
|
||||
typedef struct CMA__T_TCB_PAD {
|
||||
/*
|
||||
* Adjust to align the tcb prolog at byte 32.
|
||||
* 12 bytes are required as object header is currently
|
||||
* 20 bytes long.
|
||||
*/
|
||||
cma_t_integer pad1; /* pad bytes */
|
||||
cma_t_integer pad2; /* pad bytes */
|
||||
cma_t_integer pad3; /* pad bytes */
|
||||
} cma__t_tcb_pad;
|
||||
|
||||
#if (_CMA_OS_ == _CMA__UNIX) && !_CMA_THREAD_SYNC_IO_
|
||||
typedef struct CMA__T_TCB_SELECT {
|
||||
cma__t_queue queue;
|
||||
#if (_CMA_UNIX_TYPE != _CMA__SVR4)
|
||||
cma__t_file_mask *rfds;
|
||||
cma__t_file_mask *wfds;
|
||||
cma__t_file_mask *efds;
|
||||
#else
|
||||
cma__t_poll_info poll_info;
|
||||
#endif /* (_CMA_UNIX_TYPE != _CMA__SVR4) */
|
||||
cma_t_integer nfound;
|
||||
} cma__t_tcb_select;
|
||||
#endif
|
||||
|
||||
typedef struct CMA__T_TCB_TIME {
|
||||
cma__t_queue queue; /* must be first entry! */
|
||||
cma_t_integer mode;
|
||||
struct CMA__T_SEMAPHORE *semaphore; /* used for timed semaphores */
|
||||
cma_t_date_time wakeup_time;
|
||||
cma_t_integer quanta_remaining;
|
||||
} cma__t_tcb_time;
|
||||
|
||||
typedef enum CMA__T_DEBEVT {
|
||||
cma__c_debevt_activating = 1, /* First transition to running */
|
||||
cma__c_debevt_running = 2, /* Any transition to running */
|
||||
cma__c_debevt_preempting = 3, /* Preemted (replaced) another thread */
|
||||
cma__c_debevt_blocking = 4, /* Any transition to blocked */
|
||||
cma__c_debevt_terminating = 5, /* Final state transition */
|
||||
cma__c_debevt_term_alert = 6, /* Terminated due to alert/cancel */
|
||||
cma__c_debevt_term_exc = 7, /* Terminated due to exception */
|
||||
cma__c_debevt_exc_handled = 8 /* Exception is being handled */
|
||||
} cma__t_debevt;
|
||||
|
||||
#define cma__c_debevt__first ((cma_t_integer)cma__c_debevt_activating)
|
||||
#define cma__c_debevt__last ((cma_t_integer)cma__c_debevt_exc_handled)
|
||||
#define cma__c_debevt__dim (cma__c_debevt__last + 1)
|
||||
|
||||
/*
|
||||
* Type defining thread substate, which is used by the debugger.
|
||||
* If the state is blocked, substate indicates WHY the thread is blocked.
|
||||
*/
|
||||
typedef enum CMA__T_SUBSTATE {
|
||||
cma__c_substa_normal = 0,
|
||||
cma__c_substa_mutex = 1,
|
||||
cma__c_substa_cv = 2,
|
||||
cma__c_substa_timed_cv = 3,
|
||||
cma__c_substa_term_alt = 4,
|
||||
cma__c_substa_term_exc = 5,
|
||||
cma__c_substa_delay =6,
|
||||
cma__c_substa_not_yet_run = 7
|
||||
} cma__t_substate;
|
||||
#define cma__c_substa__first ((cma_t_integer)cma__c_substa_normal)
|
||||
#define cma__c_substa__last ((cma_t_integer)cma__c_substa_not_yet_run)
|
||||
#define cma__c_substa__dim (cma__c_substa__last + 1)
|
||||
|
||||
|
||||
/*
|
||||
* Per-thread state for the debugger
|
||||
*/
|
||||
typedef struct CMA__T_TCB_DEBUG {
|
||||
cma_t_boolean on_hold; /* Thread was put on hold by debugger */
|
||||
cma_t_boolean activated; /* Activation event was reported */
|
||||
cma_t_boolean did_preempt; /* Thread preempted prior one */
|
||||
cma_t_address start_pc; /* Start routine address */
|
||||
cma_t_address object_addr; /* Addr of thread object */
|
||||
cma__t_substate substate; /* Reason blocked, terminated, etc.*/
|
||||
cma_t_boolean notify_debugger;/* Notify debugger thread is running */
|
||||
cma_t_address SPARE2; /* SPARE */
|
||||
cma_t_address SPARE3; /* SPARE */
|
||||
struct CMA__T_INT_TCB
|
||||
*preempted_tcb; /* TCB of thread that got preempted */
|
||||
cma_t_boolean flags[cma__c_debevt__dim];
|
||||
/* Events enabled for this thread */
|
||||
} cma__t_tcb_debug;
|
||||
|
||||
typedef struct CMA__T_TCB_SCHED {
|
||||
cma_t_integer adj_time; /* Abs. time in ticks of last prio adj */
|
||||
cma_t_integer tot_time; /* Weighted ave in ticks (scaled) */
|
||||
cma_t_integer time_stamp; /* Abs. time in ticks of last update */
|
||||
cma_t_integer cpu_time; /* Weighted average in ticks */
|
||||
cma_t_integer cpu_ticks; /* # of ticks while comp. (scaled) */
|
||||
cma_t_integer q_num; /* Number of last ready queue on */
|
||||
cma_t_priority priority; /* Thread priority */
|
||||
cma_t_sched_policy policy; /* Scheduling policy of thread */
|
||||
cma_t_boolean rtb; /* "Run 'Till Block" scheduling */
|
||||
cma_t_boolean spp; /* "Strict Priority Preemption" sched */
|
||||
cma_t_boolean fixed_prio; /* Fixed priority */
|
||||
cma__t_sched_class class; /* Scheduling class */
|
||||
struct CMA__T_VP *processor; /* Current processor (if running) */
|
||||
} cma__t_tcb_sched;
|
||||
|
||||
typedef struct CMA__T_INT_ALERT {
|
||||
cma_t_boolean pending : 1; /* alert_pending bit */
|
||||
cma_t_boolean g_enable : 1; /* general delivery state */
|
||||
cma_t_boolean a_enable : 1; /* asynchronous delivery state */
|
||||
cma_t_integer spare : 29; /* Pad to longword */
|
||||
cma_t_natural count; /* Alert scope nesting count */
|
||||
} cma__t_int_alert;
|
||||
|
||||
typedef enum CMA__T_STATE {
|
||||
cma__c_state_running = 0, /* For consistency with initial TCB */
|
||||
cma__c_state_ready = 1,
|
||||
cma__c_state_blocked = 2,
|
||||
cma__c_state_terminated = 3
|
||||
} cma__t_state;
|
||||
#define cma__c_state__first ((cma_t_integer)cma__c_state_running)
|
||||
#define cma__c_state__last ((cma_t_integer)cma__c_state_terminated)
|
||||
#define cma__c_state__dim (cma__c_state__last + 1)
|
||||
|
||||
typedef enum CMA__T_THKIND {
|
||||
cma__c_thkind_initial = 0, /* Initial thread */
|
||||
cma__c_thkind_normal = 1, /* Normal thread */
|
||||
cma__c_thkind_null = 2 /* A null thread */
|
||||
} cma__t_thkind;
|
||||
#define cma__c_thkind__first ((cma_t_integer)cma__c_thkind_initial)
|
||||
#define cma__c_thkind__last ((cma_t_integer)cma__c_thkind_null)
|
||||
#define cma__c_thkind__dim (cma__c_thkind__last + 1)
|
||||
|
||||
typedef enum CMA__T_SYSCALL_STATE {
|
||||
cma__c_syscall_ok = 1, /* syscall was not interrupted */
|
||||
cma__c_syscall_intintrpt = 1, /* syscall was interrupted by VTALRM */
|
||||
cma__c_syscall_extintrpt = 2 /* syscall was interrupted by external signal */
|
||||
} cma__t_syscall_state;
|
||||
|
||||
|
||||
typedef struct CMA__T_INT_TCB {
|
||||
/*
|
||||
* Fixed part of TCB.
|
||||
* Modifications to the following three fields must be coordinated.
|
||||
* The object header must always be first, and the prolog must always
|
||||
* remain at the same offset (32) for all time. Thus the object header
|
||||
* must never grow beyond a maximum of 32 bytes.
|
||||
*/
|
||||
cma__t_object header; /* Common object header */
|
||||
cma__t_tcb_pad pad1; /* Pad required to align prolog */
|
||||
cma_t_tcb_prolog prolog; /* Standard prolog for tasks, threads */
|
||||
|
||||
/*
|
||||
* Floating part of TCB (fields here on are free to be moved and resized).
|
||||
*/
|
||||
cma__t_queue threads; /* List of all known threads */
|
||||
cma__t_int_attr *attributes; /* Backpointer to attr obj */
|
||||
cma__t_state state; /* Current state of thread */
|
||||
cma__t_thkind kind; /* Which kind of thread */
|
||||
struct CMA__T_INT_MUTEX
|
||||
*mutex; /* Mutex to control TCB access */
|
||||
struct CMA__T_INT_CV
|
||||
*term_cv; /* CV for join */
|
||||
struct CMA__T_INT_MUTEX
|
||||
*tswait_mutex; /* Mutex for thread-synchronous waits */
|
||||
struct CMA__T_INT_CV
|
||||
*tswait_cv; /* CV for thread-synchronous waits */
|
||||
cma_t_start_routine start_code; /* Address of start routine */
|
||||
cma_t_address start_arg; /* Argument to pass to start_code */
|
||||
cma__t_queue stack; /* Queue header for stack descr. */
|
||||
cma_t_natural context_count; /* Size of context array */
|
||||
cma__t_context_list contexts; /* Context value array pointer */
|
||||
cma_t_exit_status exit_status; /* Exit status of thread */
|
||||
cma_t_address return_value; /* Thread's return value */
|
||||
cma__t_async_ctx async_ctx; /* Asynchronous context switch info */
|
||||
cma__t_static_ctx static_ctx; /* Static context switch information */
|
||||
cma_t_integer event_status; /* Status of semaphore operation */
|
||||
cma__t_tcb_time timer; /* Time info for dispatcher */
|
||||
cma__t_tcb_sched sched; /* Scheduler info */
|
||||
cma__t_tcb_debug debug; /* Debugger info */
|
||||
#if _CMA_OS_ == _CMA__UNIX
|
||||
# if !_CMA_THREAD_SYNC_IO_
|
||||
cma__t_tcb_select select; /* Select info for timed selects */
|
||||
# endif
|
||||
struct sigaction sigaction_data[NSIG];
|
||||
#endif
|
||||
cma_t_natural syscall_state; /* set if one of the cma wrapped syscalls was interrupted. */
|
||||
cma_t_boolean detached; /* Set if already detached */
|
||||
cma_t_boolean terminated; /* Set if terminated */
|
||||
cma_t_integer joiners; /* Count of joiners, for zombie frees */
|
||||
cma__t_int_alert alert; /* Current alert state info */
|
||||
struct CMA__T_INT_CV
|
||||
*wait_cv; /* CV thread is currently waiting on */
|
||||
struct CMA__T_INT_MUTEX
|
||||
*wait_mutex; /* Mutex thread is waiting on */
|
||||
struct EXC_CONTEXT_T
|
||||
*exc_stack; /* Top of exception stack */
|
||||
#if _CMA_PLATFORM_ == _CMA__IBMR2_UNIX
|
||||
char ctx_stack[cma__c_ibmr2_ctx_stack_size];
|
||||
#endif
|
||||
cma_t_integer thd_errno; /* Per-thread errno value */
|
||||
#if _CMA_OS_ == _CMA__VMS
|
||||
cma_t_integer thd_vmserrno; /* Per-thread VMS errno value */
|
||||
#endif
|
||||
} cma__t_int_tcb;
|
||||
|
||||
#endif
|
|
@ -1,125 +0,0 @@
|
|||
/*
|
||||
* (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC.
|
||||
* (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY
|
||||
* (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION
|
||||
* (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems
|
||||
* To anyone who acknowledges that this file is provided "AS IS" without
|
||||
* any express or implied warranty: permission to use, copy, modify, and
|
||||
* distribute this file for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notices and this notice appears in
|
||||
* all source code copies, and that none of the names listed above be used
|
||||
* in advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. None of these organizations
|
||||
* makes any representations about the suitability of this software for
|
||||
* any purpose.
|
||||
*/
|
||||
/*
|
||||
* Header file for CMA internal UTIL operations
|
||||
*/
|
||||
|
||||
#ifndef CMA_UTIL
|
||||
#define CMA_UTIL
|
||||
|
||||
/*
|
||||
* INCLUDE FILES
|
||||
*/
|
||||
|
||||
#include <cma.h>
|
||||
#include <cma_attr.h>
|
||||
#include <cma_defs.h>
|
||||
|
||||
#if _CMA_OS_ == _CMA__VMS
|
||||
# include <cma_rms.h>
|
||||
#endif
|
||||
|
||||
#if _CMA_VENDOR_ == _CMA__SUN
|
||||
# include <sys/time.h>
|
||||
#else
|
||||
# include <time.h>
|
||||
#endif
|
||||
|
||||
#if _CMA_OS_ == _CMA__UNIX
|
||||
# include <stdio.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* CONSTANTS AND MACROS
|
||||
*/
|
||||
|
||||
#define cma__c_buffer_size 256 /* Size of output buffer */
|
||||
|
||||
/*
|
||||
* TYPEDEFS
|
||||
*/
|
||||
|
||||
/*
|
||||
* Alternate eol routine
|
||||
*/
|
||||
typedef void (*cma__t_eol_routine) (char *);
|
||||
|
||||
#if _CMA_OS_ == _CMA__VMS
|
||||
typedef struct CMA__T_VMSFILE {
|
||||
struct RAB rab;
|
||||
struct FAB fab;
|
||||
} cma__t_vmsfile, *cma__t_file;
|
||||
#elif ( _CMA_UNIX_TYPE == _CMA__SVR4 )
|
||||
typedef int cma__t_file;
|
||||
#else
|
||||
typedef FILE *cma__t_file;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* GLOBAL DATA
|
||||
*/
|
||||
|
||||
/*
|
||||
* INTERNAL INTERFACES
|
||||
*/
|
||||
|
||||
extern void cma__abort (void);
|
||||
|
||||
extern cma_t_integer cma__atol (char *);
|
||||
|
||||
extern cma_t_integer cma__atoi (char *);
|
||||
|
||||
extern char * cma__getenv (char *,char *,int);
|
||||
|
||||
extern int cma__gettimespec (struct timespec *);
|
||||
|
||||
extern cma__t_file cma__int_fopen (char *,char *);
|
||||
|
||||
#ifndef NDEBUG
|
||||
extern void cma__init_trace (char *_env);
|
||||
#endif
|
||||
|
||||
extern char * cma__memcpy (char *,char *,cma_t_integer);
|
||||
|
||||
#ifndef cma__memset
|
||||
extern char * cma__memset (char *,cma_t_integer,cma_t_integer);
|
||||
#endif
|
||||
|
||||
extern void cma__putformat (char *,char *,...);
|
||||
|
||||
extern void cma__putstring (char *,char *);
|
||||
|
||||
extern void cma__putint (char *,cma_t_integer);
|
||||
|
||||
extern void cma__putint_5 (char *,cma_t_integer);
|
||||
|
||||
extern void cma__putint_10 (char *,cma_t_integer);
|
||||
|
||||
extern void cma__puthex (char *,cma_t_integer);
|
||||
|
||||
extern void cma__puthex_8 (char *,cma_t_integer);
|
||||
|
||||
extern void cma__puteol (char *);
|
||||
|
||||
extern void cma__set_eol_routine (cma__t_eol_routine,cma__t_eol_routine *);
|
||||
|
||||
extern cma_t_integer cma__strlen (char *);
|
||||
|
||||
extern int cma__strncmp (char *,char *,cma_t_integer);
|
||||
|
||||
extern char *cma__gets (char *,char *);
|
||||
|
||||
#endif
|
|
@ -1,165 +0,0 @@
|
|||
prefix = /usr/local
|
||||
|
||||
program_transform_name =
|
||||
exec_prefix = $(prefix)
|
||||
bindir = $(exec_prefix)/bin
|
||||
libdir = $(exec_prefix)/lib
|
||||
tooldir = $(libdir)/$(target_alias)
|
||||
|
||||
datadir = $(prefix)/share
|
||||
mandir = $(prefix)/man
|
||||
man1dir = $(mandir)/man1
|
||||
man2dir = $(mandir)/man2
|
||||
man3dir = $(mandir)/man3
|
||||
man4dir = $(mandir)/man4
|
||||
man5dir = $(mandir)/man5
|
||||
man6dir = $(mandir)/man6
|
||||
man7dir = $(mandir)/man7
|
||||
man8dir = $(mandir)/man8
|
||||
man9dir = $(mandir)/man9
|
||||
infodir = $(prefix)/info
|
||||
includedir = $(prefix)/include
|
||||
|
||||
ARM_RELEASE='"Berkeley Licence for Cygnus"'
|
||||
|
||||
SHELL = /bin/sh
|
||||
|
||||
INSTALL = `cd $(srcdir)/../..;pwd`/install.sh -c
|
||||
INSTALL_PROGRAM = $(INSTALL)
|
||||
INSTALL_DATA = $(INSTALL)
|
||||
INSTALL_XFORM = $(INSTALL) -t='$(program_transform_name)'
|
||||
INSTALL_XFORM1 = $(INSTALL_XFORM) -b=.1
|
||||
|
||||
AR = ar
|
||||
AR_FLAGS = qv
|
||||
RANLIB = ranlib
|
||||
|
||||
LD = ld
|
||||
|
||||
# If you are compiling with GCC, make sure that either 1) You use the
|
||||
# -traditional flag, or 2) You have the fixed include files where GCC
|
||||
# can reach them. Otherwise the ioctl calls in inflow.c
|
||||
# will be incorrectly compiled. The "fixincludes" script in the gcc
|
||||
# distribution will fix your include files up.
|
||||
#CC=cc
|
||||
#CC=gcc -traditional
|
||||
GCC=gcc
|
||||
|
||||
# Directory containing source files. Don't clean up the spacing,
|
||||
# this exact string is matched for by the "configure" script.
|
||||
srcdir = .
|
||||
|
||||
# It is also possible that you will need to add -I/usr/include/sys to the
|
||||
# CFLAGS section if your system doesn't have fcntl.h in /usr/include (which
|
||||
# is where it should be according to Posix).
|
||||
|
||||
# Set this up with gcc if you have gnu ld and the loader will print out
|
||||
# line numbers for undefinded refs.
|
||||
#CC-LD=gcc -static
|
||||
CC-LD=${CC}
|
||||
|
||||
# All the includes used for CFLAGS and for lint.
|
||||
# -I. for config files.
|
||||
# -I${srcdir} possibly for regex.h also.
|
||||
# -I${srcdir}/config for more generic config files.
|
||||
INCLUDE_CFLAGS = -I. -I${srcdir}
|
||||
|
||||
# M{H,T}_CFLAGS, if defined, has host- and target-dependent CFLAGS
|
||||
# from the config/ directory.
|
||||
GLOBAL_CFLAGS = ${MT_CFLAGS} ${MH_CFLAGS} -DRETRANS -DARM_RELEASE=$(ARM_RELEASE)
|
||||
#PROFILE_CFLAGS = -pg
|
||||
|
||||
# CFLAGS is specifically reserved for setting from the command line
|
||||
# when running make. I.E. "make CFLAGS=-Wmissing-prototypes".
|
||||
CFLAGS = -g
|
||||
|
||||
# INTERNAL_CFLAGS is the aggregate of all other *CFLAGS macros.
|
||||
INTERNAL_CFLAGS = ${CFLAGS} ${GLOBAL_CFLAGS} ${PROFILE_CFLAGS} \
|
||||
${BFD_CFLAGS} ${MMALLOC_CFLAGS} ${INCLUDE_CFLAGS}
|
||||
|
||||
# LDFLAGS is specifically reserved for setting from the command line
|
||||
# when running make.
|
||||
|
||||
# Host and target-dependent makefile fragments come in here.
|
||||
####
|
||||
# End of host and target-dependent makefile fragments
|
||||
|
||||
# All source files that go into linking GDB remote server.
|
||||
|
||||
SFILES = $(srcdir)/
|
||||
|
||||
DEPFILES =
|
||||
|
||||
SOURCES = $(SFILES) $(ALLDEPFILES)
|
||||
TAGFILES = $(SOURCES) ${HFILES} ${ALLPARAM} ${POSSLIBS}
|
||||
|
||||
OBS = hostchan.o drivers.o devsw.o rx.o tx.o params.o hsys.o crc.o \
|
||||
logging.o msgbuild.o ardi.o serdrv.o serpardr.o etherdrv.o bytesex.o \
|
||||
unixcomm.o
|
||||
|
||||
# Prevent Sun make from putting in the machine type. Setting
|
||||
# TARGET_ARCH to nothing works for SunOS 3, 4.0, but not for 4.1.
|
||||
.c.o:
|
||||
${CC} -c ${INTERNAL_CFLAGS} $<
|
||||
|
||||
all: libangsd.a
|
||||
|
||||
libangsd.a: $(OBS)
|
||||
rm -f libangsd.a
|
||||
$(AR) $(AR_FLAGS) libangsd.a $(OBS)
|
||||
$(RANLIB) libangsd.a
|
||||
|
||||
# Traditionally "install" depends on "all". But it may be useful
|
||||
# not to; for example, if the user has made some trivial change to a
|
||||
# source file and doesn't care about rebuilding or just wants to save the
|
||||
# time it takes for make to check that all is up to date.
|
||||
# install-only is intended to address that need.
|
||||
install: all install-only
|
||||
install-only:
|
||||
|
||||
uninstall:
|
||||
|
||||
installcheck:
|
||||
check:
|
||||
info dvi:
|
||||
install-info:
|
||||
clean-info:
|
||||
|
||||
config.status:
|
||||
@echo "You must configure rdi-share. Look at the README file for details."
|
||||
@false
|
||||
|
||||
clean:
|
||||
rm -f *.o ${ADD_FILES} *~
|
||||
rm -f gdbserver core make.log
|
||||
|
||||
distclean: clean
|
||||
rm -f config.status
|
||||
rm -f Makefile
|
||||
|
||||
maintainer-clean realclean: clean
|
||||
rm -f config.status
|
||||
rm -f Makefile
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(host_makefile_frag) $(target_makefile_frag)
|
||||
$(SHELL) ./config.status
|
||||
|
||||
force:
|
||||
|
||||
# GNU Make has an annoying habit of putting *all* the Makefile variables
|
||||
# into the environment, unless you include this target as a circumvention.
|
||||
# Rumor is that this will be fixed (and this target can be removed)
|
||||
# in GNU Make 4.0.
|
||||
.NOEXPORT:
|
||||
|
||||
# GNU Make 3.63 has a different problem: it keeps tacking command line
|
||||
# overrides onto the definition of $(MAKE). This variable setting
|
||||
# will remove them.
|
||||
MAKEOVERRIDES=
|
||||
|
||||
## This is ugly, but I don't want GNU make to put these variables in
|
||||
## the environment. Older makes will see this as a set of targets
|
||||
## with no dependencies and no actions.
|
||||
unexport CHILLFLAGS CHILL_LIB CHILL_FOR_TARGET :
|
||||
|
||||
# This is the end of "Makefile.in".
|
|
@ -1,6 +0,0 @@
|
|||
This is a version of ARM's RDI library which has been been put under a
|
||||
free software license.
|
||||
|
||||
See ARM's Software Development Tools Reference Manual (Remote
|
||||
Debugging chapter), and the file gdb/remote-rdi.c for information
|
||||
about how to use it.
|
File diff suppressed because it is too large
Load Diff
|
@ -1,72 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*
|
||||
* Project: ANGEL
|
||||
*
|
||||
* Title: Definitions of ADP error codes
|
||||
*/
|
||||
|
||||
#ifndef angsd_adperrs_h
|
||||
#define angsd_adperrs_h
|
||||
/*
|
||||
* ADP failure codes start at 256 to distinguish them for debug purposes
|
||||
*/
|
||||
enum AdpErrs
|
||||
{
|
||||
adp_ok = 0,
|
||||
adp_failed = 256,
|
||||
adp_malloc_failure,
|
||||
adp_illegal_args,
|
||||
adp_device_not_found,
|
||||
adp_device_open_failed,
|
||||
adp_device_already_open,
|
||||
adp_device_not_open,
|
||||
adp_bad_channel_id,
|
||||
adp_callback_already_registered,
|
||||
adp_write_busy,
|
||||
adp_bad_packet,
|
||||
adp_seq_high,
|
||||
adp_seq_low,
|
||||
adp_timeout_on_open,
|
||||
adp_abandon_boot_wait,
|
||||
adp_late_startup,
|
||||
adp_new_agent_starting
|
||||
};
|
||||
|
||||
#ifndef __cplusplus
|
||||
typedef enum AdpErrs AdpErrs;
|
||||
#endif
|
||||
|
||||
#define AdpMess_Failed "ADP Error - unspecific failure"
|
||||
#define AdpMess_MallocFailed "ADP Error - malloc failed"
|
||||
#define AdpMess_IllegalArgs "ADP Error - illegal arguments"
|
||||
#define AdpMess_DeviceNotFound "ADP Error - invalid device specified"
|
||||
#define AdpMess_DeviceOpenFailed "ADP Error - specified device failed to open"
|
||||
#define AdpMess_DeviceAlreadyOpen "ADP Error - device already open"
|
||||
#define AdpMess_DeviceNotOpen "ADP Error - device not open"
|
||||
#define AdpMess_BadChannelId "ADP Error - bad channel Id"
|
||||
#define AdpMess_CBAlreadyRegd "ADP Error - callback already registered"
|
||||
#define AdpMess_WriteBusy "ADP Error - write busy"
|
||||
#define AdpMess_BadPacket "ADP Error - bad packet"
|
||||
#define AdpMess_SeqHigh "ADP Error - sequence number too high"
|
||||
#define AdpMess_SeqLow "ADP Error - sequence number too low"
|
||||
#define AdpMess_TimeoutOnOpen "ADP Error - target did not respond"
|
||||
#define AdpMess_AbandonBootWait "abandoned wait for late startup"
|
||||
#define AdpMess_LateStartup "Target compiled with LATE_STARTUP set.\n" \
|
||||
"Waiting for target...\n" \
|
||||
"Press <Ctrl-C> to abort.\n"
|
||||
#define AdpMessLen_LateStartup (3*80)
|
||||
#define AdpMess_NewAgentStarting "New Debug Agent about to start.\n"
|
||||
|
||||
#endif /* ndef angsd_adperr_h */
|
||||
|
||||
/* EOF adperr.h */
|
|
@ -1,175 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/*> angel.h <*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* This header file is the main holder for the declarations and
|
||||
* prototypes for the core Angel system. Some Angel concepts are
|
||||
* described at the start of this file to ensure that a complete view
|
||||
* of the Angel world can be derived purely from the source.
|
||||
*
|
||||
*
|
||||
*
|
||||
* NOTE: Currently the Angel source is designed to be simple,
|
||||
* understandable and easy to port to new hardware platforms. However,
|
||||
* this does not always yield the highest performing system. The
|
||||
* current layered approach introduces an overhead to the performance
|
||||
* of the system. In a true commercial target, this code should be
|
||||
* re-designed to build a system where the Angel logical message
|
||||
* system, device driver and hardware accesses are merged to provide
|
||||
* the best performance.
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Angel overview:
|
||||
|
||||
... some comments describing Angel ...
|
||||
|
||||
* Angel is designed as a kit-of-parts that can be used to provide
|
||||
* run-time support for the development of ARM applications. The main
|
||||
* core of Angel is in providing support for the "debug" message
|
||||
* communication with a host system. These messages do not just cover
|
||||
* debugging ARM processes, but also the process of downloading ARM
|
||||
* programs or attaching to executing processes on the target.
|
||||
*
|
||||
* A stand-alone ROM based Angel world is the basic starting point for
|
||||
* a system, since it will allow programs to be downloaded to the
|
||||
* target. The ROM version of Angel will provide the generic debug
|
||||
* support, but no system specific routines. The preferred method of
|
||||
* using Angel is as a link library. This ensures that applications
|
||||
* carry with them the Angel routines necessary to support debugging
|
||||
* (and also ensure that the Angel version is up-to-date, independant
|
||||
* of the version in the target ROM). Eventually, once a program has
|
||||
* been fully debugged, a ROMmed version of the program can be
|
||||
* generated with the Angel code being provided in the application.
|
||||
|
||||
.. more comments ..
|
||||
|
||||
* The standard Angel routines do *NOT* perform any dynamic memory
|
||||
* allocation. To simplify the source, and aid the porting to a non C
|
||||
* library world, memory is either pre-allocated (as build-time
|
||||
* globals) or actually given to the particular Angel routine by the
|
||||
* active run-time. This ensures that the interaction between Angel
|
||||
* and the target O/S is minimised.
|
||||
*
|
||||
* Notes: We sub-include more header files to keep the source
|
||||
* modular. Since Angel is a kit-of-parts alternative systems may need
|
||||
* to change the prototypes of particular functions, whilst
|
||||
* maintaining a fixed external interface. e.g. using the standard
|
||||
* DEBUG messages, but with a different communications world.
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __angel_h
|
||||
#define __angel_h
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*-- Global Angel definitions and manifests ---------------------------------*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* When building Angel we may not include the standard library
|
||||
* headers. However, it is useful coding using standard macro names
|
||||
* since it makes the code easier to understand.
|
||||
*/
|
||||
|
||||
typedef unsigned int word ;
|
||||
typedef unsigned char byte ;
|
||||
|
||||
/* The following typedefs can be used to access I/O registers: */
|
||||
typedef volatile unsigned int vuword ;
|
||||
typedef volatile unsigned char vubyte ;
|
||||
|
||||
/*
|
||||
* The following typedefs are used when defining objects that may also
|
||||
* be created on a host system, where the word size is not
|
||||
* 32bits. This ensures that the same data values are manipulated.
|
||||
*/
|
||||
#ifdef TARGET
|
||||
typedef unsigned int unsigned32;
|
||||
typedef signed int signed32;
|
||||
typedef int int32;
|
||||
|
||||
typedef unsigned short int unsigned16;
|
||||
typedef signed short int signed16;
|
||||
|
||||
/*
|
||||
* yet another solution for the bool/boolean problem, this one is
|
||||
* copied from Scott's modifications to clx/host.h
|
||||
*/
|
||||
# ifdef IMPLEMENT_BOOL_AS_ENUM
|
||||
enum _bool { _false, _true };
|
||||
# define _bool enum _bool
|
||||
# elif defined(IMPLEMENT_BOOL_AS_INT) || !defined(__cplusplus)
|
||||
# define _bool int
|
||||
# define _false 0
|
||||
# define _true 1
|
||||
# endif
|
||||
|
||||
# ifdef _bool
|
||||
# define bool _bool
|
||||
# endif
|
||||
|
||||
# ifndef true
|
||||
# define true _true
|
||||
# define false _false
|
||||
# endif
|
||||
|
||||
# ifndef YES
|
||||
# define YES true
|
||||
# define NO false
|
||||
# endif
|
||||
|
||||
# undef TRUE /* some OSF headers define as 1 */
|
||||
# define TRUE true
|
||||
|
||||
# undef FALSE /* some OSF headers define as 1 */
|
||||
# define FALSE false
|
||||
|
||||
# ifndef NULL
|
||||
# define NULL 0
|
||||
# endif
|
||||
|
||||
#else
|
||||
|
||||
# include "host.h"
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef IGNORE
|
||||
# define IGNORE(x) ((x)=(x))
|
||||
#endif
|
||||
|
||||
/* The following typedef allows us to cast between integral and
|
||||
* function pointers. This isn't allowed by direct casting when
|
||||
* conforming to the ANSI spec.
|
||||
*/
|
||||
typedef union ansibodge
|
||||
{
|
||||
word w ;
|
||||
word *wp ;
|
||||
void *vp ;
|
||||
byte *bp ;
|
||||
void (*vfn)(void) ;
|
||||
word (*wfn)(void) ;
|
||||
int (*ifn)(void) ;
|
||||
byte (*bfn)(void) ;
|
||||
} ansibodge ;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/* The amount setup aside by the run-time system for stack overflow
|
||||
* handlers to execute in. This must be at least 256bytes, since that
|
||||
* value is assumed by the current ARM Ltd compiler.
|
||||
* This space is _only_ kept for the USR stack, not any of the privileged
|
||||
* mode stacks, as stack overflow on these is always fatal - there is
|
||||
* no point attemptingto recover. In addition is is important that
|
||||
* Angel should keep privileged stack space requirements to a minimum.
|
||||
*/
|
||||
#define APCS_STACKGUARD 256
|
||||
|
||||
#endif /* __angel_h */
|
||||
|
||||
/* EOF angel.h */
|
File diff suppressed because it is too large
Load Diff
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ardi.h
|
||||
* ADP RDI interfaces
|
||||
*
|
||||
*/
|
||||
|
||||
#include "host.h"
|
||||
|
||||
typedef unsigned32 ARMword;
|
||||
|
||||
#include "dbg_rdi.h"
|
||||
#include "dbg_conf.h"
|
||||
|
||||
extern char *commandline;
|
||||
extern ARMword last_vector_catch;
|
||||
|
||||
/* This is the size of buffers that are asked for by standard channels
|
||||
* Non standard channels may wish to copy this!
|
||||
*/
|
||||
extern int Armsd_BufferSize;
|
||||
|
||||
typedef int (*host_ChannelBufferFilledFnPtr)(unsigned int ,unsigned char ** ,void *);
|
||||
|
||||
int angel_RDI_open(
|
||||
unsigned type, Dbg_ConfigBlock const *config,
|
||||
Dbg_HostosInterface const *hostif, struct Dbg_MCState *dbg_state);
|
||||
int angel_RDI_close(void);
|
||||
|
||||
int angel_RDI_read(ARMword source, void *dest, unsigned *nbytes);
|
||||
int angel_RDI_write(const void *source, ARMword dest, unsigned *nbytes);
|
||||
|
||||
int angel_RDI_CPUread(unsigned mode, unsigned long mask, ARMword *buffer);
|
||||
int angel_RDI_CPUwrite(unsigned mode, unsigned long mask,
|
||||
ARMword const *buffer);
|
||||
|
||||
int angel_RDI_CPread(unsigned CPnum, unsigned long mask, ARMword *buffer);
|
||||
int angel_RDI_CPwrite(unsigned CPnum, unsigned long mask,
|
||||
ARMword const *buffer);
|
||||
|
||||
int angel_RDI_setbreak(ARMword address, unsigned type, ARMword bound,
|
||||
PointHandle *handle);
|
||||
int angel_RDI_clearbreak(PointHandle handle);
|
||||
|
||||
int angel_RDI_setwatch(ARMword address, unsigned type, unsigned datatype,
|
||||
ARMword bound, PointHandle *handle);
|
||||
int angel_RDI_clearwatch(PointHandle handle);
|
||||
|
||||
int angel_RDI_pointinq(ARMword *address, unsigned type, unsigned datatype,
|
||||
ARMword *bound);
|
||||
|
||||
int angel_RDI_execute(PointHandle *handle);
|
||||
|
||||
int angel_RDI_step(unsigned ninstr, PointHandle *handle);
|
||||
|
||||
int angel_RDI_info(unsigned type, ARMword *arg1, ARMword *arg2);
|
||||
|
||||
int angel_RDI_AddConfig(unsigned long nbytes);
|
||||
|
||||
int angel_RDI_LoadConfigData(unsigned long nbytes, char const *data);
|
||||
|
||||
int angel_RDI_SelectConfig(RDI_ConfigAspect aspect, char const *name,
|
||||
RDI_ConfigMatchType matchtype, unsigned versionreq,
|
||||
unsigned *versionp);
|
||||
|
||||
RDI_NameList const *angel_RDI_drivernames(void);
|
||||
|
||||
int angel_RDI_LoadAgent(ARMword dest, unsigned long size, getbufferproc *getb,
|
||||
void *getbarg);
|
||||
|
||||
extern const struct Dbg_HostosInterface *angel_hostif;
|
||||
|
||||
typedef int angel_RDI_TargetStoppedProc(unsigned stopped_reason, void *arg);
|
||||
|
||||
extern int angel_RDI_OnTargetStopping(angel_RDI_TargetStoppedProc *fn,
|
||||
void *arg);
|
File diff suppressed because it is too large
Load Diff
|
@ -1,109 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*
|
||||
* Project: ANGEL
|
||||
*
|
||||
* Title: Public interface to buffer management
|
||||
*/
|
||||
|
||||
#ifndef angel_buffers_h
|
||||
#define angel_buffers_h
|
||||
|
||||
#include "chandefs.h" /* CHAN_HEADER_SIZE */
|
||||
|
||||
|
||||
/* the handle to a buffer */
|
||||
typedef unsigned char *p_Buffer;
|
||||
|
||||
|
||||
/*
|
||||
* Angel Packets are structured as a fixed size header, followed
|
||||
* by the packet data
|
||||
*/
|
||||
#ifdef TARGET
|
||||
# define BUFFERDATA(b) (b) /* channels layer takes care of it */
|
||||
#else
|
||||
# define BUFFERDATA(b) (&((b)[CHAN_HEADER_SIZE]))
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* The buffer management function prototypes are only applicable
|
||||
* when compiling target code
|
||||
*/
|
||||
#ifdef TARGET
|
||||
|
||||
/*
|
||||
* Function: Angel_BufferQuerySizes
|
||||
* Purpose: Request infomation on the default and maximum buffer sizes
|
||||
* that can be allocated
|
||||
*
|
||||
* Params:
|
||||
* In/Out: default_size, max_size: pointers to place the
|
||||
* sizes in on return
|
||||
*/
|
||||
|
||||
void Angel_BufferQuerySizes(unsigned int *default_size,
|
||||
unsigned int *max_size );
|
||||
|
||||
/*
|
||||
* Function: Angel_RxEnginBuffersLeft
|
||||
* Purpose: return the number of free buffers
|
||||
*
|
||||
* Params:
|
||||
* Returns: number of free buffers
|
||||
*/
|
||||
unsigned int Angel_BuffersLeft( void );
|
||||
|
||||
/*
|
||||
* Function: Angel_BufferAlloc
|
||||
* Purpose: allocate a buffer that is at least req_size bytes long
|
||||
*
|
||||
* Params:
|
||||
* Input: req_size the required size of the buffer
|
||||
*
|
||||
* Returns: pointer to the buffer NULL if unable to
|
||||
* fulfil the request
|
||||
*/
|
||||
p_Buffer Angel_BufferAlloc(unsigned int req_size);
|
||||
|
||||
/*
|
||||
* Function: Angel_BufferRelease
|
||||
* Purpose: release a buffer back to the free pool
|
||||
*
|
||||
* Params:
|
||||
* Input: pointer to the buffer to free
|
||||
*/
|
||||
void Angel_BufferRelease(p_Buffer buffer);
|
||||
|
||||
|
||||
/* return values for angel_InitBuffers */
|
||||
typedef enum buf_init_error{
|
||||
INIT_BUF_OK,
|
||||
INIT_BUF_FAIL
|
||||
} buf_init_error;
|
||||
|
||||
/*
|
||||
* Function: Angel_InitBuffers
|
||||
* Purpose: Initalised and malloc the buffer pool
|
||||
*
|
||||
* Params:
|
||||
* Returns: see above
|
||||
*/
|
||||
|
||||
buf_init_error Angel_InitBuffers(void);
|
||||
|
||||
#endif /* def TARGET */
|
||||
|
||||
#endif /* ndef angel_buffers_h */
|
||||
|
||||
/* EOF buffers.h */
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/*
|
||||
* bytesex.c - Code to support byte-sex independence
|
||||
* Copyright: (C) 1991, Advanced RISC Machines Ltd., Cambridge, England.
|
||||
*/
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
#include "bytesex.h"
|
||||
|
||||
static int reversing_bytes = 0;
|
||||
|
||||
void bytesex_reverse(yes_or_no)
|
||||
int yes_or_no;
|
||||
{ reversing_bytes = yes_or_no;
|
||||
}
|
||||
|
||||
int bytesex_reversing()
|
||||
{
|
||||
return reversing_bytes;
|
||||
}
|
||||
|
||||
int32 bytesex_hostval(v)
|
||||
int32 v;
|
||||
{ /* Return v with the same endian-ness as the host */
|
||||
/* This mess generates better ARM code than the more obvious mess */
|
||||
/* and may eventually peephole to optimal code... */
|
||||
if (reversing_bytes)
|
||||
{ unsigned32 t;
|
||||
/* t = v ^ (v ror 16) */
|
||||
t = v ^ ((v << 16) | (((unsigned32)v) >> 16));
|
||||
t &= ~0xff0000;
|
||||
/* v = v ror 8 */
|
||||
v = (v << 24) | (((unsigned32)v) >> 8);
|
||||
v = v ^ (t >> 8);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
int32 bytesex_hostval_16(v)
|
||||
int32 v;
|
||||
{
|
||||
if (reversing_bytes) {
|
||||
v = ((v >> 8) & 0xff) | ((v << 8) & 0xff00);
|
||||
}
|
||||
return v;
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/*
|
||||
Title: Code to support byte-sex independence
|
||||
Copyright: (C) 1991, Advanced RISC Machines Ltd., Cambridge, England.
|
||||
*/
|
||||
/*
|
||||
*/
|
||||
|
||||
#ifndef __bytesex_h
|
||||
#define __bytesex_h
|
||||
|
||||
#include "host.h"
|
||||
|
||||
void bytesex_reverse(int yes_or_no);
|
||||
/*
|
||||
* Turn sex-reversal on or off - 0 means off, non-0 means on.
|
||||
*/
|
||||
|
||||
int bytesex_reversing(void);
|
||||
/*
|
||||
* Return non-0 if reversing the byte sex, else 0.
|
||||
*/
|
||||
|
||||
int32 bytesex_hostval(int32 v);
|
||||
/*
|
||||
* Return v or byte-reversed v, according to whether sex-reversval
|
||||
* is on or off.
|
||||
*/
|
||||
|
||||
int32 bytesex_hostval_16(int32 v);
|
||||
/* Return v or byte-reversed v for a 16 bit value */
|
||||
|
||||
#endif
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*
|
||||
* Project: ANGEL
|
||||
*
|
||||
* Title: Enumeration with all supported channels
|
||||
*/
|
||||
|
||||
#ifndef angel_chandefs_h
|
||||
#define angel_chandefs_h
|
||||
|
||||
enum channelIDs {
|
||||
CI_PRIVATE = 0, /* channels protocol control messages */
|
||||
CI_HADP, /* ADP, host originated */
|
||||
CI_TADP, /* ADP, target originated */
|
||||
CI_HBOOT, /* Boot, host originated */
|
||||
CI_TBOOT, /* Boot, target originated */
|
||||
CI_CLIB, /* Semihosting C library support */
|
||||
CI_HUDBG, /* User debug support, host originated */
|
||||
CI_TUDBG, /* User debug support, target originated */
|
||||
CI_HTDCC, /* Thumb direct comms channel, host orig. */
|
||||
CI_TTDCC, /* Thumb direct comms channel, target orig. */
|
||||
CI_TLOG, /* Target debug/logging */
|
||||
CI_NUM_CHANNELS
|
||||
};
|
||||
|
||||
typedef unsigned ChannelID;
|
||||
|
||||
|
||||
/*
|
||||
* Size in bytes of the channel header.
|
||||
* This is a duplicate of XXX in chanpriv.h, but we don't want everyone
|
||||
* to have access to all of chanpriv.h, so we'll double-check in chanpriv.h.
|
||||
*/
|
||||
#define CHAN_HEADER_SIZE (4)
|
||||
|
||||
#endif /* ndef angel_chandefs_h */
|
||||
|
||||
/* EOF chandefs.h */
|
|
@ -1,382 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*
|
||||
* Project: ANGEL
|
||||
*
|
||||
* Title: User interface to the channels layer
|
||||
*/
|
||||
|
||||
#ifndef angel_channels_h
|
||||
#define angel_channels_h
|
||||
|
||||
/*
|
||||
* This provides the public interface to the channels layer read and write
|
||||
* routines, and buffer management routines.
|
||||
*/
|
||||
|
||||
/* Nested header files, if required */
|
||||
|
||||
#include "devices.h"
|
||||
#include "chandefs.h"
|
||||
#include "adperr.h"
|
||||
|
||||
/* General purpose constants, macros, enums, typedefs */
|
||||
|
||||
/* use the default device */
|
||||
#define CH_DEFAULT_DEV ((DeviceID)-1)
|
||||
|
||||
/* return codes */
|
||||
typedef enum ChanError {
|
||||
CE_OKAY, /* no error */
|
||||
CE_ABANDONED, /* abandoned due to device switch */
|
||||
CE_DEV_ERROR, /* unexpected error from device driver */
|
||||
CE_BUSY, /* channel in use */
|
||||
CE_BUFF_ERROR, /* unable to get buffer */
|
||||
CE_PRIVATE /* start of internal error codes */
|
||||
} ChanError;
|
||||
|
||||
|
||||
/* Publically-accessible globals */
|
||||
|
||||
/*
|
||||
* The following two globals are only valid after angel_InitialiseChannels()
|
||||
* has been called.
|
||||
*/
|
||||
|
||||
/* the default size of a channel buffer, for global use */
|
||||
extern unsigned Angel_ChanBuffSize;
|
||||
|
||||
/* the size of a long buffer, for global use */
|
||||
extern unsigned Angel_ChanLongSize;
|
||||
|
||||
#ifdef TARGET
|
||||
AdpErrs send_resend_msg(DeviceID devid);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Function: angel_InitialiseChannels
|
||||
* Purpose: initialise the channels layer
|
||||
*
|
||||
* Params:
|
||||
* Input: -
|
||||
* Output: -
|
||||
* In/Out: -
|
||||
*
|
||||
* Returns: -
|
||||
*
|
||||
* Reads globals: -
|
||||
* Modifies globals: -
|
||||
*
|
||||
* Other side effects: -
|
||||
*/
|
||||
|
||||
void angel_InitialiseChannels( void );
|
||||
|
||||
/*
|
||||
* Function: adp_init_seq
|
||||
* Purpose: initialise sequence numbers and free anyt leftover buffers
|
||||
*
|
||||
* Params:
|
||||
* Input: -
|
||||
* Output: -
|
||||
* In/Out: -
|
||||
*
|
||||
* Returns: - adp_ok if things went ok else an error code
|
||||
*
|
||||
* Reads globals: -
|
||||
* Modifies globals: -
|
||||
*
|
||||
* Other side effects: -
|
||||
*/
|
||||
|
||||
AdpErrs adp_init_seq(void);
|
||||
|
||||
/*
|
||||
* Function: angel_ChannelAllocBuffer
|
||||
* Purpose: allocate a buffer that is at least req_size bytes long
|
||||
*
|
||||
* Params:
|
||||
* Input: req_size the minimum size required
|
||||
* Output: -
|
||||
* In/Out: -
|
||||
*
|
||||
* Returns: pointer to allocated buffer, or
|
||||
* NULL if unable to allocate suitable buffer
|
||||
*
|
||||
* Reads globals: -
|
||||
* Modifies globals: -
|
||||
*
|
||||
* Other side effects: -
|
||||
*/
|
||||
|
||||
p_Buffer angel_ChannelAllocBuffer(unsigned req_size);
|
||||
|
||||
|
||||
/*
|
||||
* Function: angel_ChannelReleaseBuffer
|
||||
* Purpose: release a buffer back to the free pool
|
||||
*
|
||||
* Params:
|
||||
* Input: buffer the buffer to release
|
||||
* Output: -
|
||||
* In/Out: -
|
||||
*
|
||||
* Returns: -
|
||||
*
|
||||
* Reads globals: -
|
||||
* Modifies globals: -
|
||||
*
|
||||
* Other side effects: -
|
||||
*/
|
||||
|
||||
void angel_ChannelReleaseBuffer(p_Buffer buffer);
|
||||
|
||||
|
||||
/*
|
||||
* Function: angel_ChannelSend
|
||||
* Purpose: blocking send of a packet via a channel
|
||||
*
|
||||
* Params:
|
||||
* Input: devid Device to use, or CH_DEFAULT_DEV
|
||||
* chanid Channel to use for tx
|
||||
* buffer Pointer to data to send
|
||||
* len Length of data to send
|
||||
* Output: -
|
||||
* In/Out: -
|
||||
*
|
||||
* Returns: CE_OKAY Transmission completed
|
||||
* CE_BAD_CHAN Channel id invalid
|
||||
* CE_ABANDONED Tx abandoned due to device switch
|
||||
*
|
||||
* Reads globals: -
|
||||
* Modifies globals: -
|
||||
*
|
||||
* Other side effects: -
|
||||
*/
|
||||
|
||||
ChanError angel_ChannelSend(DeviceID devid, ChannelID chanid,
|
||||
const p_Buffer buffer, unsigned len);
|
||||
|
||||
|
||||
/*
|
||||
* Function: angel_ChannelSendAsync
|
||||
* Purpose: asynchronous send of a packet via a channel
|
||||
*
|
||||
* Params:
|
||||
* Input: devid Device to use, or CH_DEFAULT_DEV
|
||||
* chanid Channel to use for tx
|
||||
* buffer Pointer to data to send
|
||||
* len Length of data to send
|
||||
* callback Function to call on completion
|
||||
* callback_data Pointer to pass to callback
|
||||
* Output: -
|
||||
* In/Out: -
|
||||
*
|
||||
* Returns: CE_OKAY Transmission underway
|
||||
* CE_BAD_CHAN Channel id invalid
|
||||
* CE_ABANDONED Tx abandoned due to device switch
|
||||
*
|
||||
* Reads globals: -
|
||||
* Modifies globals: -
|
||||
*
|
||||
* Other side effects: -
|
||||
*
|
||||
* register an asynchronous send on the given channel
|
||||
* (blocks until send can be commenced)
|
||||
*/
|
||||
|
||||
typedef void (*ChanTx_CB_Fn)(ChannelID chanid, /* which channel */
|
||||
void *callback_data); /* as supplied... */
|
||||
|
||||
|
||||
ChanError angel_ChannelSendAsync( DeviceID devid,
|
||||
ChannelID chanid,
|
||||
const p_Buffer buffer,
|
||||
unsigned len,
|
||||
ChanTx_CB_Fn callback,
|
||||
void *callback_data);
|
||||
|
||||
|
||||
/*
|
||||
* Function: angel_ChannelRead
|
||||
* Purpose: blocking read of a packet from a channel
|
||||
*
|
||||
* Params:
|
||||
* Input: devid Device to use, or CH_DEFAULT_DEV
|
||||
* chanid Channel to use for rx
|
||||
* Output: buffer The buffer, supplied and filled
|
||||
* len How many bytes there are in the buffer
|
||||
* In/Out: -
|
||||
*
|
||||
* Returns: CE_OKAY Reception successful
|
||||
* CE_BAD_CHAN Channel id invalid
|
||||
* CE_ABANDONED Tx abandoned due to device switch
|
||||
*
|
||||
* Reads globals: -
|
||||
* Modifies globals: -
|
||||
*
|
||||
* Other side effects: -
|
||||
*
|
||||
* Note that in the present version, if an asynchronous read has been
|
||||
* registered, a blocking read will be refused with CE_BUSY.
|
||||
*/
|
||||
ChanError angel_ChannelRead(DeviceID devid,
|
||||
ChannelID chanid,
|
||||
p_Buffer *buffer,
|
||||
unsigned *len);
|
||||
|
||||
|
||||
/*
|
||||
* Function: angel_ChannelReadAsync
|
||||
* Purpose: asynchronous read of a packet via a channel
|
||||
*
|
||||
* Params:
|
||||
* Input: devid Device to use, or CH_DEFAULT_DEV
|
||||
* chanid Channel to wait on
|
||||
* callback Function to call on completion, or NULL
|
||||
* callback_data Pointer to pass to callback
|
||||
* Output: -
|
||||
* In/Out: -
|
||||
*
|
||||
* Returns: CE_OKAY Read request registered
|
||||
* CE_BAD_CHAN Channel id invalid
|
||||
* CE_BUSY Someone else is using the channel
|
||||
* (in a single threaded world)
|
||||
*
|
||||
* Reads globals: -
|
||||
* Modifies globals: -
|
||||
*
|
||||
* Other side effects: -
|
||||
*
|
||||
* Register an asynchronous read on the given channel. There can only be one
|
||||
* async. reader per channel, and blocking reads are not permitted whilst
|
||||
* an async. reader is registered.
|
||||
*
|
||||
* Reader can unregister by specifying NULL as the callback function.
|
||||
*/
|
||||
|
||||
typedef void (*ChanRx_CB_Fn)(DeviceID devID, /* ID of receiving device */
|
||||
ChannelID chanID, /* ID of receiving channel */
|
||||
p_Buffer buff, /* pointer to buffer */
|
||||
unsigned len, /* length of data */
|
||||
void *cb_data /* callback data */
|
||||
);
|
||||
|
||||
ChanError angel_ChannelReadAsync(DeviceID devid,
|
||||
ChannelID chanid,
|
||||
ChanRx_CB_Fn callback,
|
||||
void *callback_data);
|
||||
|
||||
|
||||
/*
|
||||
* Function: angel_ChannelReadAll
|
||||
* Purpose: register an asynchronous read across all devices
|
||||
*
|
||||
* Params:
|
||||
* Input: chanid Channel to look for (usually HBOOT)
|
||||
* callback Function to call on completion
|
||||
* callback_data Pointer to pass to callback
|
||||
* Output: -
|
||||
* In/Out: -
|
||||
*
|
||||
* Returns: CE_OKAY Read request registered
|
||||
* CE_BAD_CHAN Channel id invalid
|
||||
* CE_BUSY Someone else is reading all devices
|
||||
*
|
||||
* Reads globals: -
|
||||
* Modifies globals: -
|
||||
*
|
||||
* Other side effects: -
|
||||
*
|
||||
* Register an asynchronous read across all devices. This is a 'fallback',
|
||||
* which will be superseded (temporarily) by a registered reader or blocking
|
||||
* read on a specific device.
|
||||
*/
|
||||
|
||||
ChanError angel_ChannelReadAll( ChannelID chanid,
|
||||
ChanRx_CB_Fn callback,
|
||||
void *callback_data);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Function: angel_ChannelSendThenRead
|
||||
* Purpose: blocking write to followed by read from a channel
|
||||
*
|
||||
* Params:
|
||||
* Input: devid Device to use, or CH_DEFAULT_DEV
|
||||
* chanid Channel to use for rx
|
||||
* In/Out: buffer On entry: the packet to be sent
|
||||
* On return: the packet received
|
||||
* len On entry: length of packet to be sent
|
||||
* On return: length of packet rx'd
|
||||
* In/Out: -
|
||||
*
|
||||
* Returns: CE_OKAY Tx and Reception successful
|
||||
* CE_BAD_CHAN Channel id invalid
|
||||
* CE_ABANDONED Tx abandoned due to device switch
|
||||
*
|
||||
* Reads globals: -
|
||||
* Modifies globals: -
|
||||
*
|
||||
* Other side effects: -
|
||||
*
|
||||
* Note that in the present version, if an asynchronous read has been
|
||||
* registered, this will be refused with CE_BUSY.
|
||||
*/
|
||||
ChanError angel_ChannelSendThenRead(DeviceID devid,
|
||||
ChannelID chanid,
|
||||
p_Buffer *buffer,
|
||||
unsigned *len);
|
||||
|
||||
|
||||
/*
|
||||
* Function: angel_ChannelSelectDevice
|
||||
* Purpose: select the device to be used for all channel comms
|
||||
*
|
||||
* Params:
|
||||
* Input: device ID of device to use as the default
|
||||
* Output: -
|
||||
* In/Out: -
|
||||
*
|
||||
* Returns: CE_OKAY Default device selected
|
||||
* CE_BAD_DEV Invalid device ID
|
||||
*
|
||||
* Reads globals: -
|
||||
* Modifies globals: -
|
||||
*
|
||||
* Other side effects: Any channel operations in progress are
|
||||
* abandoned.
|
||||
*
|
||||
* select the device for all channels comms
|
||||
*/
|
||||
|
||||
ChanError angel_ChannelSelectDevice(DeviceID device);
|
||||
|
||||
|
||||
/*
|
||||
* Function: angel_ChannelReadActiveDevice
|
||||
* Purpose: reads the device id of the currently active device
|
||||
*
|
||||
* Params:
|
||||
* Input: device address of a DeviceID variable
|
||||
* Output: *device ID of device currently being used
|
||||
* In/Out: -
|
||||
*
|
||||
* Returns: CE_OKAY Default device selected
|
||||
*/
|
||||
|
||||
ChanError angel_ChannelReadActiveDevice(DeviceID *device);
|
||||
|
||||
#endif /* ndef angel_channels_h */
|
||||
|
||||
/* EOF channels.h */
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*
|
||||
* Project: ANGEL
|
||||
*
|
||||
* Title: Private header for channels implementations
|
||||
*/
|
||||
|
||||
#ifndef angel_chanpriv_h
|
||||
#define angel_chanpriv_h
|
||||
|
||||
/*
|
||||
* This describes the internal structure and flags for a channels packet.
|
||||
*/
|
||||
|
||||
/* byte positions within channel packet */
|
||||
#define CF_CHANNEL_BYTE_POS 0
|
||||
#define CF_HOME_SEQ_BYTE_POS 1
|
||||
#define CF_OPPO_SEQ_BYTE_POS 2
|
||||
#define CF_FLAGS_BYTE_POS 3
|
||||
#define CF_DATA_BYTE_POS 4
|
||||
|
||||
/* flags for FLAGS field */
|
||||
#define CF_RELIABLE (1 << 0) /* use reliable channels protocol */
|
||||
#define CF_RESEND (1 << 1) /* this is a renegotiation packet */
|
||||
#define CF_HEARTBEAT (1 << 2) /* heartbeat packet - prod target into sync */
|
||||
|
||||
/* byte positions within buffer */
|
||||
#define CB_LINK_BYTE_POS 0 /* the link pointer */
|
||||
#define CB_CHAN_HEADER_BYTE_POS 4 /* the channel frame starts here */
|
||||
|
||||
/* macro to get buffer position of packet component */
|
||||
#define CB_PACKET(x) (CB_CHAN_HEADER_BYTE_POS + (x))
|
||||
|
||||
/* byte offset of packet data within buffer */
|
||||
#define CB_CHAN_DATA_BYTE_POS (CB_PACKET(CF_DATA_BYTE_POS))
|
||||
|
||||
/* access the link in a buffer, where b is byte pointer to buffer */
|
||||
#define CB_LINK(b) ((p_Buffer)(&(b)[0]))
|
||||
|
||||
#define invalidChannelID(chan) (((int)(chan)) < 0 || \
|
||||
(chan) >= CI_NUM_CHANNELS)
|
||||
|
||||
#endif /* ndef angel_chanpriv_h */
|
||||
|
||||
/* EOF chanpriv.h */
|
|
@ -1,44 +0,0 @@
|
|||
srcname="RDI library"
|
||||
srctrigger=ardi.c
|
||||
|
||||
# per-host:
|
||||
|
||||
. ${srcdir}/../configure.host
|
||||
|
||||
echo "rdi-share/configure.in: host is $host, target is $target"
|
||||
|
||||
if [ ! -f ${srcdir}/../config/${gdb_host_cpu}/${gdb_host}.mh ]; then
|
||||
echo '***' "GDB remote does not support host ${host}" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# We really shouldn't depend on there being a space after XM_FILE= ...
|
||||
hostfile=`awk '$1 == "XM_FILE=" { print $2 }' <${srcdir}/../config/${gdb_host_cpu}/${gdb_host}.mh`
|
||||
|
||||
# per-target:
|
||||
|
||||
. ${srcdir}/../configure.tgt
|
||||
|
||||
echo "rdi-share/configure.in: host_cpu is $host_cpu, target_cpu is $target_cpu"
|
||||
|
||||
if [ ! -f ${srcdir}/../config/${gdb_target_cpu}/${gdb_target}.mt ]; then
|
||||
echo '***' "GDB remote does not support target ${target}" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "${removing}" ] ; then
|
||||
cat ${srcdir}/../config/${gdb_host_cpu}/${gdb_host}.mh ${srcdir}/../config/${gdb_target_cpu}/${gdb_target}.mt | awk '$1 == "#msg" {
|
||||
print substr($0,6)}'
|
||||
fi
|
||||
|
||||
# We really shouldn't depend on there being a space after TM_FILE= ...
|
||||
targetfile=`awk '$1 == "TM_FILE=" { print $2 }' <${srcdir}/../config/${gdb_target_cpu}/${gdb_target}.mt`
|
||||
|
||||
if [ "${target}" = "${host}" ] ; then
|
||||
nativefile=`awk '$1 == "NAT_FILE=" { print $2 }' <${srcdir}/../config/${gdb_host_cpu}/${gdb_host}.mh`
|
||||
fi
|
||||
|
||||
host_makefile_frag=../config/${gdb_host_cpu}/${gdb_host}.mh
|
||||
target_makefile_frag=../config/${gdb_target_cpu}/${gdb_target}.mt
|
||||
|
||||
# post-target:
|
|
@ -1,255 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*
|
||||
* crc.c - provides some "standard" CRC calculation routines.
|
||||
*
|
||||
*/
|
||||
#include "crc.h" /* describes this code */
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/*
|
||||
* crc32 IEEE-802.3 32bit CRC
|
||||
* ----- --------------------
|
||||
*/
|
||||
|
||||
/* This table was generated by the "crctable" program */
|
||||
static const unsigned int crc32table[256] = {
|
||||
/* 0x00 */ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
|
||||
/* 0x04 */ 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
|
||||
/* 0x08 */ 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
|
||||
/* 0x0C */ 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
|
||||
/* 0x10 */ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
|
||||
/* 0x14 */ 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
|
||||
/* 0x18 */ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
|
||||
/* 0x1C */ 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
|
||||
/* 0x20 */ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
|
||||
/* 0x24 */ 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
|
||||
/* 0x28 */ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
|
||||
/* 0x2C */ 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
|
||||
/* 0x30 */ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
|
||||
/* 0x34 */ 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
|
||||
/* 0x38 */ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
|
||||
/* 0x3C */ 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
|
||||
/* 0x40 */ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
|
||||
/* 0x44 */ 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
|
||||
/* 0x48 */ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
|
||||
/* 0x4C */ 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
|
||||
/* 0x50 */ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
|
||||
/* 0x54 */ 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
|
||||
/* 0x58 */ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
|
||||
/* 0x5C */ 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
|
||||
/* 0x60 */ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
|
||||
/* 0x64 */ 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
|
||||
/* 0x68 */ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
|
||||
/* 0x6C */ 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
|
||||
/* 0x70 */ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
|
||||
/* 0x74 */ 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
|
||||
/* 0x78 */ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
|
||||
/* 0x7C */ 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
|
||||
/* 0x80 */ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
|
||||
/* 0x84 */ 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
|
||||
/* 0x88 */ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
|
||||
/* 0x8C */ 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
|
||||
/* 0x90 */ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
|
||||
/* 0x94 */ 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
|
||||
/* 0x98 */ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
|
||||
/* 0x9C */ 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
|
||||
/* 0xA0 */ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
|
||||
/* 0xA4 */ 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
|
||||
/* 0xA8 */ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
|
||||
/* 0xAC */ 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
|
||||
/* 0xB0 */ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
|
||||
/* 0xB4 */ 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
|
||||
/* 0xB8 */ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
|
||||
/* 0xBC */ 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
|
||||
/* 0xC0 */ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
|
||||
/* 0xC4 */ 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
|
||||
/* 0xC8 */ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
|
||||
/* 0xCC */ 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
|
||||
/* 0xD0 */ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
|
||||
/* 0xD4 */ 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
|
||||
/* 0xD8 */ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
|
||||
/* 0xDC */ 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
|
||||
/* 0xE0 */ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
|
||||
/* 0xE4 */ 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
|
||||
/* 0xE8 */ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
|
||||
/* 0xEC */ 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
|
||||
/* 0xF0 */ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
|
||||
/* 0xF4 */ 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
|
||||
/* 0xF8 */ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
|
||||
/* 0xFC */ 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
|
||||
};
|
||||
unsigned int crc32(unsigned char *address, unsigned int size, unsigned int crc)
|
||||
{
|
||||
#if 0
|
||||
/* FAST, but bigger and only good for word-aligned data */
|
||||
unsigned int *daddr = (unsigned int *)address;
|
||||
unsigned int data = FALSE; /* little-endian by default */
|
||||
|
||||
/*
|
||||
* TODO: We should really get the current processor big- or
|
||||
* little-endian state and set "data" accordingly.
|
||||
*/
|
||||
|
||||
/* Perform word loop to save on memory accesses */
|
||||
if (data)
|
||||
/* big-endian */
|
||||
for (; (size > 0); size -= sizeof(unsigned int))
|
||||
{
|
||||
data = *daddr++;
|
||||
crc = (((crc >> 8) & 0x00FFFFFF) ^
|
||||
crc32table[(crc ^ ((data >> 24) & 0xFF)) & 0xFF]);
|
||||
crc = (((crc >> 8) & 0x00FFFFFF) ^
|
||||
crc32table[(crc ^ ((data >> 16) & 0xFF)) & 0xFF]);
|
||||
crc = (((crc >> 8) & 0x00FFFFFF) ^
|
||||
crc32table[(crc ^ ((data >> 8) & 0xFF)) & 0xFF]);
|
||||
crc = (((crc >> 8) & 0x00FFFFFF) ^
|
||||
crc32table[(crc ^ ((data >> 0) & 0xFF)) & 0xFF]);
|
||||
}
|
||||
else
|
||||
for (; (size > 0); size -= sizeof(unsigned int))
|
||||
{
|
||||
data = *daddr++;
|
||||
crc = (((crc >> 8) & 0x00FFFFFF) ^
|
||||
crc32table[(crc ^ ((data >> 0) & 0xFF)) & 0xFF]);
|
||||
crc = (((crc >> 8) & 0x00FFFFFF) ^
|
||||
crc32table[(crc ^ ((data >> 8) & 0xFF)) & 0xFF]);
|
||||
crc = (((crc >> 8) & 0x00FFFFFF) ^
|
||||
crc32table[(crc ^ ((data >> 16) & 0xFF)) & 0xFF]);
|
||||
crc = (((crc >> 8) & 0x00FFFFFF) ^
|
||||
crc32table[(crc ^ ((data >> 24) & 0xFF)) & 0xFF]);
|
||||
}
|
||||
#else
|
||||
for (; (size > 0); size--)
|
||||
/* byte loop */
|
||||
crc = (((crc >> 8) & 0x00FFFFFF) ^
|
||||
crc32table[(crc ^ *address++) & 0x000000FF]);
|
||||
#endif
|
||||
|
||||
return(crc);
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/*
|
||||
* crc16 16bit CRC-CCITT
|
||||
* ----- ---------------
|
||||
* This function provides a table driven 16bit CRC generation for byte data.
|
||||
* This CRC is also known as the HDLC CRC.
|
||||
*/
|
||||
/*
|
||||
* 960201 KWelton
|
||||
*
|
||||
*TODO: Is this correct? The compiler predefines __arm, *not* __ARM
|
||||
*/
|
||||
#ifdef __ARM
|
||||
/*
|
||||
* To make the code quicker on the ARM, we double the table size and
|
||||
* use integer slots rather than short slots for the table.
|
||||
*/
|
||||
static const unsigned int crctableA[16] = {
|
||||
#else
|
||||
static const unsigned short crctableA[16] = {
|
||||
#endif
|
||||
0x0000,
|
||||
0x1081,
|
||||
0x2102,
|
||||
0x3183,
|
||||
0x4204,
|
||||
0x5285,
|
||||
0x6306,
|
||||
0x7387,
|
||||
0x8408,
|
||||
0x9489,
|
||||
0xA50A,
|
||||
0xB58B,
|
||||
0xC60C,
|
||||
0xD68D,
|
||||
0xE70E,
|
||||
0xF78F
|
||||
};
|
||||
|
||||
#ifdef __ARM
|
||||
/* See comments above */
|
||||
static const unsigned int crctableB[16] = {
|
||||
#else
|
||||
static const unsigned short crctableB[16] = {
|
||||
#endif
|
||||
0x0000,
|
||||
0x1189,
|
||||
0x2312,
|
||||
0x329B,
|
||||
0x4624,
|
||||
0x57AD,
|
||||
0x6536,
|
||||
0x74BF,
|
||||
0x8C48,
|
||||
0x9DC1,
|
||||
0xAF5A,
|
||||
0xBED3,
|
||||
0xCA6C,
|
||||
0xDBE5,
|
||||
0xE97E,
|
||||
0xF8F7
|
||||
};
|
||||
|
||||
unsigned short crc16(unsigned char *address, unsigned int size,
|
||||
unsigned short crc)
|
||||
{
|
||||
for (; (size > 0); size--)
|
||||
{
|
||||
/* byte loop */
|
||||
unsigned char data = *address++; /* fetch the next data byte */
|
||||
|
||||
data ^= crc; /* EOR data with current CRC value */
|
||||
crc = ((crctableA[(data & 0xF0) >> 4] ^ crctableB[data & 0x0F]) ^
|
||||
(crc >> 8));
|
||||
}
|
||||
|
||||
return(crc);
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
#if 0 /* not required at the moment */
|
||||
|
||||
/*
|
||||
* elf_hash
|
||||
* --------
|
||||
* This function is derived from the one on page 68 of chapter of the "Unix
|
||||
* SVR4 Programmer's Guide". It is used to generate a hash-code from a
|
||||
* symbol name.
|
||||
*/
|
||||
unsigned int elf_hash(const unsigned char *name)
|
||||
{
|
||||
unsigned int h = 0;
|
||||
unsigned int g;
|
||||
|
||||
/* NULL pointer returns a hash of zero */
|
||||
while (name && (*name))
|
||||
{
|
||||
h = ((h << 4) + *name++);
|
||||
|
||||
if (g = (h & 0xF0000000))
|
||||
h ^= (g >> 24);
|
||||
|
||||
h &= ~g;
|
||||
}
|
||||
|
||||
return(h);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/* EOF crc.c */
|
|
@ -1,88 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*
|
||||
* crc.h - describes some "standard" CRC calculation routines.
|
||||
*/
|
||||
#ifndef angel_crc_h
|
||||
#define angel_crc_h
|
||||
|
||||
/*
|
||||
* manifests
|
||||
*/
|
||||
|
||||
/*
|
||||
* When using "crc32" or "crc16" these initial CRC values must be given to
|
||||
* the respective function the first time it is called. The function can
|
||||
* then be called with the return value from the last call of the function
|
||||
* to generate a running CRC over multiple data blocks.
|
||||
* When the last data block has been processed using the "crc32" algorithm
|
||||
* the CRC value should be inverted to produce the final CRC value:
|
||||
* e.g. CRC = ~CRC
|
||||
*/
|
||||
|
||||
#define startCRC32 (0xFFFFFFFF) /* CRC initialised to all 1s */
|
||||
#define startCRC16 (0x0000) /* CRC initialised to all 0s */
|
||||
|
||||
/*
|
||||
* For the CRC-32 residual to be calculated correctly requires that the CRC
|
||||
* value is in memory little-endian due to the byte read, bit-ordering
|
||||
* nature of the algorithm.
|
||||
*/
|
||||
#define CRC32residual (0xDEBB20E3) /* good CRC-32 residual */
|
||||
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/*
|
||||
* exported functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* Function: crc32
|
||||
* Purpose: Provides a table driven implementation of the IEEE-802.3
|
||||
* 32-bit CRC algorithm for byte data.
|
||||
*
|
||||
* Params:
|
||||
* Input: address pointer to the byte data
|
||||
* size number of bytes of data to be processed
|
||||
* crc initial CRC value to be used (can be the output
|
||||
* from a previous call to this function).
|
||||
* Returns:
|
||||
* OK: 32-bit CRC value for the specified data
|
||||
*/
|
||||
extern unsigned int crc32(unsigned char *address, unsigned int size,
|
||||
unsigned int crc);
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/*
|
||||
*
|
||||
* Function: crc16
|
||||
* Purpose: Generates a table driven 16-bit CRC-CCITT for byte data
|
||||
*
|
||||
* Params:
|
||||
* Input: address pointer to the byte data
|
||||
* size number of bytes of data to be processed
|
||||
* crc initial CRC value to be used (can be the output
|
||||
* from a previous call to this function).
|
||||
*
|
||||
* Returns:
|
||||
* OK: 16-bit CRC value for the specified data
|
||||
*/
|
||||
extern unsigned short crc16(unsigned char *address, unsigned int size,
|
||||
unsigned short crc);
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
#endif /* !defined(angel_crc_h) */
|
||||
|
||||
/* EOF crc.h */
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ARM symbolic debugger toolbox: dbg_conf.h
|
||||
*/
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
#ifndef Dbg_Conf__h
|
||||
|
||||
#define Dbg_Conf__h
|
||||
|
||||
typedef struct Dbg_ConfigBlock {
|
||||
int bytesex;
|
||||
int fpe; /* Target should initialise FPE */
|
||||
long memorysize;
|
||||
unsigned long cpu_speed;/* Cpu speed (HZ) */
|
||||
int serialport; /*) remote connection parameters */
|
||||
int seriallinespeed; /*) (serial connection) */
|
||||
int parallelport; /*) ditto */
|
||||
int parallellinespeed; /*) (parallel connection) */
|
||||
char *ethernettarget; /* name of remote ethernet target */
|
||||
int processor; /* processor the armulator is to emulate (eg ARM60) */
|
||||
int rditype; /* armulator / remote processor */
|
||||
int heartbeat_on; /* angel heartbeat */
|
||||
int drivertype; /* parallel / serial / etc */
|
||||
char const *configtoload;
|
||||
char const *memconfigtoload;
|
||||
int flags;
|
||||
} Dbg_ConfigBlock;
|
||||
|
||||
#define Dbg_ConfigFlag_Reset 1
|
||||
#define Dbg_ConfigFlag_LLSymsNeedPrefix 2
|
||||
|
||||
typedef struct Dbg_HostosInterface Dbg_HostosInterface;
|
||||
/* This structure allows access by the (host-independent) C-library support
|
||||
module of armulator or pisd (armos.c) to host-dependent functions for
|
||||
which there is no host-independent interface. Its contents are unknown
|
||||
to the debugger toolbox.
|
||||
The assumption is that, in a windowed system, fputc(stderr) for example
|
||||
may not achieve the desired effect of the character appearing in some
|
||||
window.
|
||||
*/
|
||||
|
||||
#endif
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ARM symbolic debugger toolbox: dbg_cp.h
|
||||
*/
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
#ifndef Dbg_CP__h
|
||||
|
||||
#define Dbg_CP__h
|
||||
|
||||
#define Dbg_Access_Readable 1
|
||||
#define Dbg_Access_Writable 2
|
||||
#define Dbg_Access_CPDT 4 /* else CPRT */
|
||||
|
||||
typedef struct {
|
||||
unsigned short rmin, rmax;
|
||||
/* a single description can be used for a range of registers with
|
||||
the same properties *accessed via CPDT instructions*
|
||||
*/
|
||||
unsigned char nbytes; /* size of register */
|
||||
unsigned char access; /* see above (Access_xxx) */
|
||||
union {
|
||||
struct { /* CPDT instructions do not allow the coprocessor much freedom:
|
||||
only bit 22 ('N') and 12-15 ('CRd') are free for the
|
||||
coprocessor to use as it sees fit.
|
||||
*/
|
||||
unsigned char nbit;
|
||||
unsigned char rdbits;
|
||||
} cpdt;
|
||||
struct { /* CPRT instructions have much more latitude. The bits fixed
|
||||
by the ARM are 24..31 (condition mask & opcode)
|
||||
20 (direction)
|
||||
8..15 (cpnum, arm register)
|
||||
4 (CPRT not CPDO)
|
||||
leaving 14 bits free to the coprocessor (fortunately
|
||||
falling within two bytes).
|
||||
*/
|
||||
unsigned char read_b0, read_b1,
|
||||
write_b0, write_b1;
|
||||
} cprt;
|
||||
} accessinst;
|
||||
} Dbg_CoProRegDesc;
|
||||
|
||||
struct Dbg_CoProDesc {
|
||||
int entries;
|
||||
Dbg_CoProRegDesc regdesc[1/* really nentries */];
|
||||
};
|
||||
|
||||
#define Dbg_CoProDesc_Size(n) (sizeof(struct Dbg_CoProDesc) + ((n)-1)*sizeof(Dbg_CoProRegDesc))
|
||||
|
||||
#endif
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ARM debugger toolbox : dbg_hif.c
|
||||
* Description of the Dbg_HostosInterface structure. This is *NOT*
|
||||
* part of the debugger toolbox, but it is required by 2 back ends
|
||||
* (armul & pisd) and two front ends (armsd & wdbg), so putting it
|
||||
* in the toolbox is the only way of avoiding multiple copies.
|
||||
*/
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
#ifndef dbg_hif__h
|
||||
#define dbg_hif__h
|
||||
|
||||
#if defined __STDC__ || defined ALMOST_STDC
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# include <varargs.h>
|
||||
#endif
|
||||
|
||||
typedef void Hif_DbgPrint(void *arg, const char *format, va_list ap);
|
||||
typedef void Hif_DbgPause(void *arg);
|
||||
|
||||
typedef void Hif_WriteC(void *arg, int c);
|
||||
typedef int Hif_ReadC(void *arg);
|
||||
typedef int Hif_Write(void *arg, char const *buffer, int len);
|
||||
typedef char *Hif_GetS(void *arg, char *buffer, int len);
|
||||
|
||||
typedef void Hif_RDIResetProc(void *arg);
|
||||
|
||||
struct Dbg_HostosInterface {
|
||||
Hif_DbgPrint *dbgprint;
|
||||
Hif_DbgPause *dbgpause;
|
||||
void *dbgarg;
|
||||
|
||||
Hif_WriteC *writec;
|
||||
Hif_ReadC *readc;
|
||||
Hif_Write *write;
|
||||
Hif_GetS *gets;
|
||||
void *hostosarg;
|
||||
|
||||
Hif_RDIResetProc *reset;
|
||||
void *resetarg;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,509 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ARM debugger toolbox : dbg_rdi.h
|
||||
*/
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
#ifndef dbg_rdi__h
|
||||
#define dbg_rdi__h
|
||||
|
||||
/***************************************************************************\
|
||||
* Other RDI values *
|
||||
\***************************************************************************/
|
||||
|
||||
#define RDISex_Little 0 /* the byte sex of the debuggee */
|
||||
#define RDISex_Big 1
|
||||
#define RDISex_DontCare 2
|
||||
|
||||
#define RDIPoint_EQ 0 /* the different types of break/watchpoints */
|
||||
#define RDIPoint_GT 1
|
||||
#define RDIPoint_GE 2
|
||||
#define RDIPoint_LT 3
|
||||
#define RDIPoint_LE 4
|
||||
#define RDIPoint_IN 5
|
||||
#define RDIPoint_OUT 6
|
||||
#define RDIPoint_MASK 7
|
||||
|
||||
#define RDIPoint_16Bit 16 /* 16-bit breakpoint */
|
||||
#define RDIPoint_Conditional 32
|
||||
|
||||
/* ORRed with point type in extended RDP break and watch messages */
|
||||
#define RDIPoint_Inquiry 64
|
||||
#define RDIPoint_Handle 128 /* messages */
|
||||
|
||||
#define RDIWatch_ByteRead 1 /* types of data accesses to watch for*/
|
||||
#define RDIWatch_HalfRead 2
|
||||
#define RDIWatch_WordRead 4
|
||||
#define RDIWatch_ByteWrite 8
|
||||
#define RDIWatch_HalfWrite 16
|
||||
#define RDIWatch_WordWrite 32
|
||||
|
||||
#define RDIReg_R15 (1L << 15) /* mask values for CPU */
|
||||
#define RDIReg_PC (1L << 16)
|
||||
#define RDIReg_CPSR (1L << 17)
|
||||
#define RDIReg_SPSR (1L << 18)
|
||||
#define RDINumCPURegs 19
|
||||
|
||||
#define RDINumCPRegs 10 /* current maximum */
|
||||
|
||||
#define RDIMode_Curr 255
|
||||
|
||||
/* RDI_Info subcodes */
|
||||
/* rdp in parameters are all preceded by */
|
||||
/* in byte = RDP_Info, word = info subcode */
|
||||
/* out parameters are all preceded by */
|
||||
/* out byte = RDP_Return */
|
||||
|
||||
#define RDIInfo_Target 0
|
||||
/* rdi: out ARMword *targetflags, out ARMword *processor id */
|
||||
/* rdp: in none, out word targetflags, word processorid, byte status */
|
||||
/* the following bits are defined in targetflags */
|
||||
# define RDITarget_LogSpeed 0x0f
|
||||
# define RDITarget_HW 0x10 /* else emulator */
|
||||
# define RDITarget_AgentMaxLevel 0xe0
|
||||
# define RDITarget_AgentLevelShift 5
|
||||
# define RDITarget_DebuggerMinLevel 0x700
|
||||
# define RDITarget_DebuggerLevelShift 8
|
||||
# define RDITarget_CanReloadAgent 0x800
|
||||
# define RDITarget_CanInquireLoadSize 0x1000
|
||||
# define RDITarget_UnderstandsRDPInterrupt 0x2000
|
||||
# define RDITarget_CanProfile 0x4000
|
||||
# define RDITarget_Code16 0x8000
|
||||
# define RDITarget_HasCommsChannel 0x10000
|
||||
|
||||
#define RDIInfo_Points 1
|
||||
/* rdi: out ARMword *pointcapabilities */
|
||||
/* rdp: in none, out word pointcapabilities, byte status */
|
||||
/* the following bits are defined in pointcapabilities */
|
||||
# define RDIPointCapability_Comparison 1
|
||||
# define RDIPointCapability_Range 2
|
||||
/* 4 to 128 are RDIWatch_xx{Read,Write} left-shifted by two */
|
||||
# define RDIPointCapability_Mask 0x100
|
||||
# define RDIPointCapability_ThreadBreak 0x200
|
||||
# define RDIPointCapability_ThreadWatch 0x400
|
||||
# define RDIPointCapability_CondBreak 0x800
|
||||
# define RDIPointCapability_Status 0x1000 /* status enquiries available */
|
||||
|
||||
#define RDIInfo_Step 2
|
||||
/* rdi: out ARMword *stepcapabilities */
|
||||
/* rdp: in none, out word stepcapabilities, byte status */
|
||||
/* the following bits are defined in stepcapabilities */
|
||||
# define RDIStep_Multiple 1
|
||||
# define RDIStep_PCChange 2
|
||||
# define RDIStep_Single 4
|
||||
|
||||
#define RDIInfo_MMU 3
|
||||
/* rdi: out ARMword *mmuidentity */
|
||||
/* rdp: in none, out word mmuidentity, byte status */
|
||||
|
||||
#define RDIInfo_DownLoad 4
|
||||
/* Inquires whether configuration download and selection is available. */
|
||||
/* rdp: in none, out byte status */
|
||||
/* No argument, no return value. status == ok if available */
|
||||
|
||||
#define RDIInfo_SemiHosting 5
|
||||
/* Inquires whether RDISemiHosting_* RDI_Info calls are available. */
|
||||
/* rdp: in none, out byte status */
|
||||
/* No argument, no return value. status == ok if available */
|
||||
|
||||
#define RDIInfo_CoPro 6
|
||||
/* Inquires whether CoPro RDI_Info calls are available. */
|
||||
/* rdp: in none, out byte status */
|
||||
/* No argument, no return value. status == ok if available */
|
||||
|
||||
#define RDIInfo_Icebreaker 7
|
||||
/* Inquires whether debuggee controlled by IceBreaker. */
|
||||
/* rdp: in none, out byte status */
|
||||
/* No argument, no return value. status == ok if available */
|
||||
|
||||
#define RDIMemory_Access 8
|
||||
/* rdi: out RDI_MemAccessStats *p, in ARMword *handle */
|
||||
/* rdp: in word handle */
|
||||
/* out word nreads, word nwrites, word sreads, word swrites, */
|
||||
/* word ns, word s, byte status */
|
||||
|
||||
/* Get memory access information for memory block with specified handle */
|
||||
|
||||
#define RDIMemory_Map 9
|
||||
/* rdi: in RDI_MemDescr md[n], in ARMword *n */
|
||||
/* rdp: in word n, n * { */
|
||||
/* word handle, word start, word limit, */
|
||||
/* byte width, byte access */
|
||||
/* word Nread_ns, word Nwrite_ns, */
|
||||
/* word Sread_ns, word Swrite_ns} */
|
||||
/* out byte status */
|
||||
/* Sets memory characteristics. */
|
||||
|
||||
#define RDISet_CPUSpeed 10
|
||||
/* rdi: in ARMword *speed */
|
||||
/* rdp: in word speed, out byte status */
|
||||
/* Sets CPU speed (in ns) */
|
||||
|
||||
#define RDIRead_Clock 12
|
||||
/* rdi: out ARMword *ns, out ARMword *s */
|
||||
/* rdp: in none, out word ns, word s, byte status */
|
||||
/* Reads simulated time */
|
||||
|
||||
#define RDIInfo_Memory_Stats 13
|
||||
/* Inquires whether RDI_Info codes 8-10 are available */
|
||||
/* rdp: in none, out byte status */
|
||||
/* No argument, no return value. status == ok if available */
|
||||
|
||||
/* The next two are only to be used if RDIInfo_DownLoad returned no */
|
||||
/* error */
|
||||
#define RDIConfig_Count 14
|
||||
/* rdi: out ARMword *count */
|
||||
/* rdp: out byte status, word count (if status == OK) */
|
||||
|
||||
/* In addition, the next one is only to be used if RDIConfig_Count */
|
||||
/* returned no error */
|
||||
typedef struct { unsigned32 version; char name[32]; } RDI_ConfigDesc;
|
||||
#define RDIConfig_Nth 15
|
||||
/* rdi: in ARMword *n, out RDI_ConfigDesc * */
|
||||
/* rdp: in word n */
|
||||
/* out word version, byte namelen, bytes * bytelen name, */
|
||||
/* byte status */
|
||||
|
||||
/* Set a front-end polling function to be used from within driver poll */
|
||||
/* loops */
|
||||
typedef void RDI_PollProc(void *);
|
||||
typedef struct { RDI_PollProc *p; void *arg; } RDI_PollDesc;
|
||||
#define RDISet_PollProc 16
|
||||
/* rdi: in RDI_PollDesc const *from, RDI_PollDesc *to */
|
||||
/* if from non-NULL, sets the polling function from it */
|
||||
/* if to non-NULL, returns the previous polling function to it */
|
||||
/* No corresponding RDP operation */
|
||||
|
||||
/* Called on debugger startup to see if the target is ready to execute */
|
||||
#define RDIInfo_CanTargetExecute 20
|
||||
/* rdi: in void
|
||||
* out byte status (RDIError_NoError => Yes, Otherwise No)
|
||||
*/
|
||||
|
||||
/* Called to set the top of target memory in an ICEman2 system
|
||||
* This is then used by ICEman to tell the C Library via the INFOHEAP
|
||||
* SWI where the stack should start.
|
||||
* Note that only ICEman2 supports this call. Other systems eg.
|
||||
* Demon, Angel, will simply return an error, which means that setting
|
||||
* the top of memory in this fashion is not supported.
|
||||
*/
|
||||
#define RDIInfo_SetTopMem 21
|
||||
/* rdi: in word mem_top
|
||||
* out byte status (RDIError_NoError => Done, Other => Not supported
|
||||
*/
|
||||
|
||||
/* Called before performing a loadagent to determine the endianess of
|
||||
* the debug agent, so that images of the wrong bytesex can be
|
||||
* complained about
|
||||
*/
|
||||
#define RDIInfo_AgentEndianess 22
|
||||
/* rdi: in void
|
||||
* out byte status
|
||||
* status should be RDIError_LittleEndian or RDIError_BigEndian
|
||||
* any other value indicates the target does not support this
|
||||
* request, so the debugger will have to make a best guess, which
|
||||
* probably means only allow little endian loadagenting.
|
||||
*/
|
||||
|
||||
/* The next two are only to be used if the value returned by */
|
||||
/* RDIInfo_Points has RDIPointCapability_Status set. */
|
||||
#define RDIPointStatus_Watch 0x80
|
||||
#define RDIPointStatus_Break 0x81
|
||||
/* rdi: inout ARMword * (in handle, out hwresource), out ARMword *type */
|
||||
/* rdp: in word handle, out word hwresource, word type, byte status */
|
||||
|
||||
#define RDISignal_Stop 0x100
|
||||
/* Requests that the debuggee stop */
|
||||
/* No arguments, no return value */
|
||||
/* rdp: no reply (when the debuggee stops, there will be a reply to the */
|
||||
/* step or execute request which started it) */
|
||||
|
||||
#define RDIVector_Catch 0x180
|
||||
/* rdi: in ARMword *bitmap */
|
||||
/* rdp: int word bitmap, out byte status */
|
||||
/* bit i in bitmap set to cause vector i to cause entry to debugger */
|
||||
|
||||
/* The next four are only to be used if RDIInfo_Semihosting returned */
|
||||
/* no error */
|
||||
#define RDISemiHosting_SetState 0x181
|
||||
/* rdi: in ARMword *semihostingstate */
|
||||
/* rdp: in word semihostingstate, out byte status */
|
||||
#define RDISemiHosting_GetState 0x182
|
||||
/* rdi: out ARMword *semihostingstate */
|
||||
/* rdp: in none, out word semihostingstate, byte status */
|
||||
#define RDISemiHosting_SetVector 0x183
|
||||
/* rdi: in ARMword *semihostingvector */
|
||||
/* rdp: in word semihostingvector, out byte status */
|
||||
#define RDISemiHosting_GetVector 0x184
|
||||
/* rdi: out ARMword *semihostingvector */
|
||||
/* rdp: in none, out word semihostingvector, byte status */
|
||||
|
||||
/* The next two are only to be used if RDIInfo_Icebreaker returned */
|
||||
/* no error */
|
||||
#define RDIIcebreaker_GetLocks 0x185
|
||||
/* rdi: out ARMword *lockedstate */
|
||||
/* rdp: in none, out word lockedstate, byte status */
|
||||
|
||||
#define RDIIcebreaker_SetLocks 0x186
|
||||
/* rdi: in ARMword *lockedstate */
|
||||
/* rdp: in word lockedstate, out byte status */
|
||||
|
||||
/* lockedstate is a bitmap of the icebreaker registers locked against */
|
||||
/* use by IceMan (because explicitly written by the user) */
|
||||
|
||||
#define RDIInfo_GetLoadSize 0x187
|
||||
/* rdi: out ARMword *maxloadsize */
|
||||
/* rdp: in none, out word maxloadsize, byte status */
|
||||
/* Inquires the maximum length of data transfer the agent is prepared */
|
||||
/* to receive */
|
||||
/* Only usable if RDIInfo_Target returned RDITarget_CanInquireLoadSize */
|
||||
/* rdi: out ARMword *size */
|
||||
|
||||
/* Only to be used if the value returned by RDIInfo_Target had */
|
||||
/* RDITarget_HasCommsChannel set */
|
||||
typedef void RDICCProc_ToHost(void *arg, ARMword data);
|
||||
typedef void RDICCProc_FromHost(void *arg, ARMword *data, int *valid);
|
||||
|
||||
#define RDICommsChannel_ToHost 0x188
|
||||
/* rdi: in RDICCProc_ToHost *, in void *arg */
|
||||
/* rdp: in byte connect, out byte status */
|
||||
#define RDICommsChannel_FromHost 0x189
|
||||
/* rdi: in RDICCProc_FromHost *, in void *arg */
|
||||
/* rdp: in byte connect, out byte status */
|
||||
|
||||
/* These 4 are only to be used if RDIInfo_Semihosting returns no error */
|
||||
#define RDISemiHosting_SetARMSWI 0x190
|
||||
/* rdi: in ARMword ARM_SWI_number */
|
||||
/* rdp: in ARMword ARM_SWI_number, out byte status */
|
||||
|
||||
#define RDISemiHosting_GetARMSWI 0x191
|
||||
/* rdi: out ARMword ARM_SWI_number */
|
||||
/* rdp: out ARMword ARM_SWI_number, byte status */
|
||||
|
||||
#define RDISemiHosting_SetThumbSWI 0x192
|
||||
/* rdi: in ARMword Thumb_SWI_number */
|
||||
/* rdp: in ARMword Thumb_SWI_number, out byte status */
|
||||
|
||||
#define RDISemiHosting_GetThumbSWI 0x193
|
||||
/* rdi: out ARMword ARM_Thumb_number */
|
||||
/* rdp: out ARMword ARM_Thumb_number, byte status */
|
||||
|
||||
|
||||
#define RDICycles 0x200
|
||||
/* rdi: out ARMword cycles[12] */
|
||||
/* rdp: in none, out 6 words cycles, byte status */
|
||||
/* the rdi result represents 6 big-endian doublewords; the rdp results */
|
||||
/* return values for the ls halves of these */
|
||||
# define RDICycles_Size 48
|
||||
|
||||
#define RDIErrorP 0x201
|
||||
/* rdi: out ARMaddress *errorp */
|
||||
/* rdp: in none, out word errorp, byte status */
|
||||
/* Returns the error pointer associated with the last return from step */
|
||||
/* or execute with status RDIError_Error. */
|
||||
|
||||
#define RDISet_Cmdline 0x300
|
||||
/* rdi: in char *commandline (a null-terminated string) */
|
||||
/* No corresponding RDP operation (cmdline is sent to the agent in */
|
||||
/* response to SWI_GetEnv) */
|
||||
|
||||
#define RDISet_RDILevel 0x301
|
||||
/* rdi: in ARMword *level */
|
||||
/* rdp: in word level, out byte status */
|
||||
/* Sets the RDI/RDP protocol level to be used (must lie between the */
|
||||
/* limits returned by RDIInfo_Target). */
|
||||
|
||||
#define RDISet_Thread 0x302
|
||||
/* rdi: in ARMword *threadhandle */
|
||||
/* rdp: in word threadhandle, out byte status */
|
||||
/* Sets the thread context for subsequent thread-sensitive operations */
|
||||
/* (null value sets no thread) */
|
||||
|
||||
/* The next two are only to be used if RDI_read or RDI_write returned */
|
||||
/* RDIError_LittleEndian or RDIError_BigEndian, to signify that the */
|
||||
/* debugger has noticed. */
|
||||
#define RDIInfo_AckByteSex 0x303
|
||||
/* rdi: in ARMword *sex (RDISex_Little or RDISex_Big) */
|
||||
|
||||
/* The next two are only to be used if RDIInfo_CoPro returned no error */
|
||||
#define RDIInfo_DescribeCoPro 0x400
|
||||
/* rdi: in int *cpno, Dbg_CoProDesc *cpd */
|
||||
/* rdp: in byte cpno, */
|
||||
/* cpd->entries * { */
|
||||
/* byte rmin, byte rmax, byte nbytes, byte access, */
|
||||
/* byte cprt_r_b0, cprt_r_b1, cprt_w_b0, cprt_w_b1} */
|
||||
/* byte = 255 */
|
||||
/* out byte status */
|
||||
|
||||
#define RDIInfo_RequestCoProDesc 0x401
|
||||
/* rdi: in int *cpno, out Dbg_CoProDesc *cpd */
|
||||
/* rpd: in byte cpno */
|
||||
/* out nentries * { */
|
||||
/* byte rmin, byte rmax, byte nbytes, byte access, */
|
||||
/* } */
|
||||
/* byte = 255, byte status */
|
||||
|
||||
#define RDIInfo_Log 0x800
|
||||
/* rdi: out ARMword *logsetting */
|
||||
/* No corresponding RDP operation */
|
||||
#define RDIInfo_SetLog 0x801
|
||||
/* rdi: in ARMword *logsetting */
|
||||
/* No corresponding RDP operation */
|
||||
|
||||
#define RDIProfile_Stop 0x500
|
||||
/* No arguments, no return value */
|
||||
/* rdp: in none, out byte status */
|
||||
/* Requests that pc sampling stop */
|
||||
|
||||
#define RDIProfile_Start 0x501
|
||||
/* rdi: in ARMword *interval */
|
||||
/* rdp: in word interval, out byte status */
|
||||
/* Requests that pc sampling start, with period <interval> usec */
|
||||
|
||||
#define RDIProfile_WriteMap 0x502
|
||||
/* rdi: in ARMword map[] */
|
||||
/* map[0] is the length of the array, subsequent elements are sorted */
|
||||
/* and are the base of ranges for pc sampling (so if the sampled pc */
|
||||
/* lies between map[i] and map[i+1], count[i] is incremented). */
|
||||
/* rdp: a number of messages, each of form: */
|
||||
/* in word len, word size, word offset, <size> words map data */
|
||||
/* out status */
|
||||
/* len, size and offset are all word counts. */
|
||||
|
||||
#define RDIProfile_ReadMap 0x503
|
||||
/* rdi: in ARMword *len, out ARMword counts[len] */
|
||||
/* Requests that the counts array be set to the accumulated pc sample */
|
||||
/* counts */
|
||||
/* rdp: a number of messages, each of form: */
|
||||
/* in word offset, word size */
|
||||
/* out <size> words, status */
|
||||
/* len, size and offset are all word counts. */
|
||||
|
||||
#define RDIProfile_ClearCounts 0x504
|
||||
/* No arguments, no return value */
|
||||
/* rdp: in none, out byte status */
|
||||
/* Requests that pc sample counts be set to zero */
|
||||
|
||||
#define RDIInfo_RequestReset 0x900
|
||||
/* Request reset of the target environment */
|
||||
/* No arguments, no return value */
|
||||
/* No RDP equivalent, sends an RDP reset */
|
||||
|
||||
#define RDIInfo_CapabilityRequest 0x8000
|
||||
/* Request whether the interface supports the named capability. The */
|
||||
/* capability is specified by or'ing the RDIInfo number with this, and */
|
||||
/* sending that request */
|
||||
/* rdi: in none */
|
||||
/* rdp: in none, out byte status */
|
||||
|
||||
typedef struct {
|
||||
ARMword len;
|
||||
ARMword map[1];
|
||||
} RDI_ProfileMap;
|
||||
|
||||
typedef unsigned32 PointHandle;
|
||||
typedef unsigned32 ThreadHandle;
|
||||
#define RDINoPointHandle ((PointHandle)-1L)
|
||||
#define RDINoHandle ((ThreadHandle)-1L)
|
||||
|
||||
struct Dbg_ConfigBlock;
|
||||
struct Dbg_HostosInterface;
|
||||
struct Dbg_MCState;
|
||||
typedef int rdi_open_proc(unsigned type, struct Dbg_ConfigBlock const *config,
|
||||
struct Dbg_HostosInterface const *i,
|
||||
struct Dbg_MCState *dbg_state);
|
||||
typedef int rdi_close_proc(void);
|
||||
typedef int rdi_read_proc(ARMword source, void *dest, unsigned *nbytes);
|
||||
typedef int rdi_write_proc(const void *source, ARMword dest, unsigned *nbytes);
|
||||
typedef int rdi_CPUread_proc(unsigned mode, unsigned32 mask, ARMword *state);
|
||||
typedef int rdi_CPUwrite_proc(unsigned mode, unsigned32 mask, ARMword const *state);
|
||||
typedef int rdi_CPread_proc(unsigned CPnum, unsigned32 mask, ARMword *state);
|
||||
typedef int rdi_CPwrite_proc(unsigned CPnum, unsigned32 mask, ARMword const *state);
|
||||
typedef int rdi_setbreak_proc(ARMword address, unsigned type, ARMword bound,
|
||||
PointHandle *handle);
|
||||
typedef int rdi_clearbreak_proc(PointHandle handle);
|
||||
typedef int rdi_setwatch_proc(ARMword address, unsigned type, unsigned datatype,
|
||||
ARMword bound, PointHandle *handle);
|
||||
typedef int rdi_clearwatch_proc(PointHandle handle);
|
||||
typedef int rdi_execute_proc(PointHandle *handle);
|
||||
typedef int rdi_step_proc(unsigned ninstr, PointHandle *handle);
|
||||
typedef int rdi_info_proc(unsigned type, ARMword *arg1, ARMword *arg2);
|
||||
typedef int rdi_pointinq_proc(ARMword *address, unsigned type,
|
||||
unsigned datatype, ARMword *bound);
|
||||
|
||||
typedef enum {
|
||||
RDI_ConfigCPU,
|
||||
RDI_ConfigSystem
|
||||
} RDI_ConfigAspect;
|
||||
|
||||
typedef enum {
|
||||
RDI_MatchAny,
|
||||
RDI_MatchExactly,
|
||||
RDI_MatchNoEarlier
|
||||
} RDI_ConfigMatchType;
|
||||
|
||||
typedef int rdi_addconfig_proc(unsigned32 nbytes);
|
||||
typedef int rdi_loadconfigdata_proc(unsigned32 nbytes, char const *data);
|
||||
typedef int rdi_selectconfig_proc(RDI_ConfigAspect aspect, char const *name,
|
||||
RDI_ConfigMatchType matchtype, unsigned versionreq,
|
||||
unsigned *versionp);
|
||||
|
||||
typedef char *getbufferproc(void *getbarg, unsigned32 *sizep);
|
||||
typedef int rdi_loadagentproc(ARMword dest, unsigned32 size, getbufferproc *getb, void *getbarg);
|
||||
typedef int rdi_targetisdead(void);
|
||||
|
||||
typedef struct {
|
||||
int itemmax;
|
||||
char const * const *names;
|
||||
} RDI_NameList;
|
||||
|
||||
typedef RDI_NameList const *rdi_namelistproc(void);
|
||||
|
||||
typedef int rdi_errmessproc(char *buf, int buflen, int errnum);
|
||||
|
||||
struct RDIProcVec {
|
||||
char rditypename[12];
|
||||
|
||||
rdi_open_proc *open;
|
||||
rdi_close_proc *close;
|
||||
rdi_read_proc *read;
|
||||
rdi_write_proc *write;
|
||||
rdi_CPUread_proc *CPUread;
|
||||
rdi_CPUwrite_proc *CPUwrite;
|
||||
rdi_CPread_proc *CPread;
|
||||
rdi_CPwrite_proc *CPwrite;
|
||||
rdi_setbreak_proc *setbreak;
|
||||
rdi_clearbreak_proc *clearbreak;
|
||||
rdi_setwatch_proc *setwatch;
|
||||
rdi_clearwatch_proc *clearwatch;
|
||||
rdi_execute_proc *execute;
|
||||
rdi_step_proc *step;
|
||||
rdi_info_proc *info;
|
||||
/* V2 RDI */
|
||||
rdi_pointinq_proc *pointinquiry;
|
||||
|
||||
/* These three useable only if RDIInfo_DownLoad returns no error */
|
||||
rdi_addconfig_proc *addconfig;
|
||||
rdi_loadconfigdata_proc *loadconfigdata;
|
||||
rdi_selectconfig_proc *selectconfig;
|
||||
|
||||
rdi_namelistproc *drivernames;
|
||||
rdi_namelistproc *cpunames;
|
||||
|
||||
rdi_errmessproc *errmess;
|
||||
|
||||
/* Only if RDIInfo_Target returns a value with RDITarget_LoadAgent set */
|
||||
rdi_loadagentproc *loadagent;
|
||||
rdi_targetisdead *targetisdead;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,258 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*
|
||||
* Project: ANGEL
|
||||
*
|
||||
* Title: Public client interface to devices
|
||||
*/
|
||||
|
||||
#ifndef angel_devclnt_h
|
||||
#define angel_devclnt_h
|
||||
|
||||
/*
|
||||
* This header exports the public interface to Angel-compliant device
|
||||
* drivers.
|
||||
*
|
||||
* They are intended to be used solely by Angel, not by the User
|
||||
* Application. See devappl.h for the User Application interface to
|
||||
* the device drivers.
|
||||
*/
|
||||
|
||||
#include "devices.h"
|
||||
|
||||
/* General purpose constants, macros, enums, typedefs */
|
||||
|
||||
/*
|
||||
* possible channels at device level
|
||||
*
|
||||
* XXX
|
||||
*
|
||||
* these are used as array indices, so be specific about their values
|
||||
*/
|
||||
typedef enum DevChanID {
|
||||
DC_DBUG = 0, /* reliable debug packets
|
||||
* containing SDBG, CLIB,UDBG, etc.) */
|
||||
DC_APPL = 1, /* application packets */
|
||||
DC_NUM_CHANNELS
|
||||
} DevChanID;
|
||||
|
||||
/* Publically-accessible globals */
|
||||
/* none */
|
||||
|
||||
/* Public functions */
|
||||
|
||||
/*
|
||||
* Function: angel_DeviceWrite
|
||||
* Purpose: The main entry point for asynchronous writes to a device.
|
||||
*
|
||||
* Params:
|
||||
* Input: devID index of the device to write to
|
||||
* buff data to write
|
||||
* length how much data to write
|
||||
* callback callback here when write finished
|
||||
* or error
|
||||
* cb_data data to be passed to callback
|
||||
* chanID device channel to use
|
||||
* Output: -
|
||||
* In/Out: -
|
||||
*
|
||||
* Returns: DE_OKAY write request is underway
|
||||
* DE_NO_DEV no such device
|
||||
* DE_BAD_DEV device does not support angel writes
|
||||
* DE_BAD_CHAN no such device channel
|
||||
* DE_BUSY device busy with another write
|
||||
* DE_INVAL silly length
|
||||
*
|
||||
* Reads globals: -
|
||||
* Modifies globals: -
|
||||
*
|
||||
* Other side effects: -
|
||||
*
|
||||
* Commence asynchronous transmission of a buffer on a device. The
|
||||
* callback will occur when the write completes or if there is an
|
||||
* error.
|
||||
*
|
||||
* This must be called for each packet to be sent.
|
||||
*/
|
||||
|
||||
DevError angel_DeviceWrite(DeviceID devID, p_Buffer buff,
|
||||
unsigned length, DevWrite_CB_Fn callback,
|
||||
void *cb_data, DevChanID chanID);
|
||||
|
||||
|
||||
/*
|
||||
* Function: angel_DeviceRegisterRead
|
||||
* Purpose: The main entry point for asynchronous reads from a device.
|
||||
*
|
||||
* Params:
|
||||
* Input: devID index of the device to read from
|
||||
* callback callback here when read finished
|
||||
* or error
|
||||
* cb_data data to be passed to callback
|
||||
* get_buff callback to be used to acquire buffer
|
||||
* for incoming packets
|
||||
* getb_data data to be passed to get_buff
|
||||
* chanID device channel to use
|
||||
* Output: -
|
||||
* In/Out: -
|
||||
*
|
||||
* Returns: DE_OKAY read request is underway
|
||||
* DE_NO_DEV no such device
|
||||
* DE_BAD_DEV device does not support angel reads
|
||||
* DE_BAD_CHAN no such device channel
|
||||
* DE_BUSY device busy with another read
|
||||
* DE_INVAL silly length
|
||||
*
|
||||
* Reads globals: -
|
||||
* Modifies globals: -
|
||||
*
|
||||
* Other side effects: -
|
||||
*
|
||||
* Register asynchronous packet read from a device. The callback will
|
||||
* occur when the read completes or if there is an error.
|
||||
*
|
||||
* This is persistent: the read remains registered for all incoming
|
||||
* packets on the device channel.
|
||||
*/
|
||||
|
||||
DevError angel_DeviceRegisterRead(DeviceID devID,
|
||||
DevRead_CB_Fn callback, void *cb_data,
|
||||
DevGetBuff_Fn get_buff, void *getb_data,
|
||||
DevChanID chanID);
|
||||
|
||||
|
||||
/*
|
||||
* Function: angel_DeviceControl
|
||||
* Purpose: Call a control function for a device
|
||||
*
|
||||
* Params:
|
||||
* Input: devID index of the device to control to
|
||||
* op operation to perform
|
||||
* arg parameter depending on op
|
||||
*
|
||||
* Returns: DE_OKAY control request is underway
|
||||
* DE_NO_DEV no such device
|
||||
* DE_BAD_OP device does not support operation
|
||||
*
|
||||
* Reads globals: -
|
||||
* Modifies globals: -
|
||||
*
|
||||
* Other side effects: -
|
||||
*
|
||||
* Have a device perform a control operation. Extra parameters vary
|
||||
* according to the operation requested.
|
||||
*/
|
||||
|
||||
DevError angel_DeviceControl(DeviceID devID, DeviceControl op, void *arg);
|
||||
|
||||
|
||||
/*
|
||||
* Function: angel_ReceiveMode
|
||||
* Purpose: enable or disable reception across all devices
|
||||
*
|
||||
* Params:
|
||||
* Input: mode choose enable or disable
|
||||
*
|
||||
* Pass the mode parameter to the receive_mode control method of each device
|
||||
*/
|
||||
|
||||
void angel_ReceiveMode(DevRecvMode mode);
|
||||
|
||||
|
||||
/*
|
||||
* Function: angel_ResetDevices
|
||||
* Purpose: reset all devices
|
||||
*
|
||||
* Params: none
|
||||
*
|
||||
* Call the reset control method for each device
|
||||
*/
|
||||
|
||||
void angel_ResetDevices(void);
|
||||
|
||||
|
||||
/*
|
||||
* Function: angel_InitialiseDevices
|
||||
* Purpose: initialise the device driver layer
|
||||
*
|
||||
* Params: none
|
||||
*
|
||||
* Set up the device driver layer and call the init method for each device
|
||||
*/
|
||||
|
||||
void angel_InitialiseDevices(void);
|
||||
|
||||
|
||||
/*
|
||||
* Function: angel_IsAngelDevice
|
||||
* Purpose: Find out if a device supports Angel packets
|
||||
*
|
||||
* Params:
|
||||
* Input: devID index of the device to control to
|
||||
*
|
||||
* Returns: TRUE supports Angel packets
|
||||
* FALSE raw device
|
||||
*
|
||||
* Reads globals: -
|
||||
* Modifies globals: -
|
||||
*
|
||||
* Other side effects: -
|
||||
*/
|
||||
|
||||
bool angel_IsAngelDevice(DeviceID devID);
|
||||
|
||||
|
||||
#if !defined(MINIMAL_ANGEL) || MINIMAL_ANGEL == 0
|
||||
|
||||
/*
|
||||
* Function: angel_ApplDeviceHandler
|
||||
* Purpose: The entry point for User Application Device Driver requests
|
||||
* in a full functiionality version of Angel.
|
||||
* It will never be called directly by the User Application,
|
||||
* but gets called indirectly, via the SWI handler.
|
||||
*
|
||||
* Params:
|
||||
* Input: swi_r0 Argument to SWI indicating that
|
||||
* angel_ApplDeviceHandler was to be called. This
|
||||
* will not be used in this function, but is needed
|
||||
* by the SWI handler.
|
||||
* arg_blk pointer to block of arguments
|
||||
* arg_blk[0] is one of
|
||||
* angel_SWIreason_ApplDevice_{Read,Write,Yield}
|
||||
* which indicates which angel_Device* fn is to
|
||||
* be called. arg_blk[1] - arg_blk[n] are the
|
||||
* arguments to the corresponding
|
||||
* angel_ApplDevice* function.
|
||||
* Output: -
|
||||
* In/Out: -
|
||||
*
|
||||
* Returns: whatever the specified angel_Device* function
|
||||
* returns.
|
||||
*
|
||||
* Reads globals: -
|
||||
* Modifies globals: -
|
||||
*
|
||||
* Other side effects: -
|
||||
*
|
||||
* This has the side effects of angel_Device{Read,Write,Yield}
|
||||
* depending upon which is operation is specified as described above.
|
||||
*/
|
||||
|
||||
DevError angel_ApplDeviceHandler(
|
||||
unsigned swi_r0, unsigned *arg_blk
|
||||
);
|
||||
|
||||
#endif /* ndef MINIMAL_ANGEL */
|
||||
|
||||
#endif /* ndef angel_devclnt_h */
|
||||
|
||||
/* EOF devclnt.h */
|
|
@ -1,102 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*
|
||||
* Project: ANGEL
|
||||
*
|
||||
* Title: Devices header file
|
||||
*/
|
||||
|
||||
#ifndef angel_devices_h
|
||||
#define angel_devices_h
|
||||
|
||||
/*
|
||||
* Provides common types for using devices, and provides access to the
|
||||
* device table.
|
||||
*/
|
||||
|
||||
#include "angel.h"
|
||||
#include "buffers.h"
|
||||
|
||||
/* General purpose constants, macros, enums, typedefs */
|
||||
|
||||
/* a non-enum holder for device IDs */
|
||||
typedef unsigned int DeviceID;
|
||||
|
||||
/* device error codes */
|
||||
typedef enum DevError {
|
||||
DE_OKAY, /* no error */
|
||||
DE_NO_DEV, /* no such device */
|
||||
DE_BAD_DEV, /* device does not support angel */
|
||||
DE_BAD_CHAN, /* no such device channel */
|
||||
DE_BAD_OP, /* operation not supported by this device */
|
||||
DE_BUSY, /* device already busy */
|
||||
DE_INVAL, /* length invalid */
|
||||
DE_FAILED /* something else went wrong */
|
||||
} DevError;
|
||||
|
||||
/* return codes from asynchronous calls - primarily for channels' benefit */
|
||||
typedef enum DevStatus {
|
||||
DS_DONE, /* operation succeeded */
|
||||
DS_OVERFLOW, /* not enough buffer space */
|
||||
DS_BAD_PACKET, /* packet failed */
|
||||
DS_DEV_ERROR, /* device error */
|
||||
DS_INT_ERROR /* internal error */
|
||||
} DevStatus;
|
||||
|
||||
/* Callback for async. writes */
|
||||
typedef void (*DevWrite_CB_Fn)(
|
||||
void *buff, /* pointer to data -- cast to p_Buffer */
|
||||
void *length, /* how much done -- cast to unsigned */
|
||||
void *status, /* success code -- cast to DevStatus */
|
||||
void *cb_data /* as supplied */
|
||||
);
|
||||
|
||||
/* Callback for async. reads */
|
||||
typedef void (*DevRead_CB_Fn)(
|
||||
void *buff, /* pointer to data -- cast to p_Buffer */
|
||||
void *length, /* how much read -- cast to unsigned */
|
||||
void *status, /* success code -- cast to DevStatus */
|
||||
void *cb_data /* as supplied */
|
||||
);
|
||||
|
||||
/* control operations */
|
||||
typedef enum DeviceControl {
|
||||
DC_INIT, /* initialise device */
|
||||
DC_RESET, /* reset device */
|
||||
DC_RECEIVE_MODE, /* control reception */
|
||||
DC_SET_PARAMS, /* set parameters of device */
|
||||
#ifndef TARGET
|
||||
DC_GET_USER_PARAMS, /* params set by user at open */
|
||||
DC_GET_DEFAULT_PARAMS, /* device default parameters */
|
||||
DC_RESYNC, /* resynchronise with new agent */
|
||||
#endif
|
||||
DC_PRIVATE /* start of private device codes */
|
||||
} DeviceControl;
|
||||
|
||||
typedef enum DevRecvMode {
|
||||
DR_DISABLE,
|
||||
DR_ENABLE
|
||||
} DevRecvMode;
|
||||
|
||||
/*
|
||||
* callback to allow a device driver to request a buffer, to be filled
|
||||
* with an incoming packet
|
||||
*/
|
||||
typedef p_Buffer (*DevGetBuff_Fn)(unsigned req_size, void *cb_data);
|
||||
|
||||
|
||||
/* Publically-accessible globals */
|
||||
/* none */
|
||||
|
||||
#endif /* ndef angel_devices_h */
|
||||
|
||||
/* EOF devices.h */
|
|
@ -1,398 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "adp.h"
|
||||
#include "hsys.h"
|
||||
#include "rxtx.h"
|
||||
#include "drivers.h"
|
||||
#include "buffers.h"
|
||||
#include "devclnt.h"
|
||||
#include "adperr.h"
|
||||
#include "devsw.h"
|
||||
#include "hostchan.h"
|
||||
#include "logging.h"
|
||||
|
||||
/*
|
||||
* TODO: this should be adjustable - it could be done by defining
|
||||
* a reason code for DevSW_Ioctl. It could even be a
|
||||
* per-devicechannel parameter.
|
||||
*/
|
||||
static const unsigned int allocsize = ADP_BUFFER_MIN_SIZE;
|
||||
|
||||
#define illegalDevChanID(type) ((type) >= DC_NUM_CHANNELS)
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/*
|
||||
* Function: initialise_read
|
||||
* Purpose: Set up a read request for another packet
|
||||
*
|
||||
* Params:
|
||||
* In/Out: ds State structure to be initialised
|
||||
*
|
||||
* Returns:
|
||||
* OK: 0
|
||||
* Error: -1
|
||||
*/
|
||||
static int initialise_read(DevSWState *ds)
|
||||
{
|
||||
struct data_packet *dp;
|
||||
|
||||
/*
|
||||
* try to claim the structure that will
|
||||
* eventually hold the new packet.
|
||||
*/
|
||||
if ((ds->ds_nextreadpacket = DevSW_AllocatePacket(allocsize)) == NULL)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Calls into the device driver use the DriverCall structure: use
|
||||
* the buffer we have just allocated, and declare its size. We
|
||||
* are also obliged to clear the driver's context pointer.
|
||||
*/
|
||||
dp = &ds->ds_activeread.dc_packet;
|
||||
dp->buf_len = allocsize;
|
||||
dp->data = ds->ds_nextreadpacket->pk_buffer;
|
||||
|
||||
ds->ds_activeread.dc_context = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function: initialise_write
|
||||
* Purpose: Set up a write request for another packet
|
||||
*
|
||||
* Params:
|
||||
* Input: packet The packet to be written
|
||||
*
|
||||
* type The type of the packet
|
||||
*
|
||||
* In/Out: dc The structure to be intialised
|
||||
*
|
||||
* Returns: Nothing
|
||||
*/
|
||||
static void initialise_write(DriverCall *dc, Packet *packet, DevChanID type)
|
||||
{
|
||||
struct data_packet *dp = &dc->dc_packet;
|
||||
|
||||
dp->len = packet->pk_length;
|
||||
dp->data = packet->pk_buffer;
|
||||
dp->type = type;
|
||||
|
||||
/*
|
||||
* we are required to clear the state structure for the driver
|
||||
*/
|
||||
dc->dc_context = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function: enqueue_packet
|
||||
* Purpose: move a newly read packet onto the appropriate queue
|
||||
* of read packets
|
||||
*
|
||||
* Params:
|
||||
* In/Out: ds State structure with new packet
|
||||
*
|
||||
* Returns: Nothing
|
||||
*/
|
||||
static void enqueue_packet(DevSWState *ds)
|
||||
{
|
||||
struct data_packet *dp = &ds->ds_activeread.dc_packet;
|
||||
Packet *packet = ds->ds_nextreadpacket;
|
||||
|
||||
/*
|
||||
* transfer the length
|
||||
*/
|
||||
packet->pk_length = dp->len;
|
||||
|
||||
/*
|
||||
* take this packet out of the incoming slot
|
||||
*/
|
||||
ds->ds_nextreadpacket = NULL;
|
||||
|
||||
/*
|
||||
* try to put it on the correct input queue
|
||||
*/
|
||||
if (illegalDevChanID(dp->type))
|
||||
{
|
||||
/* this shouldn't happen */
|
||||
WARN("Illegal type for Rx packet");
|
||||
DevSW_FreePacket(packet);
|
||||
}
|
||||
else
|
||||
Adp_addToQueue(&ds->ds_readqueue[dp->type], packet);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function: flush_packet
|
||||
* Purpose: Send a packet to the device driver
|
||||
*
|
||||
* Params:
|
||||
* Input: device The device to be written to
|
||||
*
|
||||
* In/Out: dc Describes the packet to be sent
|
||||
*
|
||||
* Returns: Nothing
|
||||
*
|
||||
* Post-conditions: If the whole packet was accepted by the device
|
||||
* driver, then dc->dc_packet.data will be
|
||||
* set to NULL.
|
||||
*/
|
||||
static void flush_packet(const DeviceDescr *device, DriverCall *dc)
|
||||
{
|
||||
if (device->DeviceWrite(dc) > 0)
|
||||
/*
|
||||
* the whole packet was swallowed
|
||||
*/
|
||||
dc->dc_packet.data = NULL;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/*
|
||||
* These are the externally visible functions. They are documented in
|
||||
* devsw.h
|
||||
*/
|
||||
Packet *DevSW_AllocatePacket(const unsigned int length)
|
||||
{
|
||||
Packet *pk;
|
||||
|
||||
if ((pk = malloc(sizeof(*pk))) == NULL)
|
||||
{
|
||||
WARN("malloc failure");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((pk->pk_buffer = malloc(length+CHAN_HEADER_SIZE)) == NULL)
|
||||
{
|
||||
WARN("malloc failure");
|
||||
free(pk);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pk;
|
||||
}
|
||||
|
||||
void DevSW_FreePacket(Packet *pk)
|
||||
{
|
||||
free(pk->pk_buffer);
|
||||
free(pk);
|
||||
}
|
||||
|
||||
AdpErrs DevSW_Open(DeviceDescr *device, const char *name, const char *arg,
|
||||
const DevChanID type)
|
||||
{
|
||||
DevSWState *ds;
|
||||
|
||||
/*
|
||||
* is this the very first open call for this driver?
|
||||
*/
|
||||
if ((ds = (DevSWState *)(device->SwitcherState)) == NULL)
|
||||
{
|
||||
/*
|
||||
* yes, it is: initialise state
|
||||
*/
|
||||
if ((ds = malloc(sizeof(*ds))) == NULL)
|
||||
/* give up */
|
||||
return adp_malloc_failure;
|
||||
|
||||
(void)memset(ds, 0, sizeof(*ds));
|
||||
device->SwitcherState = (void *)ds;
|
||||
}
|
||||
|
||||
/*
|
||||
* check that we haven't already been opened for this type
|
||||
*/
|
||||
if ((ds->ds_opendevchans & (1 << type)) != 0)
|
||||
return adp_device_already_open;
|
||||
|
||||
/*
|
||||
* if no opens have been done for this device, then do it now
|
||||
*/
|
||||
if (ds->ds_opendevchans == 0)
|
||||
if (device->DeviceOpen(name, arg) < 0)
|
||||
return adp_device_open_failed;
|
||||
|
||||
/*
|
||||
* open has finished
|
||||
*/
|
||||
ds->ds_opendevchans |= (1 << type);
|
||||
return adp_ok;
|
||||
}
|
||||
|
||||
AdpErrs DevSW_Match(const DeviceDescr *device, const char *name,
|
||||
const char *arg)
|
||||
{
|
||||
return (device->DeviceMatch(name, arg) == -1) ? adp_failed : adp_ok;
|
||||
}
|
||||
|
||||
AdpErrs DevSW_Close(const DeviceDescr *device, const DevChanID type)
|
||||
{
|
||||
DevSWState *ds = (DevSWState *)(device->SwitcherState);
|
||||
Packet *pk;
|
||||
|
||||
if ((ds->ds_opendevchans & (1 << type)) == 0)
|
||||
return adp_device_not_open;
|
||||
|
||||
ds->ds_opendevchans &= ~(1 << type);
|
||||
|
||||
/*
|
||||
* if this is the last close for this channel, then inform the driver
|
||||
*/
|
||||
if (ds->ds_opendevchans == 0)
|
||||
device->DeviceClose();
|
||||
|
||||
/*
|
||||
* release all packets of the appropriate type
|
||||
*/
|
||||
for (pk = Adp_removeFromQueue(&(ds->ds_readqueue[type]));
|
||||
pk != NULL;
|
||||
pk = Adp_removeFromQueue(&(ds->ds_readqueue[type])))
|
||||
DevSW_FreePacket(pk);
|
||||
|
||||
/* that's all */
|
||||
return adp_ok;
|
||||
}
|
||||
|
||||
AdpErrs DevSW_Read(const DeviceDescr *device, const DevChanID type,
|
||||
Packet **packet, bool block)
|
||||
{
|
||||
int read_err;
|
||||
DevSWState *ds = device->SwitcherState;
|
||||
|
||||
/*
|
||||
* To try to get information out of the device driver as
|
||||
* quickly as possible, we try and read more packets, even
|
||||
* if a completed packet is already available.
|
||||
*/
|
||||
|
||||
/*
|
||||
* have we got a packet currently pending?
|
||||
*/
|
||||
if (ds->ds_nextreadpacket == NULL)
|
||||
/*
|
||||
* no - set things up
|
||||
*/
|
||||
if (initialise_read(ds) < 0) {
|
||||
/*
|
||||
* we failed to initialise the next packet, but can
|
||||
* still return a packet that has already arrived.
|
||||
*/
|
||||
*packet = Adp_removeFromQueue(&ds->ds_readqueue[type]);
|
||||
return adp_ok;
|
||||
}
|
||||
read_err = device->DeviceRead(&ds->ds_activeread, block);
|
||||
switch (read_err) {
|
||||
case 1:
|
||||
/*
|
||||
* driver has pulled in a complete packet, queue it up
|
||||
*/
|
||||
#ifdef RET_DEBUG
|
||||
printf("got a complete packet\n");
|
||||
#endif
|
||||
enqueue_packet(ds);
|
||||
*packet = Adp_removeFromQueue(&ds->ds_readqueue[type]);
|
||||
return adp_ok;
|
||||
case 0:
|
||||
/*
|
||||
* OK, return the head of the read queue for the given type
|
||||
*/
|
||||
/* enqueue_packet(ds); */
|
||||
*packet = Adp_removeFromQueue(&ds->ds_readqueue[type]);
|
||||
return adp_ok;
|
||||
case -1:
|
||||
#ifdef RET_DEBUG
|
||||
printf("got a bad packet\n");
|
||||
#endif
|
||||
/* bad packet */
|
||||
*packet = NULL;
|
||||
return adp_bad_packet;
|
||||
default:
|
||||
panic("DevSW_Read: bad read status %d", read_err);
|
||||
}
|
||||
return 0; /* get rid of a potential compiler warning */
|
||||
}
|
||||
|
||||
|
||||
AdpErrs DevSW_FlushPendingWrite(const DeviceDescr *device)
|
||||
{
|
||||
struct DriverCall *dc;
|
||||
struct data_packet *dp;
|
||||
|
||||
dc = &((DevSWState *)(device->SwitcherState))->ds_activewrite;
|
||||
dp = &dc->dc_packet;
|
||||
|
||||
/*
|
||||
* try to flush any packet that is still being written
|
||||
*/
|
||||
if (dp->data != NULL)
|
||||
{
|
||||
flush_packet(device, dc);
|
||||
|
||||
/* see if it has gone */
|
||||
if (dp->data != NULL)
|
||||
return adp_write_busy;
|
||||
else
|
||||
return adp_ok;
|
||||
}
|
||||
else
|
||||
return adp_ok;
|
||||
}
|
||||
|
||||
|
||||
AdpErrs DevSW_Write(const DeviceDescr *device, Packet *packet, DevChanID type)
|
||||
{
|
||||
struct DriverCall *dc;
|
||||
struct data_packet *dp;
|
||||
|
||||
dc = &((DevSWState *)(device->SwitcherState))->ds_activewrite;
|
||||
dp = &dc->dc_packet;
|
||||
|
||||
if (illegalDevChanID(type))
|
||||
return adp_illegal_args;
|
||||
|
||||
/*
|
||||
* try to flush any packet that is still being written
|
||||
*/
|
||||
if (DevSW_FlushPendingWrite(device) != adp_ok)
|
||||
return adp_write_busy;
|
||||
|
||||
/*
|
||||
* we can take this packet - set things up, then try to get rid of it
|
||||
*/
|
||||
initialise_write(dc, packet, type);
|
||||
flush_packet(device, dc);
|
||||
|
||||
return adp_ok;
|
||||
}
|
||||
|
||||
AdpErrs DevSW_Ioctl(const DeviceDescr *device, const int opcode, void *args)
|
||||
{
|
||||
return (device->DeviceIoctl(opcode, args) < 0) ? adp_failed : adp_ok;
|
||||
}
|
||||
|
||||
bool DevSW_WriteFinished(const DeviceDescr *device)
|
||||
{
|
||||
struct DriverCall *dc;
|
||||
struct data_packet *dp;
|
||||
|
||||
dc = &((DevSWState *)(device->SwitcherState))->ds_activewrite;
|
||||
dp = &dc->dc_packet;
|
||||
|
||||
return (dp == NULL || dp->data == NULL);
|
||||
}
|
||||
|
||||
/* EOF devsw.c */
|
|
@ -1,266 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*/
|
||||
#ifndef angsd_devsw_h
|
||||
#define angsd_devsw_h
|
||||
|
||||
#include "devclnt.h"
|
||||
#include "adperr.h"
|
||||
#include "drivers.h"
|
||||
|
||||
#ifndef __cplusplus
|
||||
typedef struct Packet Packet;
|
||||
typedef struct DevSWState DevSWState;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* the basic structure used for passing packets around
|
||||
*/
|
||||
struct Packet
|
||||
{
|
||||
struct Packet *pk_next; /* XXX first field in struct */
|
||||
unsigned int pk_length;
|
||||
unsigned char *pk_buffer;
|
||||
};
|
||||
|
||||
/*
|
||||
* control structure, used for maintaining device switcher state
|
||||
*/
|
||||
struct DevSWState
|
||||
{
|
||||
unsigned int ds_opendevchans; /* bitmap of open device channels */
|
||||
|
||||
/*
|
||||
* queue of packets read for the various device channels
|
||||
*/
|
||||
Packet *ds_readqueue[DC_NUM_CHANNELS];
|
||||
|
||||
/*
|
||||
* structures for managing active read and write operations
|
||||
*/
|
||||
Packet *ds_nextreadpacket;
|
||||
DriverCall ds_activeread;
|
||||
DriverCall ds_activewrite;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Function: DevSW_AllocatePacket
|
||||
* Purpose: Claim some memory to hold a struct Packet, and the buffer for
|
||||
* that packet.
|
||||
*
|
||||
* Params:
|
||||
* Input: length Size of the buffer in struct Packet.
|
||||
*
|
||||
* Returns:
|
||||
* OK: Pointer to the newly malloc()ed Packet.
|
||||
* Error: NULL
|
||||
*/
|
||||
Packet *DevSW_AllocatePacket(const unsigned int length);
|
||||
|
||||
/*
|
||||
* Function: DevSW_FreePacket
|
||||
* Purpose: Free the memory associated with a struct Packet.
|
||||
*
|
||||
* Pre-conditions The structure must have been originally claimed
|
||||
* via DevSW_AllocatePacket.
|
||||
*
|
||||
* Params:
|
||||
* Input: pk The packet to be freed.
|
||||
*
|
||||
* Returns: Nothing
|
||||
*/
|
||||
void DevSW_FreePacket(Packet *pk);
|
||||
|
||||
/*
|
||||
* Function: DevSW_Open
|
||||
* Purpose: Open the specified device driver
|
||||
*
|
||||
* Params:
|
||||
* Input: name Identifies which device to open. This can either be
|
||||
* a host specific identifier (e.g. "/dev/ttya",
|
||||
* "COM1:"), or a number which is used to refer to
|
||||
* `standard' interfaces, so "1" would be the first host
|
||||
* interface, "2" the second, and so on.
|
||||
*
|
||||
* arg Driver specific arguments. For example, some serial
|
||||
* drivers accept speed and control arguments such as
|
||||
* "9600" or "19200/NO_BREAK". These arguments are
|
||||
* completely free-form: it is the individual drivers
|
||||
* which do the necessary interpretation.
|
||||
*
|
||||
* type The type of packet the caller is interested in. Only
|
||||
* one open is allowed for each type of packet.
|
||||
*
|
||||
* In/Out: device The device driver to open
|
||||
*
|
||||
* Returns:
|
||||
* OK: adp_ok
|
||||
* Error: adp_device_open_failed
|
||||
* adp_device_already_open
|
||||
* adp_malloc_failure
|
||||
*/
|
||||
AdpErrs DevSW_Open(DeviceDescr *device, const char *name, const char *arg,
|
||||
const DevChanID type);
|
||||
|
||||
/*
|
||||
* Function: DevSW_Match
|
||||
* Purpose: Minimal veneer for DeviceMatch
|
||||
*
|
||||
* Params:
|
||||
* Input: device The device driver to match.
|
||||
*
|
||||
* name Identifies which device to open. This can either be
|
||||
* a host specific identifier (e.g. "/dev/ttya",
|
||||
* "COM1:"), or a number which is used to refer to
|
||||
* `standard' interfaces, so "1" would be the first host
|
||||
* interface, "2" the second, and so on.
|
||||
*
|
||||
* arg Driver specific arguments. For example, some serial
|
||||
* drivers accept speed and control arguments such as
|
||||
* "9600" or "19200/NO_BREAK". These arguments are
|
||||
* completely free-form: it is the individual drivers
|
||||
* which do the necessary interpretation.
|
||||
*
|
||||
* Returns:
|
||||
* OK: adp_ok
|
||||
* Error: adp_failed
|
||||
*/
|
||||
AdpErrs DevSW_Match(const DeviceDescr *device, const char *name,
|
||||
const char *arg);
|
||||
|
||||
/*
|
||||
* Function: DevSW_Close
|
||||
* Purpose: Close the specified device driver. All packets of the type
|
||||
* used by the caller held within the switching layer will
|
||||
* be discarded.
|
||||
*
|
||||
* Pre-conditions: Device must have been previously opened.
|
||||
*
|
||||
* Params:
|
||||
* Input: device The device driver to close
|
||||
*
|
||||
* type The type of packet the caller was interested in.
|
||||
*
|
||||
* Returns:
|
||||
* OK: adp_ok
|
||||
* Error: adp_device_not_open
|
||||
*/
|
||||
AdpErrs DevSW_Close(const DeviceDescr *device, const DevChanID type);
|
||||
|
||||
/*
|
||||
* Function: DevSW_Read
|
||||
* Purpose: Read a packet of appropriate type from the device driver
|
||||
*
|
||||
* Params:
|
||||
* Input: device The device driver to read packet from.
|
||||
*
|
||||
* type The type of packet the caller is interested in.
|
||||
*
|
||||
* Output: packet Pointer to new packet (if one is available)
|
||||
* NULL (if no complete packet is available)
|
||||
*
|
||||
* Input: block If TRUE, read may safely block for a short period
|
||||
* of time (say up to 20ms), to avoid high CPU load
|
||||
* whilst waiting for a reply.
|
||||
* If FALSE, read MUST NOT block.
|
||||
*
|
||||
* Returns:
|
||||
* OK: adp_ok
|
||||
* Error: adp_bad_packet
|
||||
*
|
||||
* Post-conditions: The calling function is responsible for freeing the
|
||||
* resources used by the packet when it is no longer
|
||||
* needed.
|
||||
*/
|
||||
AdpErrs DevSW_Read(const DeviceDescr *device, const DevChanID type,
|
||||
Packet **packet, bool block);
|
||||
|
||||
/*
|
||||
* Function: DevSW_Write
|
||||
* Purpose: Try to write a packet to the device driver. The write will
|
||||
* be bounced if another write is still in progress.
|
||||
*
|
||||
* Params:
|
||||
* Input: device The device driver to write a packet to.
|
||||
*
|
||||
* packet The packet to be written.
|
||||
*
|
||||
* type The type to be assigned to the packet.
|
||||
*
|
||||
* Returns:
|
||||
* OK: adp_ok
|
||||
* Error: adp_illegal_args
|
||||
* adp_write_busy
|
||||
*
|
||||
* Post-conditions: The calling function retains "ownership" of the packet,
|
||||
* i.e. it is responsible for freeing the resources used
|
||||
* by the packet when it is no longer needed.
|
||||
*/
|
||||
AdpErrs DevSW_Write(const DeviceDescr *device, Packet *packet, DevChanID type);
|
||||
|
||||
/*
|
||||
* Function: DevSW_FlushPendingWrite
|
||||
* Purpose: If a write is in progress, give it a chance to finish.
|
||||
*
|
||||
* Params:
|
||||
* Input: device The device driver to flush.
|
||||
*
|
||||
* Returns:
|
||||
* adp_ok no pending write, or write flushed completely
|
||||
* adp_write_busy pending write not flushed completely
|
||||
*/
|
||||
AdpErrs DevSW_FlushPendingWrite(const DeviceDescr *device);
|
||||
|
||||
/*
|
||||
* Function: DevSW_Ioctl
|
||||
* Purpose: Perform miscellaneous control operations. This is a minimal
|
||||
* veneer to DeviceIoctl.
|
||||
*
|
||||
* Params:
|
||||
* Input: device The device driver to control.
|
||||
*
|
||||
* opcode Reason code indicating the operation to perform.
|
||||
*
|
||||
* In/Out: args Pointer to opcode-sensitive arguments/result space.
|
||||
*
|
||||
* Returns:
|
||||
* OK: adp_ok
|
||||
* Error: adp_failed
|
||||
*/
|
||||
AdpErrs DevSW_Ioctl(const DeviceDescr *device, const int opcode, void *args);
|
||||
|
||||
/*
|
||||
* Function: DevSW_WriteFinished
|
||||
* Purpose: Return TRUE if the active device has finished writing
|
||||
* the last packet to be sent, or FALSE if a packet is still
|
||||
* being transmitted.
|
||||
*
|
||||
* Params:
|
||||
* Input: device The device driver to check.
|
||||
*
|
||||
* Returns:
|
||||
* TRUE: write finished or inactive
|
||||
* FALSE: write in progress
|
||||
*/
|
||||
bool DevSW_WriteFinished(const DeviceDescr *device);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ndef angsd_devsw_h */
|
||||
|
||||
/* EOF devsw.h */
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*
|
||||
* drivers.c - declares a NULL terminated list of device driver
|
||||
* descriptors supported by the host.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
#include "drivers.h"
|
||||
|
||||
extern DeviceDescr angel_SerialDevice;
|
||||
extern DeviceDescr angel_SerparDevice;
|
||||
extern DeviceDescr angel_EthernetDevice;
|
||||
|
||||
DeviceDescr *devices[] =
|
||||
{
|
||||
&angel_SerialDevice,
|
||||
&angel_SerparDevice,
|
||||
&angel_EthernetDevice,
|
||||
NULL
|
||||
};
|
||||
|
||||
/* EOF drivers.c */
|
|
@ -1,191 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*
|
||||
* Project: ANGEL
|
||||
*
|
||||
* Title: Definitions for device driver interface.
|
||||
*/
|
||||
#ifndef angsd_drivers_h
|
||||
#define angsd_drivers_h
|
||||
|
||||
#include "rxtx.h"
|
||||
|
||||
#ifndef __cplusplus
|
||||
typedef struct DeviceDescr DeviceDescr;
|
||||
typedef struct DriverCall DriverCall;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* used to pass packets across the driver interface
|
||||
*/
|
||||
struct DriverCall
|
||||
{
|
||||
struct data_packet dc_packet;
|
||||
void *dc_context;
|
||||
};
|
||||
|
||||
/*
|
||||
* used to describe a device driver
|
||||
*/
|
||||
struct DeviceDescr
|
||||
{
|
||||
char *DeviceName;
|
||||
int (*DeviceOpen)(const char *name, const char *arg);
|
||||
int (*DeviceMatch)(const char *name, const char *arg);
|
||||
void (*DeviceClose)(void);
|
||||
int (*DeviceRead)(DriverCall *dc, bool block);
|
||||
int (*DeviceWrite)(DriverCall *dc);
|
||||
int (*DeviceIoctl)(const int opcode, void *args);
|
||||
void *SwitcherState; /* used by switcher interface */
|
||||
};
|
||||
|
||||
/*
|
||||
* Function: DeviceOpen
|
||||
*
|
||||
* Purpose: Open a communications device
|
||||
*
|
||||
* Pre-conditions: No previous open is still active
|
||||
*
|
||||
* Params:
|
||||
* Input: name Identifies which device to open. This can either be
|
||||
* a host specific identifier (e.g. "/dev/ttya",
|
||||
* "COM1:"), or a number which is used to refer to
|
||||
* `standard' interfaces, so "1" would be the first host
|
||||
* interface, "2" the second, and so on.
|
||||
*
|
||||
* arg Driver specific arguments. For example, some serial
|
||||
* drivers accept speed and control arguments such as
|
||||
* "9600" or "19200/NO_BREAK". These arguments are
|
||||
* completely free-form: it is the individual drivers
|
||||
* which do the necessary interpretation.
|
||||
*
|
||||
* Returns:
|
||||
* OK: 0
|
||||
* Error: -1
|
||||
*/
|
||||
extern int DeviceOpen(const char *name, const char *arg);
|
||||
|
||||
/*
|
||||
* Function: DeviceMatch
|
||||
*
|
||||
* Purpose: Check whether parameters are OK to be passed to DeviceOpen
|
||||
*
|
||||
* Params:
|
||||
* Input: name Identifies which device to open. This can either be
|
||||
* a host specific identifier (e.g. "/dev/ttya",
|
||||
* "COM1:"), or a number which is used to refer to
|
||||
* `standard' interfaces, so "1" would be the first host
|
||||
* interface, "2" the second, and so on.
|
||||
*
|
||||
* arg Driver specific arguments. For example, some serial
|
||||
* drivers accept speed and control arguments such as
|
||||
* "9600" or "19200/NO_BREAK". These arguments are
|
||||
* completely free-form: it is the individual drivers
|
||||
* which do the necessary interpretation.
|
||||
*
|
||||
* Returns:
|
||||
* OK: 0
|
||||
* Error: -1
|
||||
*/
|
||||
extern int DeviceMatch(const char *name, const char *arg);
|
||||
|
||||
/*
|
||||
* Function: DeviceClose
|
||||
*
|
||||
* Purpose: Close a communications device
|
||||
*
|
||||
* Pre-conditions: Device must have been previously opened
|
||||
*
|
||||
* Params: None
|
||||
*
|
||||
* Returns: Nothing
|
||||
*/
|
||||
extern void DeviceClose(void);
|
||||
|
||||
/*
|
||||
* Function: DeviceRead
|
||||
*
|
||||
* Purpose: Try to read a complete packet from a communications device.
|
||||
* This read must usually be non-blocking, i.e. it should read as
|
||||
* many data from the device as needed to complete the packet,
|
||||
* but it should not wait if the packet is not complete, and no
|
||||
* more data are currently available from the device.
|
||||
* As an optimisation the read can optionally block when 'block'
|
||||
* is TRUE, but only for a short time. It is acceptable for the
|
||||
* 'block' parameter to be ignored in which case all reads
|
||||
* should be non-blocking.
|
||||
*
|
||||
* Pre-conditions: Device has been opened via DeviceOpen()
|
||||
*
|
||||
* Params:
|
||||
* In/Out: dc Describes the packet being read (dc->dc_packet);
|
||||
* dc->dc_context is for the driver to store private
|
||||
* context, and is guaranteed to be NULL the first
|
||||
* time DeviceRead is called for a given packet.
|
||||
*
|
||||
* In: block If TRUE, read may safely block for a short period
|
||||
* of time (say up to 20ms), to avoid high CPU load
|
||||
* whilst waiting for a reply.
|
||||
* If FALSE, read MUST NOT block.
|
||||
*
|
||||
* Returns:
|
||||
* OK: 1 (packet is complete)
|
||||
* 0 (packet is not yet complete)
|
||||
* Error: -1 bad packet
|
||||
*
|
||||
* Post-conditions: should a calamatous error occur panic() will be called
|
||||
*/
|
||||
extern int DeviceRead(DriverCall *dc, bool block);
|
||||
|
||||
/*
|
||||
* Function: DeviceWrite
|
||||
*
|
||||
* Purpose: Try to write a packet to a communications device. This write
|
||||
* must be non-blocking, i.e. it should write as many data to
|
||||
* the device as is immediately possible, but should not wait
|
||||
* for space to send any more after that.
|
||||
*
|
||||
* Pre-conditions: Device has been opened via DeviceOpen()
|
||||
*
|
||||
* Params:
|
||||
* In/Out: dc Describes the packet being written (dc->dc_packet);
|
||||
* dc->dc_context is for the driver to store private
|
||||
* context, and is guaranteed to be NULL the first
|
||||
* time DeviceWrite is called for a given packet.
|
||||
*
|
||||
* Returns:
|
||||
* OK: 1 (all of the packet has been written)
|
||||
* 0 (some of the packet remains to be written)
|
||||
* Error: -1
|
||||
*/
|
||||
extern int DeviceWrite(DriverCall *dc);
|
||||
|
||||
/*
|
||||
* Function: DeviceIoctl
|
||||
*
|
||||
* Purpose: Perform miscellaneous driver operations
|
||||
*
|
||||
* Pre-conditions: Device has been open via DeviceOpen()
|
||||
*
|
||||
* Params:
|
||||
* Input: opcode Reason code indicating the operation to perform
|
||||
* In/Out: args Pointer to opcode-sensitive arguments/result space
|
||||
*
|
||||
* Returns:
|
||||
* OK: 0
|
||||
* Error: -1
|
||||
*/
|
||||
extern int DeviceIoctl(const int opcode, void *args);
|
||||
|
||||
#endif /* !defined(angsd_drivers_h) */
|
||||
|
||||
/* EOF drivers.h */
|
|
@ -1,123 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*
|
||||
* endian.h - target endianness independent read/write primitives.
|
||||
*/
|
||||
|
||||
#ifndef angel_endian_h
|
||||
#define angel_endian_h
|
||||
|
||||
/*
|
||||
* The endianness of the data being processed needs to be known, but
|
||||
* the host endianness is not required (since the data is constructed
|
||||
* using bytes). At the moment these are provided as macros. This
|
||||
* gives the compiler freedom in optimising individual calls. However,
|
||||
* if space is at a premium then functions should be provided.
|
||||
*
|
||||
* NOTE: These macros assume that the data has been packed in the same format
|
||||
* as the packing on the build host. If this is not the case then
|
||||
* the wrong addresses could be used when dealing with structures.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* For all the following routines the target endianness is defined by the
|
||||
* following boolean definitions.
|
||||
*/
|
||||
#define BE (1 == 1) /* TRUE : big-endian */
|
||||
#define LE (1 == 0) /* FALSE : little-endian */
|
||||
|
||||
/*
|
||||
* The following type definitions are used by the endianness converting
|
||||
* macros.
|
||||
*/
|
||||
typedef unsigned char U8;
|
||||
typedef U8 *P_U8;
|
||||
typedef const U8 *CP_U8;
|
||||
|
||||
typedef unsigned short U16;
|
||||
typedef U16 *P_U16;
|
||||
|
||||
typedef unsigned int U32;
|
||||
typedef U32 *P_U32;
|
||||
|
||||
/*
|
||||
* If the endianness of the host and target are known (fixed) and the same
|
||||
* then the following macro definitions can be used. These just directly copy
|
||||
* the data.
|
||||
*
|
||||
* #define READ(e,a) (a)
|
||||
* #define WRITE(e,a,v) ((a) = (v))
|
||||
* #define PREAD(e,a) (a)
|
||||
* #define PWRITE(e,a,v) (*(a) = (v))
|
||||
*/
|
||||
|
||||
/*
|
||||
* These macros assume that a byte (char) is 8bits in size, and that the
|
||||
* endianness is not important when reading or writing bytes.
|
||||
*/
|
||||
#define PUT8(a,v) (*((P_U8)(a)) = (U8)(v))
|
||||
#define PUT16LE(a,v) (PUT8(a,((v) & 0xFF)), \
|
||||
PUT8((((P_U8)(a)) + sizeof(char)),((v) >> 8)))
|
||||
#define PUT16BE(a,v) (PUT8(a,((v) >> 8)), \
|
||||
PUT8((((P_U8)(a)) + sizeof(char)),((v) & 0xFF)))
|
||||
#define PUT32LE(a,v) (PUT16LE(a,v), \
|
||||
PUT16LE((((P_U8)(a)) + sizeof(short)),((v) >> 16)))
|
||||
#define PUT32BE(a,v) (PUT16BE(a,((v) >> 16)), \
|
||||
PUT16BE((((P_U8)(a)) + sizeof(short)),v))
|
||||
|
||||
#define GET8(a) (*((CP_U8)(a)))
|
||||
#define GET16LE(a) (GET8(a) | (((U16)GET8(((CP_U8)(a)) + sizeof(char))) << 8))
|
||||
#define GET16BE(a) ((((U16)GET8(a)) << 8) | GET8(((CP_U8)(a)) + sizeof(char)))
|
||||
#define GET32LE(a) (GET16LE(a) | \
|
||||
(((U32)GET16LE(((CP_U8)(a)) + sizeof(short))) << 16))
|
||||
#define GET32BE(a) ((((U32)GET16BE(a)) << 16) | \
|
||||
GET16BE(((CP_U8)(a)) + sizeof(short)))
|
||||
|
||||
/*
|
||||
* These macros simplify the code in respect to reading and writing the
|
||||
* correct size data when dealing with endianness. "e" is TRUE if we are
|
||||
* dealing with big-endian data, FALSE if we are dealing with little-endian.
|
||||
*/
|
||||
|
||||
/* void WRITE(int endianness, void *address, unsigned value); */
|
||||
|
||||
#define WRITE16(e,a,v) ((e) ? PUT16BE(&(a),v) : PUT16LE(&(a),v))
|
||||
#define WRITE32(e,a,v) ((e) ? PUT32BE(&(a),v) : PUT32LE(&(a),v))
|
||||
#define WRITE(e,a,v) ((sizeof(v) == sizeof(char)) ? \
|
||||
PUT8(&(a),v) : ((sizeof(v) == sizeof(short)) ? \
|
||||
WRITE16(e,a,v) : WRITE32(e,a,v)))
|
||||
|
||||
/* unsigned READ(int endianness, void *address) */
|
||||
#define READ16(e,a) ((e) ? GET16BE(&(a)) : GET16LE(&(a)))
|
||||
#define READ32(e,a) ((e) ? GET32BE(&(a)) : GET32LE(&(a)))
|
||||
#define READ(e,a) ((sizeof(a) == sizeof(char)) ? \
|
||||
GET8((CP_U8)&(a)) : ((sizeof(a) == sizeof(short)) ? \
|
||||
READ16(e,a) : READ32(e,a)))
|
||||
|
||||
/* void PWRITE(int endianness, void *address, unsigned value); */
|
||||
#define PWRITE16(e,a,v) ((e) ? PUT16BE(a,v) : PUT16LE(a,v))
|
||||
#define PWRITE32(e,a,v) ((e) ? PUT32BE(a,v) : PUT32LE(a,v))
|
||||
#define PWRITE(e,a,v) ((sizeof(v) == sizeof(char)) ? \
|
||||
PUT8(a,v) : ((sizeof(v) == sizeof(short)) ? \
|
||||
PWRITE16(e,a,v) : PWRITE32(e,a,v)))
|
||||
|
||||
/* unsigned PREAD(int endianness, void *address) */
|
||||
#define PREAD16(e,a) ((e) ? GET16BE(a) : GET16LE(a))
|
||||
#define PREAD32(e,a) ((e) ? GET32BE(a) : GET32LE(a))
|
||||
#define PREAD(e,a) ((sizeof(*(a)) == sizeof(char)) ? \
|
||||
GET8((CP_U8)a) : ((sizeof(*(a)) == sizeof(short)) ? \
|
||||
PREAD16(e,a) : PREAD32(e,a)))
|
||||
|
||||
#endif /* !defined(angel_endian_h) */
|
||||
|
||||
/* EOF endian.h */
|
|
@ -1,723 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*
|
||||
* etherdrv.c - Ethernet Driver for Angel.
|
||||
*/
|
||||
|
||||
#ifdef __hpux
|
||||
# define _POSIX_SOURCE 1
|
||||
# define _HPUX_SOURCE 1
|
||||
# define _XOPEN_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef __hpux
|
||||
# define uint hide_HPs_uint
|
||||
#endif
|
||||
#ifdef __unix
|
||||
# include <unistd.h>
|
||||
# ifdef __hpux
|
||||
# undef uint
|
||||
# endif
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef __hpux
|
||||
# define uint hide_HPs_uint
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#ifdef __hpux
|
||||
# undef uint
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
#include "host.h"
|
||||
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
typedef char * caddr_t;
|
||||
# undef IGNORE
|
||||
# include <winsock.h>
|
||||
# include "angeldll.h"
|
||||
#else
|
||||
# ifdef __hpux
|
||||
# define uint hide_HPs_uint
|
||||
# endif
|
||||
# include <sys/types.h>
|
||||
# include <sys/socket.h>
|
||||
# ifdef __hpux
|
||||
# undef uint
|
||||
# endif
|
||||
# include <netdb.h>
|
||||
# include <sys/time.h>
|
||||
# include <sys/ioctl.h>
|
||||
# if !defined(__hpux) && !defined(__linux__) && !defined(_WIN32)
|
||||
# include <sys/filio.h>
|
||||
# endif
|
||||
# include <netinet/in.h>
|
||||
# include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "hsys.h"
|
||||
#include "devices.h"
|
||||
#include "endian.h"
|
||||
#include "buffers.h"
|
||||
#include "hostchan.h"
|
||||
#include "params.h"
|
||||
#include "logging.h"
|
||||
#include "ethernet.h"
|
||||
|
||||
|
||||
#ifndef COMPILING_ON_WINDOWS
|
||||
/* these two might not work for windows */
|
||||
extern int sys_nerr;
|
||||
extern char *sys_errlist[];
|
||||
#endif
|
||||
|
||||
#ifndef UNUSED
|
||||
# define UNUSED(x) (x = x) /* Silence compiler warnings */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* forward declarations of static functions
|
||||
*/
|
||||
static int EthernetOpen(const char *name, const char *arg);
|
||||
static int EthernetMatch(const char *name, const char *arg);
|
||||
static void EthernetClose(void);
|
||||
static int EthernetRead(DriverCall *dc, bool block);
|
||||
static int EthernetWrite(DriverCall *dc);
|
||||
static int EthernetIoctl(const int opcode, void *args);
|
||||
|
||||
/*
|
||||
* the device descriptor for Ethernet
|
||||
*/
|
||||
DeviceDescr angel_EthernetDevice =
|
||||
{
|
||||
"Ethernet",
|
||||
EthernetOpen,
|
||||
EthernetMatch,
|
||||
EthernetClose,
|
||||
EthernetRead,
|
||||
EthernetWrite,
|
||||
EthernetIoctl
|
||||
};
|
||||
|
||||
/*
|
||||
* descriptor for the socket that we talk down
|
||||
*/
|
||||
static int sock = -1;
|
||||
|
||||
/*
|
||||
* address of the remote target
|
||||
*/
|
||||
static struct sockaddr_in remote, *ia = &remote;
|
||||
|
||||
/*
|
||||
* array of dynamic port numbers on target
|
||||
*/
|
||||
static unsigned short int ports[2];
|
||||
|
||||
/*
|
||||
* Function: set_address
|
||||
* Purpose: Try to get an address into an understandable form
|
||||
*
|
||||
* Params:
|
||||
* Input: addr The address to parse
|
||||
*
|
||||
* Output: ia Structure to hold the parsed address
|
||||
*
|
||||
* Returns:
|
||||
* OK: 0
|
||||
* Error: -1
|
||||
*/
|
||||
static int set_address(const char *const addr, struct sockaddr_in *const ia)
|
||||
{
|
||||
ia->sin_family = AF_INET;
|
||||
|
||||
/*
|
||||
* Try address as a dotted decimal
|
||||
*/
|
||||
ia->sin_addr.s_addr = inet_addr(addr);
|
||||
|
||||
/*
|
||||
* If that failed, try it as a hostname
|
||||
*/
|
||||
if (ia->sin_addr.s_addr == (u_int)-1)
|
||||
{
|
||||
struct hostent *hp = gethostbyname(addr);
|
||||
|
||||
if (hp == NULL)
|
||||
return -1;
|
||||
|
||||
(void)memcpy((caddr_t)&ia->sin_addr, hp->h_addr, hp->h_length);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function: open_socket
|
||||
* Purpose: Open a non-blocking UDP socket, and bind it to a port
|
||||
* assigned by the system.
|
||||
*
|
||||
* Params: None
|
||||
*
|
||||
* Returns:
|
||||
* OK: socket descriptor
|
||||
* Error: -1
|
||||
*/
|
||||
static int open_socket(void)
|
||||
{
|
||||
int sfd;
|
||||
#if 0 /* see #if 0 just below -VVV- */
|
||||
int yesplease = 1;
|
||||
#endif
|
||||
struct sockaddr_in local;
|
||||
|
||||
/*
|
||||
* open the socket
|
||||
*/
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
|
||||
return -1;
|
||||
#else
|
||||
if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
||||
{
|
||||
# ifdef DEBUG
|
||||
perror("socket");
|
||||
# endif
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 960731 KWelton
|
||||
*
|
||||
* I don't believe that this should be necessary - if we
|
||||
* use select(), then non-blocking I/O is redundant.
|
||||
* Unfortunately, select() appears to be broken (under
|
||||
* Solaris, with a limited amount of time available for
|
||||
* debug), so this code stays in for the time being
|
||||
*/
|
||||
#if 0
|
||||
/*
|
||||
* enable non-blocking I/O
|
||||
*/
|
||||
if (ioctlsocket(sfd, FIONBIO, &yesplease) < 0)
|
||||
{
|
||||
# ifdef DEBUG
|
||||
perror("ioctl(FIONBIO)");
|
||||
# endif
|
||||
closesocket(sfd);
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif /* 0/1 */
|
||||
|
||||
/*
|
||||
* bind local address to a system-assigned port
|
||||
*/
|
||||
memset((char *)&local, 0, sizeof(local));
|
||||
local.sin_family = AF_INET;
|
||||
local.sin_port = htons(0);
|
||||
local.sin_addr.s_addr = INADDR_ANY;
|
||||
if (bind(sfd, (struct sockaddr *)&local, sizeof(local)) < 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
perror("bind");
|
||||
#endif
|
||||
closesocket(sfd);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* all done
|
||||
*/
|
||||
return sfd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function: fetch_ports
|
||||
* Purpose: Request assigned port numbers from remote target
|
||||
*
|
||||
* Params: None
|
||||
*
|
||||
* Returns: Nothing
|
||||
*
|
||||
* Post-conditions: This routine will *always* return something for the
|
||||
* port numbers. If the remote target does not
|
||||
* respond, then it makes something up - this allows
|
||||
* the standard error message (from ardi.c) to be
|
||||
* generated when the target is dead for whatever
|
||||
* reason.
|
||||
*/
|
||||
static void fetch_ports(void)
|
||||
{
|
||||
int i;
|
||||
const char ctrlpacket[] = CTRL_MAGIC;
|
||||
CtrlResponse response;
|
||||
|
||||
/*
|
||||
* we will try 3 times to elicit a response from the target
|
||||
*/
|
||||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
struct timeval tv;
|
||||
fd_set fdset;
|
||||
|
||||
/*
|
||||
* send the magic string to the control
|
||||
* port on the remote target
|
||||
*/
|
||||
ia->sin_port = htons(CTRL_PORT);
|
||||
if (sendto(sock, ctrlpacket, sizeof(ctrlpacket), 0,
|
||||
(struct sockaddr *)ia, sizeof(*ia)) < 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
perror("fetch_ports: sendto");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(sock, &fdset);
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 250000;
|
||||
|
||||
if (select(sock + 1, &fdset, NULL, NULL, &tv) < 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
perror("fetch_ports: select");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (FD_ISSET(sock, &fdset))
|
||||
{
|
||||
/*
|
||||
* there is something there - read it
|
||||
*/
|
||||
if (recv(sock, (char *)&response, sizeof(response), 0) < 0)
|
||||
{
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
unsigned int werrno = WSAGetLastError();
|
||||
|
||||
if (werrno == WSAEWOULDBLOCK || werrno == 0)
|
||||
#else
|
||||
if (errno == EWOULDBLOCK)
|
||||
#endif
|
||||
{
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
perror("fetch_ports: recv");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
/*
|
||||
* XXX
|
||||
*
|
||||
* this is *very* unpleasant - try to match the structure
|
||||
* layout
|
||||
*/
|
||||
unsigned short *sptr = (unsigned short *)(response + RESP_DBUG);
|
||||
|
||||
if (strcmp(response, ctrlpacket) == 0)
|
||||
{
|
||||
ports[DBUG_INDEX] = htons(*sptr);
|
||||
sptr++;
|
||||
ports[APPL_INDEX] = htons(*sptr);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("fetch_ports: got response, DBUG=%d, APPL=%d\n",
|
||||
ports[DBUG_INDEX], ports[APPL_INDEX]);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* we failed to get a response
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
printf("fetch_ports: failed to get a real answer\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Function: read_packet
|
||||
* Purpose: read a packet, and pass it back to higher levels
|
||||
*
|
||||
* Params:
|
||||
* In/Out: packet Holder for the read packet
|
||||
*
|
||||
* Returns: 1 - Packet is complete
|
||||
* 0 - No complete packet read
|
||||
*
|
||||
* Post-conditions: Will call panic() if something goes wrong with the OS
|
||||
*/
|
||||
static int read_packet(struct data_packet *const packet)
|
||||
{
|
||||
struct sockaddr_in from;
|
||||
int nbytes, fromlen = sizeof(from);
|
||||
DevChanID devchan;
|
||||
|
||||
/*
|
||||
* try to get the packet
|
||||
*/
|
||||
if ((nbytes = recvfrom(sock, (char *)(packet->data), packet->buf_len, 0,
|
||||
(struct sockaddr *)&from, &fromlen)) < 0)
|
||||
{
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
if (nbytes == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
|
||||
MessageBox(GetFocus(), "Error receiving packet\n", "Angel", MB_OK | MB_ICONSTOP);
|
||||
#else
|
||||
if (errno != EWOULDBLOCK)
|
||||
{
|
||||
# ifdef DEBUG
|
||||
perror("recv");
|
||||
# endif
|
||||
panic("ethernet recv failure");
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
if (pfnProgressCallback != NULL && nbytes != SOCKET_ERROR)
|
||||
{
|
||||
progressInfo.nRead += nbytes;
|
||||
(*pfnProgressCallback)(&progressInfo);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* work out where the packet was from
|
||||
*/
|
||||
if (from.sin_addr.s_addr != remote.sin_addr.s_addr)
|
||||
{
|
||||
/*
|
||||
* not from our target - ignore it
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
printf("read_packet: ignoring packet from %s\n",
|
||||
inet_ntoa(from.sin_addr));
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
else if (ntohs(from.sin_port) == ports[DBUG_INDEX])
|
||||
devchan = DC_DBUG;
|
||||
else if (ntohs(from.sin_port) == ports[APPL_INDEX])
|
||||
devchan = DC_APPL;
|
||||
else
|
||||
{
|
||||
/*
|
||||
* unknown port number - ignore it
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
printf("read_packet: ignore packet from port %hd\n",
|
||||
htons(from.sin_port));
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(DEBUG) && !defined(DO_TRACE)
|
||||
printf("EthernetRead: %d bytes from %s channel\n",
|
||||
nbytes, (devchan == DC_DBUG) ? "DBUG" : "APPL");
|
||||
#endif
|
||||
|
||||
#ifdef DO_TRACE
|
||||
printf("[%d on %d]\n", nbytes, devchan);
|
||||
{
|
||||
int i = 0;
|
||||
unsigned char *cptr = packet->data;
|
||||
|
||||
while (i < nbytes)
|
||||
{
|
||||
printf("<%02X ", *(cptr++));
|
||||
|
||||
if (!(++i % 16))
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (i % 16)
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* OK - fill in the details
|
||||
*/
|
||||
packet->type = devchan;
|
||||
packet->len = nbytes;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/*
|
||||
* Function: Ethernet_Open
|
||||
* Purpose: Open the Ethernet device. See the documentation for
|
||||
* DeviceOpen in drivers.h
|
||||
*
|
||||
* Post-conditions: Will have updated struct sockaddr_in remote (*ia)
|
||||
* with the address of the remote target.
|
||||
*/
|
||||
static int EthernetOpen(const char *name, const char *arg)
|
||||
{
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
WORD wVersionRequested;
|
||||
WSADATA wsaData;
|
||||
#endif
|
||||
/*
|
||||
* name is passed as e=<blah>, so skip 1st two characters
|
||||
*/
|
||||
const char *etheraddr = name + 2;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("EthernetOpen: name `%s'\n", name);
|
||||
#endif
|
||||
|
||||
/* Check that the name is a valid one */
|
||||
if (EthernetMatch(name, arg) != 0)
|
||||
return -1;
|
||||
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
wVersionRequested = MAKEWORD(1, 1);
|
||||
if (WSAStartup(wVersionRequested, &wsaData) != 0)
|
||||
/*
|
||||
* Couldn't find a useable winsock.dll.
|
||||
*/
|
||||
return -1;
|
||||
|
||||
if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 )
|
||||
{
|
||||
WSACleanup();
|
||||
|
||||
/*
|
||||
* Couldn't find a winsock.dll with supported version.
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
memset((char *)ia, 0, sizeof(*ia));
|
||||
if (set_address(etheraddr, ia) < 0)
|
||||
{
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
/*
|
||||
* SJ - I'm not sure that this is the correct way to handle this
|
||||
* as Fail calls remote_disable and exits, while panic just exits.
|
||||
* However at the time of writing remote_disable does nothing!
|
||||
*/
|
||||
/* Panic("EthernetOpen: bad name `%s'\n", etheraddr); */
|
||||
#else
|
||||
Fail("EthernetOpen: bad name `%s'\n", etheraddr);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((sock = open_socket()) < 0)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* fetch the port numbers assigned by the remote target
|
||||
* to its Debug and Application sockets
|
||||
*/
|
||||
fetch_ports();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int EthernetMatch(const char *name, const char *arg)
|
||||
{
|
||||
/* IGNORE arg */
|
||||
if (0)
|
||||
arg = arg;
|
||||
|
||||
if (name == NULL)
|
||||
return -1;
|
||||
|
||||
if (tolower(name[0]) != 'e' || name[1] != '=')
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void EthernetClose(void)
|
||||
{
|
||||
if (sock >= 0)
|
||||
{
|
||||
closesocket(sock);
|
||||
sock = -1;
|
||||
}
|
||||
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
WSACleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
static int EthernetRead(DriverCall *dc, bool block)
|
||||
{
|
||||
fd_set fdset;
|
||||
struct timeval tv;
|
||||
int err;
|
||||
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(sock, &fdset);
|
||||
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
UNUSED(block);
|
||||
tv.tv_sec = tv.tv_usec = 0;
|
||||
#else
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = (block ? 10000 : 0);
|
||||
#endif
|
||||
|
||||
err = select(sock + 1, &fdset, NULL, NULL, &tv);
|
||||
|
||||
if (err < 0) {
|
||||
if (errno == EINTR) {
|
||||
return 0;
|
||||
}
|
||||
panic("ethernet select failure (errno=%i)",errno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (FD_ISSET(sock, &fdset))
|
||||
return read_packet(&dc->dc_packet);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int EthernetWrite(DriverCall *dc)
|
||||
{
|
||||
int nbytes;
|
||||
struct data_packet *packet = &dc->dc_packet;
|
||||
|
||||
if (packet->type == DC_DBUG)
|
||||
ia->sin_port = htons(ports[DBUG_INDEX]);
|
||||
else if (packet->type == DC_APPL)
|
||||
ia->sin_port = htons(ports[APPL_INDEX]);
|
||||
else
|
||||
{
|
||||
panic("EthernetWrite: unknown devchan");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(DEBUG) && !defined(DO_TRACE)
|
||||
printf("EthernetWrite: %d bytes to %s channel\n",
|
||||
packet->len, (packet->type == DC_DBUG) ? "DBUG" : "APPL");
|
||||
#endif
|
||||
|
||||
#ifdef DO_TRACE
|
||||
printf("[%d on %d]\n", packet->len, packet->type);
|
||||
{
|
||||
int i = 0;
|
||||
unsigned char *cptr = packet->data;
|
||||
|
||||
while (i < packet->len)
|
||||
{
|
||||
printf(">%02X ", *(cptr++));
|
||||
|
||||
if (!(++i % 16))
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (i % 16)
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((nbytes = sendto(sock, (char *)(packet->data), packet->len, 0,
|
||||
(struct sockaddr *)ia, sizeof(*ia))) != packet->len)
|
||||
{
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
if (nbytes == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
|
||||
#else
|
||||
if (nbytes < 0 && errno != EWOULDBLOCK)
|
||||
#endif
|
||||
{
|
||||
#ifdef DEBUG
|
||||
perror("sendto");
|
||||
#endif
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
panic("ethernet send failure\n");
|
||||
#else
|
||||
/* might not work for Windows */
|
||||
panic("ethernet send failure [%s]\n",
|
||||
errno < sys_nerr ? sys_errlist[errno] : "unknown errno");
|
||||
#endif
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else if (nbytes >= 0)
|
||||
fprintf(stderr, "ethernet send: asked for %d, sent %d\n", packet->len, nbytes);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
if (pfnProgressCallback != NULL && nbytes != SOCKET_ERROR)
|
||||
{
|
||||
progressInfo.nWritten += nbytes;
|
||||
(*pfnProgressCallback)(&progressInfo);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int EthernetIoctl(const int opcode, void *args)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf( "EthernetIoctl: op %d arg %x\n", opcode, args );
|
||||
#endif
|
||||
|
||||
/*
|
||||
* IGNORE(opcode)
|
||||
*/
|
||||
if (0)
|
||||
{
|
||||
int dummy = opcode;
|
||||
UNUSED(dummy);
|
||||
}
|
||||
UNUSED(args);
|
||||
|
||||
switch ( opcode )
|
||||
{
|
||||
case DC_RESYNC:
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf( "EthernetIoctl: resync\n" );
|
||||
#endif
|
||||
fetch_ports();
|
||||
return 0;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* EOF etherdrv.c */
|
|
@ -1,97 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*
|
||||
* ethernet.h: Angel drivers for Ethernet using Fusion UDP/IP stack
|
||||
*/
|
||||
#ifndef angel_ethernet_h
|
||||
#define angel_ethernet_h
|
||||
|
||||
/*
|
||||
* the UDP ports that Angel Ethernet uses
|
||||
*/
|
||||
#define CTRL_PORT 1913
|
||||
|
||||
/*
|
||||
* the size of the largest packet accepted on the control socket
|
||||
*/
|
||||
#define CTRL_MAXPACKET 6
|
||||
|
||||
/*
|
||||
* This is the "magic number" sent to the control port to
|
||||
* request that the channel port numbers are returned
|
||||
*/
|
||||
#define CTRL_MAGIC "Angel"
|
||||
|
||||
/*
|
||||
* Array used for responding to a request on the control port
|
||||
*/
|
||||
typedef unsigned char CtrlResponse[10];
|
||||
#define RESP_MAGIC 0
|
||||
#define RESP_DBUG 6
|
||||
#define RESP_APPL 8
|
||||
|
||||
/*
|
||||
* indices for accessing the array of port numbers sent
|
||||
* over the control socket
|
||||
*/
|
||||
#define DBUG_INDEX 0
|
||||
#define APPL_INDEX 1
|
||||
|
||||
#ifdef TARGET
|
||||
|
||||
# include "devdriv.h"
|
||||
|
||||
extern const struct angel_DeviceEntry angel_EthernetDevice;
|
||||
|
||||
/*
|
||||
* Function: angel_EthernetPoll
|
||||
* Purpose: Poll Fusion for newly arrived packets
|
||||
*
|
||||
* Pre-conditions: Called in SVC mode with the lock
|
||||
*
|
||||
* Params:
|
||||
* Input: data IGNORE'd
|
||||
*
|
||||
* Returns: Nothing
|
||||
*
|
||||
* Post-conditions: Will have passed any packets received along to
|
||||
* higher levels
|
||||
*/
|
||||
void angel_EthernetPoll(unsigned int data);
|
||||
|
||||
void angel_EthernetNOP(unsigned int data);
|
||||
|
||||
|
||||
/*
|
||||
* Function: angel_FindEthernetConfigBlock
|
||||
* Purpose: Search the Flash for an ethernet config block and return
|
||||
* it if found.
|
||||
*
|
||||
* Params: None
|
||||
*
|
||||
* Returns: NULL if no config block found, the address if one is found.
|
||||
*
|
||||
*/
|
||||
extern angel_EthernetConfigBlock *angel_FindEthernetConfigBlock(void);
|
||||
|
||||
#else /* def TARGET */
|
||||
|
||||
# ifndef COMPILING_ON_WINDOWS
|
||||
# define ioctlsocket(x, y, z) ioctl((x), (y), (z))
|
||||
# define closesocket(x) close(x)
|
||||
# endif
|
||||
|
||||
#endif /* def TARGET */
|
||||
|
||||
#endif /* ndef angel_ethernet_h */
|
||||
|
||||
/* EOF ethernet.h */
|
|
@ -1,222 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _host_LOADED
|
||||
#define _host_LOADED 1
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef SEEK_SET
|
||||
# define SEEK_SET 0
|
||||
#endif
|
||||
#ifndef SEEK_CUR
|
||||
# define SEEK_CUR 1
|
||||
#endif
|
||||
#ifndef SEEK_END
|
||||
# define SEEK_END 2
|
||||
#endif
|
||||
|
||||
/* The following for the benefit of compiling on SunOS */
|
||||
#ifndef offsetof
|
||||
# define offsetof(T, member) ((char *)&(((T *)0)->member) - (char *)0)
|
||||
#endif
|
||||
|
||||
#ifdef unix /* A temporary sop to older compilers */
|
||||
# ifndef __unix /* (good for long-term portability?) */
|
||||
# define __unix 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __unix
|
||||
/* Generic unix -- hopefully a split into other variants will not be */
|
||||
/* needed. However, beware the 'bsd' test above and safe_toupper etc. */
|
||||
/* which cope with backwards (pre-posix/X/open) unix compatility. */
|
||||
# define COMPILING_ON_UNIX 1
|
||||
#endif
|
||||
#if defined(_WIN32)
|
||||
# define COMPILING_ON_WIN32 1
|
||||
# if !defined(__CYGWIN32__)
|
||||
# define COMPILING_ON_WINDOWS 1
|
||||
# endif
|
||||
#endif
|
||||
#if defined(_CONSOLE)
|
||||
# define COMPILING_ON_WINDOWS_CONSOLE 1
|
||||
# define COMPILING_ON_WINDOWS 1
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
# define COMPILING_ON_MSDOS 1
|
||||
# define COMPILING_ON_WINDOWS 1
|
||||
# if defined(__cplusplus)
|
||||
# define IMPLEMENT_BOOL_AS_INT 1 /* VC++ doesn't have 'bool' (yet) */
|
||||
# endif
|
||||
#endif
|
||||
/* The '(defined(__sparc) && defined(P_tmpdir) */
|
||||
/* && !defined(__svr4__))' is to detect gcc on SunOS. */
|
||||
/* C++ compilers don't have to define __STDC__ */
|
||||
#if (defined(__sparc) && defined(P_tmpdir))
|
||||
# if defined(__svr4__)
|
||||
# define COMPILING_ON_SOLARIS
|
||||
# else
|
||||
# define COMPILING_ON_SUNOS
|
||||
# endif
|
||||
#endif
|
||||
#ifdef __hppa
|
||||
# define COMPILING_ON_HPUX
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The following typedefs may need alteration for obscure host machines.
|
||||
*/
|
||||
#if defined(__alpha) && defined(__osf__) /* =========================== */
|
||||
/* Under OSF the alpha has 64-bit pointers and 64-bit longs. */
|
||||
typedef int int32;
|
||||
typedef unsigned int unsigned32;
|
||||
/* IPtr and UPtr are 'ints of same size as pointer'. Do not use in */
|
||||
/* new code. Currently only used within 'ncc'. */
|
||||
typedef long int IPtr;
|
||||
typedef unsigned long int UPtr;
|
||||
|
||||
#else /* all hosts except alpha under OSF ============================= */
|
||||
|
||||
typedef long int int32;
|
||||
typedef unsigned long int unsigned32;
|
||||
/* IPtr and UPtr are 'ints of same size as pointer'. Do not use in */
|
||||
/* new code. Currently only used within 'ncc'. */
|
||||
#define IPtr int32
|
||||
#define UPtr unsigned32
|
||||
#endif /* ============================================================= */
|
||||
|
||||
typedef short int int16;
|
||||
typedef unsigned short int unsigned16;
|
||||
typedef signed char int8;
|
||||
typedef unsigned char unsigned8;
|
||||
|
||||
/* The following code defines the 'bool' type to be 'int' under C */
|
||||
/* and real 'bool' under C++. It also avoids warnings such as */
|
||||
/* C++ keyword 'bool' used as identifier. It can be overridden by */
|
||||
/* defining IMPLEMENT_BOOL_AS_ENUM or IMPLEMENT_BOOL_AS_INT. */
|
||||
#undef _bool
|
||||
|
||||
#ifdef IMPLEMENT_BOOL_AS_ENUM
|
||||
enum _bool { _false, _true };
|
||||
# define _bool enum _bool
|
||||
#elif defined(IMPLEMENT_BOOL_AS_INT) || !defined(__cplusplus)
|
||||
# define _bool int
|
||||
# define _false 0
|
||||
# define _true 1
|
||||
#endif
|
||||
|
||||
#ifdef _bool
|
||||
# if defined(_MFC_VER) || defined(__CC_NORCROFT) /* When using MS Visual C/C++ v4.2 */
|
||||
# define bool _bool /* avoids "'bool' is reserved word" warning */
|
||||
# else
|
||||
typedef _bool bool;
|
||||
# endif
|
||||
# define true _true
|
||||
# define false _false
|
||||
#endif
|
||||
|
||||
#define YES true
|
||||
#define NO false
|
||||
#undef TRUE /* some OSF headers define as 1 */
|
||||
#define TRUE true
|
||||
#undef FALSE /* some OSF headers define as 1 */
|
||||
#define FALSE false
|
||||
|
||||
/* 'uint' conflicts with some Unixen sys/types.h, so we now don't define it */
|
||||
typedef unsigned8 uint8;
|
||||
typedef unsigned16 uint16;
|
||||
typedef unsigned32 uint32;
|
||||
|
||||
typedef unsigned Uint;
|
||||
typedef unsigned8 Uint8;
|
||||
typedef unsigned16 Uint16;
|
||||
typedef unsigned32 Uint32;
|
||||
|
||||
#ifdef ALPHA_TASO_SHORT_ON_OSF /* was __alpha && __osf. */
|
||||
/* The following sets ArgvType for 64-bit pointers so that */
|
||||
/* DEC Unix (OSF) cc can be used with the -xtaso_short compiler option */
|
||||
/* to force pointers to be 32-bit. Not currently used since most/all */
|
||||
/* ARM tools accept 32 or 64 bit pointers transparently. See IPtr. */
|
||||
#pragma pointer_size (save)
|
||||
#pragma pointer_size (long)
|
||||
typedef char *ArgvType;
|
||||
#pragma pointer_size (restore)
|
||||
#else
|
||||
typedef char *ArgvType;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Rotate macros
|
||||
*/
|
||||
#define ROL_32(val, n) \
|
||||
((((unsigned32)(val) << (n)) | ((unsigned32)(val) >> (32-(n)))) & 0xFFFFFFFFL)
|
||||
#define ROR_32(val, n) \
|
||||
((((unsigned32)(val) >> (n)) | ((unsigned32)(val) << (32-(n)))) & 0xFFFFFFFFL)
|
||||
|
||||
#ifdef COMPILING_ON_UNIX
|
||||
# define FOPEN_WB "w"
|
||||
# define FOPEN_RB "r"
|
||||
# define FOPEN_RWB "r+"
|
||||
# ifndef __STDC__ /* caveat RISCiX... */
|
||||
# define remove(file) unlink(file) /* a horrid hack, but probably best? */
|
||||
# endif
|
||||
#else
|
||||
# define FOPEN_WB "wb"
|
||||
# define FOPEN_RB "rb"
|
||||
# define FOPEN_RWB "rb+"
|
||||
#endif
|
||||
|
||||
#ifndef FILENAME_MAX
|
||||
# define FILENAME_MAX 256
|
||||
#endif
|
||||
|
||||
#if (!defined(__STDC__) && !defined(__cplusplus) && !defined(_MSC_VER)) || \
|
||||
defined(COMPILING_ON_SUNOS)
|
||||
/* Use bcopy rather than memmove, as memmove is not available. */
|
||||
/* There does not seem to be a header for bcopy. */
|
||||
void bcopy(const char *src, char *dst, int length);
|
||||
# define memmove(d,s,l) bcopy(s,d,l)
|
||||
|
||||
/* BSD/SUN don't have strtoul(), but then strtol() doesn't barf on */
|
||||
/* overflow as required by ANSI... This bodge is horrid. */
|
||||
# define strtoul(s, ptr, base) strtol(s, ptr, base)
|
||||
|
||||
/* strtod is present in the C-library but is not in stdlib.h */
|
||||
extern double strtod(const char *str, char **ptr);
|
||||
#endif
|
||||
|
||||
/* For systems that do not define EXIT_SUCCESS and EXIT_FAILURE */
|
||||
#ifndef EXIT_SUCCESS
|
||||
# define EXIT_SUCCESS 0
|
||||
#endif
|
||||
#ifndef EXIT_FAILURE
|
||||
# define EXIT_FAILURE 1
|
||||
#endif
|
||||
|
||||
#ifndef IGNORE
|
||||
#define IGNORE(x) (x = x) /* Silence compiler warnings for unused arguments */
|
||||
#endif
|
||||
|
||||
/* Define endian-ness of host */
|
||||
|
||||
#if defined(__acorn) || defined(__mvs) || defined(_WIN32) || \
|
||||
(defined(__alpha) && defined(__osf__))
|
||||
# define HOST_ENDIAN_LITTLE
|
||||
#elif defined(__sparc) || defined(macintosh)
|
||||
# define HOST_ENDIAN_BIG
|
||||
#else
|
||||
# define HOST_ENDIAN_UNKNOWN
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* end of host.h */
|
File diff suppressed because it is too large
Load Diff
|
@ -1,298 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*/
|
||||
#ifndef angsd_hostchan_h
|
||||
#define angsd_hostchan_h
|
||||
|
||||
/* struct timeval */
|
||||
#if defined(__unix) || defined(__CYGWIN32__)
|
||||
# include <sys/time.h>
|
||||
#else
|
||||
# include "winsock.h"
|
||||
# include "time.h"
|
||||
#endif
|
||||
|
||||
#include "chandefs.h"
|
||||
#include "adperr.h"
|
||||
#include "devsw.h"
|
||||
|
||||
/*
|
||||
* asynchronous processing modes
|
||||
*/
|
||||
enum AsyncMode
|
||||
{
|
||||
async_block_on_nothing,
|
||||
async_block_on_read,
|
||||
async_block_on_write
|
||||
};
|
||||
|
||||
#ifndef __cplusplus
|
||||
typedef enum AsyncMode AsyncMode;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* prototype for channels callback function
|
||||
*/
|
||||
typedef void (*ChannelCallback)(Packet *packet, void *state);
|
||||
|
||||
/*
|
||||
* Function: Adp_initSeq
|
||||
* Purpose: initialise the channel protocol and sequence numbers
|
||||
*
|
||||
* Params: none
|
||||
*
|
||||
* Returns: Nothing
|
||||
*/
|
||||
extern void Adp_initSeq(void);
|
||||
|
||||
/*
|
||||
* Function: Adp_addToQueue
|
||||
* Purpose: chain a Packet to the end of a linked list of such structures
|
||||
*
|
||||
* Params:
|
||||
* In/Out: head Head of the linked list
|
||||
*
|
||||
* newpkt Packet to be chained onto the list
|
||||
*
|
||||
* Returns: Nothing
|
||||
*/
|
||||
extern void Adp_addToQueue(Packet **head, Packet *newpkt);
|
||||
|
||||
/*
|
||||
* Function: removeFromQueue
|
||||
* Purpose: remove a Packet from the head of a linked list of such structures
|
||||
*
|
||||
* Params:
|
||||
* In/Out: head Head of the linked list
|
||||
*
|
||||
* Returns: Old head from the linked list
|
||||
*
|
||||
* Post-conditions: Second element in the list will be the new head.
|
||||
*/
|
||||
|
||||
extern Packet *Adp_removeFromQueue(Packet **head);
|
||||
|
||||
/*
|
||||
* Function: Adp_OpenDevice
|
||||
* Purpose: Open a device to use for channels communication. This is a
|
||||
* very thin veneer to the device drivers: what hostchan.c
|
||||
* will do is call DeviceMatch for each device driver until it
|
||||
* finds a driver that will accept name and arg, then call
|
||||
* DeviceOpen for that device.
|
||||
*
|
||||
* Pre-conditions: No previous open is still active
|
||||
*
|
||||
* Params:
|
||||
* Input: name Identifies which device to open. This can either be
|
||||
* a host specific identifier (e.g. "/dev/ttya",
|
||||
* "COM1:"), or a number which is used to refer to
|
||||
* `standard' interfaces, so "1" would be the first host
|
||||
* interface, "2" the second, and so on.
|
||||
*
|
||||
* arg Driver specific arguments. For example, some serial
|
||||
* drivers accept speed and control arguments such as
|
||||
* "9600" or "19200/NO_BREAK". These arguments are
|
||||
* completely free-form: it is the individual drivers
|
||||
* which do the necessary interpretation.
|
||||
*
|
||||
* heartbeat_on Incicates if the heartbeat is configured to be
|
||||
* used or not, true if it is, false otherwise
|
||||
*
|
||||
* Returns:
|
||||
* OK: adp_ok
|
||||
* Error: adp_device_not_known,
|
||||
* adp_device_open_failed
|
||||
* adp_device_already_open
|
||||
*/
|
||||
AdpErrs Adp_OpenDevice(const char *name, const char *arg,
|
||||
unsigned int heartbeat_on);
|
||||
|
||||
/*
|
||||
* Function: Adp_CloseDevice
|
||||
* Purpose: Close the device used for channels communication.
|
||||
*
|
||||
* Params: None
|
||||
*
|
||||
* Returns:
|
||||
* OK: adp_ok
|
||||
* Error: adp_device_not_open
|
||||
*/
|
||||
AdpErrs Adp_CloseDevice(void);
|
||||
|
||||
/*
|
||||
* Function: Adp_Ioctl
|
||||
* Purpose: Perform miscellaneous control operations on
|
||||
* the device used for channels communication.
|
||||
* This is a minimal veneer to DevSW_Ioctl.
|
||||
*
|
||||
* Params:
|
||||
* Input: opcode Reason code indicating the operation to perform.
|
||||
* In/Out: args Pointer to opcode-sensitive arguments/result space.
|
||||
*
|
||||
*
|
||||
* Returns:
|
||||
* OK: adp_ok
|
||||
* Error: adp_device_not_open, adp_failed
|
||||
*/
|
||||
AdpErrs Adp_Ioctl(int opcode, void *args);
|
||||
|
||||
/*
|
||||
* Function: Adp_ChannelRegisterRead
|
||||
* Purpose: Register a callback function for received packets on a given
|
||||
* channel
|
||||
*
|
||||
* Params:
|
||||
* Input: chan The channel the callback function is for.
|
||||
*
|
||||
* cbfunc The callback function. If NULL, then the current
|
||||
* callback is removed.
|
||||
*
|
||||
* cbstate State pointer to pass into the callback function
|
||||
*
|
||||
* Returns:
|
||||
* OK: adp_ok
|
||||
* Error: adp_device_not_open
|
||||
* adp_bad_channel_id
|
||||
*
|
||||
* Post-conditions: The callback function is responsible for freeing the
|
||||
* packet that is passed to it, when that packet is
|
||||
* no longer needed.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
extern AdpErrs Adp_ChannelRegisterRead(const ChannelID chan,
|
||||
const ChannelCallback cbfunc,
|
||||
void *cbstate);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Function: Adp_ChannelRead
|
||||
* Purpose: Wait until a packet has been read for a given channel, and
|
||||
* then return it. Callbacks for other channels are still
|
||||
* active while this read is blocking.
|
||||
*
|
||||
* Pre-conditions: No callback has been already been registered for
|
||||
* the channel.
|
||||
*
|
||||
* Params:
|
||||
* Input: chan The channel to read.
|
||||
*
|
||||
* Output: packet The received packet.
|
||||
*
|
||||
* Returns:
|
||||
* OK: adp_ok
|
||||
* Error: adp_device_not_open
|
||||
* adp_bad_channel_id
|
||||
* adp_callback_already_registered
|
||||
*
|
||||
* Post-conditions: The calling function is responsible for freeing the
|
||||
* received packet, when that packet is no longer
|
||||
* needed.
|
||||
*/
|
||||
AdpErrs Adp_ChannelRead(const ChannelID chan, Packet **packet);
|
||||
|
||||
/*
|
||||
* Function: Adp_ChannelWrite
|
||||
* Purpose: Write a packet to the given channel
|
||||
*
|
||||
* Pre-conditions: Channel must have been previously opened.
|
||||
*
|
||||
* Params:
|
||||
* Input: chan The channel to write.
|
||||
*
|
||||
* packet The packet to write.
|
||||
*
|
||||
* Returns:
|
||||
* OK: adp_ok
|
||||
* Error: adp_device_not_open
|
||||
* adp_bad_channel_id
|
||||
*
|
||||
* Post-conditions: The packet being written becomes the "property" of
|
||||
* Adp_ChannelWrite, which is responsible for freeing
|
||||
* the packet when it is no longer needed.
|
||||
*/
|
||||
AdpErrs Adp_ChannelWrite(const ChannelID chan, Packet *packet);
|
||||
|
||||
/*
|
||||
* Function: Adp_ChannelWriteAsync
|
||||
* Purpose: Write a packet to the given channel, but don't wait
|
||||
* for the write to complete before returning.
|
||||
*
|
||||
* Pre-conditions: Channel must have been previously opened.
|
||||
*
|
||||
* Params:
|
||||
* Input: chan The channel to write.
|
||||
*
|
||||
* packet The packet to write.
|
||||
*
|
||||
* Returns:
|
||||
* OK: adp_ok
|
||||
* Error: adp_device_not_open
|
||||
* adp_bad_channel_id
|
||||
*
|
||||
* Post-conditions: The packet being written becomes the "property" of
|
||||
* Adp_ChannelWrite, which is responsible for freeing
|
||||
* the packet when it is no longer needed.
|
||||
*/
|
||||
AdpErrs Adp_ChannelWriteAsync(const ChannelID chan, Packet *packet);
|
||||
|
||||
/*
|
||||
* Function: Adp_AsynchronousProcessing
|
||||
* Purpose: This routine should be called from persistent any idle loop
|
||||
* to give the data I/O routines a chance to poll for packet
|
||||
* activity. Depending upon the requested mode, this routine
|
||||
* may, or may not, block.
|
||||
*
|
||||
* Params:
|
||||
* Input: mode Specifies whether to block until a complete packet
|
||||
* has been read, all pending writes have completed,
|
||||
* or not to block at all.
|
||||
*
|
||||
* Returns: Nothing.
|
||||
*/
|
||||
void Adp_AsynchronousProcessing(const AsyncMode mode);
|
||||
|
||||
/*
|
||||
* prototype for DC_APPL packet handler
|
||||
*/
|
||||
typedef void (*DC_Appl_Handler)(const DeviceDescr *device, Packet *packet);
|
||||
|
||||
/*
|
||||
* install a handler for DC_APPL packets (can be NULL), returning old one.
|
||||
*/
|
||||
DC_Appl_Handler Adp_Install_DC_Appl_Handler(const DC_Appl_Handler handler);
|
||||
|
||||
/*
|
||||
* prototype for asynchronous processing callback
|
||||
*/
|
||||
typedef void (*Adp_Async_Callback)(const DeviceDescr *device,
|
||||
const struct timeval *const time_now);
|
||||
|
||||
/*
|
||||
* add an asynchronous processing callback to the list
|
||||
* TRUE == okay, FALSE == no more async processing slots
|
||||
*/
|
||||
bool Adp_Install_Async_Callback( const Adp_Async_Callback callback_proc );
|
||||
|
||||
/*
|
||||
* delay for a given period (in microseconds)
|
||||
*/
|
||||
void Adp_delay(unsigned int period);
|
||||
|
||||
#endif /* ndef angsd_hostchan_h */
|
||||
|
||||
/* EOF hostchan.h */
|
|
@ -1,913 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Host C Library support functions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
# include <ctype.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "adp.h"
|
||||
#include "host.h"
|
||||
#include "ardi.h"
|
||||
#include "buffers.h"
|
||||
#include "channels.h" /* Channel interface. */
|
||||
#include "endian.h"
|
||||
#include "logging.h" /* Angel support functions. */
|
||||
#include "msgbuild.h"
|
||||
#include "sys.h"
|
||||
#include "hsys.h" /* Function and structure declarations. */
|
||||
#include "hostchan.h"
|
||||
|
||||
#define FILEHANDLE int
|
||||
|
||||
/* Note: no statics allowed. All globals must be malloc()ed on the heap.
|
||||
The state struct is used for this purpose. See 'hsys.h'. */
|
||||
/* This is the message handler function passed to the channel manager in
|
||||
HostSysInit. It is called whenever a message is received. 'buffptr'
|
||||
points to the message body. Functionality is provided by the debugger
|
||||
toolkit. The routine is very loosely based on the HandleSWI routine from
|
||||
armos.c in the armulator source. */
|
||||
/* These routines could be tested by providing a simple interface to armsd,
|
||||
and running them in that. */
|
||||
|
||||
|
||||
/* taken staight from armulator source */
|
||||
#ifdef __riscos
|
||||
extern int _fisatty(FILE *);
|
||||
# define isatty_(f) _fisatty(f)
|
||||
# define EMFILE -1
|
||||
# define EBADF -1
|
||||
int _kernel_escape_seen(void) { return 0 ;}
|
||||
#else
|
||||
# if defined(_WINDOWS) || defined(_CONSOLE)
|
||||
# define isatty_(f) (f == stdin || f == stdout)
|
||||
# else
|
||||
# ifdef __ZTC__
|
||||
# include <io.h>
|
||||
# define isatty_(f) isatty((f)->_file)
|
||||
# else
|
||||
# ifdef macintosh
|
||||
# include <ioctl.h>
|
||||
# define isatty_(f) (~ioctl((f)->_file,FIOINTERACTIVE,NULL))
|
||||
# else
|
||||
# define isatty_(f) isatty(fileno(f))
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Set up the state block, filetable and register the C lib callback fn */
|
||||
int HostSysInit(const struct Dbg_HostosInterface *hostif, char **cmdline,
|
||||
hsys_state **stateptr)
|
||||
{
|
||||
ChannelCallback HandleMessageFPtr = (ChannelCallback) HandleSysMessage;
|
||||
int i;
|
||||
*stateptr = (hsys_state *)malloc(sizeof(hsys_state));
|
||||
|
||||
if (*stateptr == NULL) return RDIError_OutOfStore;
|
||||
|
||||
(*stateptr)->hostif=hostif;
|
||||
(*stateptr)->last_errno=0;
|
||||
(*stateptr)->OSptr=(OSblock *)malloc(sizeof(OSblock));
|
||||
if ((*stateptr)->OSptr == NULL) return RDIError_OutOfStore;
|
||||
for (i=0; i<UNIQUETEMPS; i++) (*stateptr)->OSptr->TempNames[i]=NULL;
|
||||
for (i=0; i<HSYS_FOPEN_MAX; i++) {
|
||||
(*stateptr)->OSptr->FileTable[i]=NULL;
|
||||
(*stateptr)->OSptr->FileFlags[i]=0;
|
||||
}
|
||||
(*stateptr)->CommandLine=cmdline;
|
||||
|
||||
return Adp_ChannelRegisterRead(CI_CLIB, (ChannelCallback)HandleMessageFPtr,
|
||||
*stateptr);
|
||||
}
|
||||
|
||||
/* Shut down the Clib support, this will probably never get called though */
|
||||
int HostSysExit(hsys_state *stateptr)
|
||||
{
|
||||
free(stateptr->OSptr);
|
||||
free(stateptr);
|
||||
return RDIError_NoError;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static void DebugCheckNullTermString(char *prefix, bool nl,
|
||||
unsigned int len, unsigned char *strp)
|
||||
{
|
||||
printf("%s: %d: ", prefix, len);
|
||||
if (strp[len]=='\0')
|
||||
printf("\"%s\"", strp);
|
||||
else
|
||||
printf("NOT NULL TERMINATED");
|
||||
if (nl)
|
||||
printf("\n");
|
||||
else
|
||||
{
|
||||
printf(" ");
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
extern int sys_nerr;
|
||||
extern char *sys_errlist[];
|
||||
|
||||
static char *DebugStrError(int last_errno)
|
||||
{
|
||||
if (last_errno < sys_nerr)
|
||||
return sys_errlist[last_errno];
|
||||
else
|
||||
return "NO MSG (errno>sys_nerr)";
|
||||
}
|
||||
|
||||
static void DebugCheckErr(char *prefix, bool nl, int err, int last_errno)
|
||||
{
|
||||
printf("\t%s: returned ", prefix);
|
||||
if (err == 0)
|
||||
printf("okay");
|
||||
else
|
||||
printf("%d, errno = %d \"%s\"", err, last_errno,
|
||||
DebugStrError(last_errno));
|
||||
if (nl)
|
||||
printf("\n");
|
||||
else
|
||||
{
|
||||
printf(" ");
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
static void DebugCheckNonNull(char *prefix, bool nl,
|
||||
void *handle, int last_errno)
|
||||
{
|
||||
printf("\t%s: returned ", prefix);
|
||||
if (handle != NULL)
|
||||
printf("okay [%08x]", (unsigned int)handle);
|
||||
else
|
||||
printf("NULL, errno = %d \"%s\"", last_errno,
|
||||
DebugStrError(last_errno));
|
||||
if (nl)
|
||||
printf("\n");
|
||||
else
|
||||
{
|
||||
printf(" ");
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
#define DebugPrintF(c) printf c;
|
||||
|
||||
#else
|
||||
|
||||
#define DebugCheckNullTermString(p, n, l, s) ((void)(0))
|
||||
#define DebugCheckErr(p, n, e, l) ((void)(0))
|
||||
#define DebugCheckNonNull(p, n, h, l) ((void)(0))
|
||||
#define DebugPrintF(c) ((void)(0))
|
||||
|
||||
#endif /* ifdef DEBUG ... else */
|
||||
|
||||
static FILE *hsysGetRealFileHandle(hsys_state *stateptr, int fh, char *flags)
|
||||
{
|
||||
FILE *file_p = NULL;
|
||||
|
||||
if (fh < 0 || fh >= HSYS_FOPEN_MAX)
|
||||
{
|
||||
stateptr->last_errno = EBADF;
|
||||
DebugPrintF(("\tfh %d out-of-bounds!\n", fh));
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
file_p = stateptr->OSptr->FileTable[fh];
|
||||
if (file_p != NULL) {
|
||||
if (flags != NULL)
|
||||
*flags = stateptr->OSptr->FileFlags[fh];
|
||||
}
|
||||
else {
|
||||
stateptr->last_errno = EBADF;
|
||||
DebugPrintF(("\tFileTable[%d] is NULL\n", fh));
|
||||
}
|
||||
|
||||
return file_p;
|
||||
}
|
||||
}
|
||||
|
||||
int HandleSysMessage(Packet *packet, hsys_state *stateptr)
|
||||
{
|
||||
unsigned int reason_code, mode, len, c, nbytes, nbtotal, nbtogo = 0;
|
||||
long posn, fl;
|
||||
char character;
|
||||
int err;
|
||||
|
||||
/* Note: We must not free the buffer passed in as the callback handler */
|
||||
/* expects to do this. Freeing any other buffers we have malloced */
|
||||
/* ourselves is acceptable */
|
||||
|
||||
unsigned char *buffp = ((unsigned char *)BUFFERDATA(packet->pk_buffer))+16;
|
||||
/* buffp points to the parameters*/
|
||||
/* the invidual messages, excluding*/
|
||||
/* standard SYS fields (debugID, */
|
||||
/* osinfo and reasoncode) */
|
||||
unsigned char *buffhead = (unsigned char *)(packet->pk_buffer);
|
||||
|
||||
int DebugID, OSInfo1, OSInfo2, count;
|
||||
|
||||
const char* fmode[] = {"r","rb","r+","r+b",
|
||||
"w","wb","w+","w+b",
|
||||
"a","ab","a+","a+b",
|
||||
"r","r","r","r"} /* last 4 are illegal */ ;
|
||||
|
||||
FILEHANDLE fh; /* fh is used as an index to the real file handle
|
||||
* in OSptr */
|
||||
FILE *fhreal;
|
||||
unpack_message(BUFFERDATA(buffhead), "%w%w%w%w", &reason_code,
|
||||
&DebugID, &OSInfo1, &OSInfo2);
|
||||
/* Extract reason code from buffer. */
|
||||
reason_code &= 0xFFFF; /* Strip away direction bit, OSInfo and */
|
||||
/* DebugInfo fields. Will want to do some */
|
||||
/* sort of validation on this later. */
|
||||
|
||||
switch(reason_code)
|
||||
{
|
||||
|
||||
case CL_WriteC: /* Write a character to the terminal. */
|
||||
/* byte data -> word status */
|
||||
{
|
||||
#ifdef DEBUG
|
||||
int c = (int)(*buffp);
|
||||
printf("CL_WriteC: [%02x]>%c<", c, isprint(c) ? c : '.');
|
||||
#endif
|
||||
stateptr->hostif->writec(stateptr->hostif->hostosarg, (int)(*buffp));
|
||||
DevSW_FreePacket(packet);
|
||||
return msgsend(CI_CLIB,"%w%w%w%w%w", CL_WriteC|HtoT,
|
||||
DebugID, OSInfo1, OSInfo2, NoError);
|
||||
}
|
||||
|
||||
case CL_Write0: /* Write a null terminated string to the terminal. */
|
||||
{
|
||||
unpack_message(buffp, "%w", &len);
|
||||
DebugCheckNullTermString("CL_Write0", TRUE, len, buffp+4);
|
||||
stateptr->hostif->write(stateptr->hostif->hostosarg,
|
||||
(char *) buffp+4, len);
|
||||
DevSW_FreePacket(packet);
|
||||
return msgsend(CI_CLIB, "%w%w%w%w%w", CL_Write0|HtoT, DebugID,
|
||||
OSInfo1, OSInfo2, NoError);
|
||||
}
|
||||
|
||||
case CL_ReadC: /* Read a byte from the terminal */
|
||||
{
|
||||
DebugPrintF(("CL_ReadC: "));
|
||||
DevSW_FreePacket(packet);
|
||||
|
||||
character = stateptr->hostif->readc(stateptr->hostif->hostosarg);
|
||||
DebugPrintF(("\nCL_ReadC returning [%02x]>%c<\n", character,
|
||||
isprint(character) ? character : '.'));
|
||||
|
||||
return msgsend(CI_CLIB, "%w%w%w%w%w%b", CL_ReadC|HtoT,
|
||||
DebugID, OSInfo1, OSInfo2, NoError, character);
|
||||
}
|
||||
|
||||
case CL_System: /* Pass NULL terminated string to the hosts command
|
||||
* interpreter. As it is nULL terminated we dont need
|
||||
* the length
|
||||
*/
|
||||
{
|
||||
unpack_message(buffp, "%w", &len);
|
||||
DebugCheckNullTermString("CL_System", TRUE, len, buffp+4);
|
||||
|
||||
err = system((char *)buffp+4); /* Use the string in the buffer */
|
||||
stateptr->last_errno = errno;
|
||||
DebugCheckErr("system", TRUE, err, stateptr->last_errno);
|
||||
|
||||
err = msgsend(CI_CLIB, "%w%w%w%w%w%w", CL_System|HtoT,
|
||||
DebugID, OSInfo1, OSInfo2, NoError, err);
|
||||
DevSW_FreePacket(packet);
|
||||
return err;
|
||||
}
|
||||
|
||||
case CL_GetCmdLine: /* Returns the command line used to call the program */
|
||||
{
|
||||
/* Note: we reuse the packet here, this may not always be desirable */
|
||||
/* /* TODO: Use long buffers if possible */
|
||||
DebugPrintF(("CL_GetCmdLine: \"%s\"\n", *(stateptr->CommandLine)));
|
||||
|
||||
if (buffhead!=NULL) {
|
||||
len = strlen(*(stateptr->CommandLine));
|
||||
if (len > Armsd_BufferSize-24) len = Armsd_BufferSize-24;
|
||||
packet->pk_length = len + msgbuild(BUFFERDATA(buffhead),
|
||||
"%w%w%w%w%w%w", CL_GetCmdLine|HtoT,
|
||||
DebugID, OSInfo1, OSInfo2,
|
||||
NoError, len);
|
||||
strncpy((char *) BUFFERDATA(buffhead)+24,*(stateptr->CommandLine),
|
||||
len);
|
||||
|
||||
Adp_ChannelWrite(CI_CLIB, packet);/* Send message. */
|
||||
return 0;
|
||||
}
|
||||
else return -1;
|
||||
}
|
||||
|
||||
case CL_Clock: /* Return the number of centiseconds since the support */
|
||||
/* code started executing */
|
||||
{
|
||||
time_t retTime = time(NULL);
|
||||
if (retTime == (time_t)-1)
|
||||
stateptr->last_errno = errno;
|
||||
else
|
||||
retTime *=100;
|
||||
|
||||
DebugPrintF(("CL_Clock: %lu\n", retTime));
|
||||
DebugCheckErr("time", TRUE, (retTime == (time_t)-1),
|
||||
stateptr->last_errno);
|
||||
|
||||
DevSW_FreePacket(packet);
|
||||
return msgsend(CI_CLIB, "%w%w%w%w%w%w",CL_Clock|HtoT,
|
||||
DebugID, OSInfo1, OSInfo2, NoError, retTime);
|
||||
}
|
||||
|
||||
case CL_Time: /* return time, in seconds since the start of 1970 */
|
||||
{
|
||||
time_t retTime = time(NULL);
|
||||
if (retTime == (time_t)-1)
|
||||
stateptr->last_errno = errno;
|
||||
|
||||
DebugPrintF(("CL_Time: %lu\n", retTime));
|
||||
DebugCheckErr("time", TRUE, (retTime == (time_t)-1),
|
||||
stateptr->last_errno);
|
||||
|
||||
DevSW_FreePacket(packet);
|
||||
return msgsend(CI_CLIB,"%w%w%w%w%w%w",CL_Time|HtoT,
|
||||
DebugID, OSInfo1, OSInfo2, NoError, retTime);
|
||||
}
|
||||
|
||||
case CL_Remove: /* delete named in the null terminated string */
|
||||
{
|
||||
/* Removing an open file will cause problems but once again
|
||||
* its not our problem, likely result is a tangled FileTable */
|
||||
/* As the filename is passed with a null terminator we can use it
|
||||
* straight out of the buffer without copying it.*/
|
||||
|
||||
unpack_message(buffp, "%w", &len);
|
||||
DebugCheckNullTermString("CL_Remove", TRUE, len, buffp+4);
|
||||
|
||||
err=remove((char *)buffp+4);
|
||||
stateptr->last_errno = errno;
|
||||
DevSW_FreePacket(packet);
|
||||
DebugCheckErr("remove", TRUE, err, stateptr->last_errno);
|
||||
|
||||
return msgsend(CI_CLIB, "%w%w%w%w%w", CL_Remove|HtoT,
|
||||
DebugID, OSInfo1, OSInfo2, err?-1:NoError);
|
||||
}
|
||||
|
||||
case CL_Rename: /* rename file */
|
||||
{
|
||||
/* Rename(word nbytes, bytes oname, word nbytes, bytes nname)
|
||||
* return(byte status)
|
||||
*/
|
||||
unsigned int len2;
|
||||
|
||||
unpack_message(buffp, "%w", &len);
|
||||
DebugCheckNullTermString("CL_Rename", FALSE, len, buffp+4);
|
||||
unpack_message(buffp+5+len, "%w", &len2);
|
||||
DebugCheckNullTermString("to", TRUE, len2, buffp+9+len);
|
||||
|
||||
/* Both names are passed with null terminators so we can use them
|
||||
* directly from the buffer. */
|
||||
err = rename((char *)buffp+4, (char *)buffp+9+len);
|
||||
stateptr->last_errno = errno;
|
||||
DebugCheckErr("rename", TRUE, err, stateptr->last_errno);
|
||||
DevSW_FreePacket(packet);
|
||||
|
||||
return msgsend(CI_CLIB, "%w%w%w%w%w", CL_Rename|HtoT,
|
||||
DebugID, OSInfo1, OSInfo2, (err==0)? NoError : -1);
|
||||
}
|
||||
|
||||
case CL_Open: /* open the file */
|
||||
{
|
||||
/* Open(word nbytes, bytes name, byte mode)
|
||||
* return(word handle)
|
||||
*/
|
||||
unpack_message(buffp, "%w", &len);
|
||||
/* get the open mode */
|
||||
unpack_message((buffp)+4+len+1, "%w", &mode);
|
||||
DebugCheckNullTermString("CL_Open", FALSE, len, buffp+4);
|
||||
DebugPrintF(("mode: %d\n", mode));
|
||||
|
||||
/* do some checking on the file first? */
|
||||
/* check if its a tty */
|
||||
if (strcmp((char *)buffp+4, ":tt")==0 && (mode==0||mode==1)) {
|
||||
/* opening tty "r" */
|
||||
fhreal = stdin;
|
||||
stateptr->last_errno = errno;
|
||||
DebugPrintF(("\tstdin "));
|
||||
}
|
||||
else if (strcmp((char *)buffp+4, ":tt")== 0 && (mode==4||mode==5)) {
|
||||
/* opening tty "w" */
|
||||
fhreal = stdout;
|
||||
stateptr->last_errno = errno;
|
||||
DebugPrintF(("\tstdout "));
|
||||
}
|
||||
else
|
||||
{
|
||||
fhreal = fopen((char *)buffp+4, fmode[mode&0xFF]);
|
||||
stateptr->last_errno = errno;
|
||||
DebugCheckNonNull("fopen", FALSE, fhreal, stateptr->last_errno);
|
||||
}
|
||||
DevSW_FreePacket(packet);
|
||||
|
||||
c = NONHANDLE;
|
||||
if (fhreal != NULL) {
|
||||
/* update filetable */
|
||||
for (c=3; c < HSYS_FOPEN_MAX; c++) {
|
||||
/* allow for stdin, stdout, stderr (!!! WHY? MJG) */
|
||||
if (stateptr->OSptr->FileTable[c] == NULL) {
|
||||
stateptr->OSptr->FileTable[c]= fhreal;
|
||||
stateptr->OSptr->FileFlags[c]= mode & 1;
|
||||
DebugPrintF(("fh: %d\n", c));
|
||||
break;
|
||||
}
|
||||
else if (c == HSYS_FOPEN_MAX) {
|
||||
/* no filehandles free */
|
||||
DebugPrintF(("no free fh: %d\n", c));
|
||||
stateptr->last_errno = EMFILE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* c = NULL;*/
|
||||
DebugPrintF(("error fh: %d\n", c));
|
||||
}
|
||||
(void) msgsend(CI_CLIB, "%w%w%w%w%w", CL_Open|HtoT,
|
||||
DebugID, OSInfo1, OSInfo2, c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case CL_Close: /* close the file pointed to by the filehandle */
|
||||
{
|
||||
unpack_message(buffp, "%w", &fh);
|
||||
DebugPrintF(("CL_Close: fh %d\n", fh));
|
||||
DevSW_FreePacket(packet);
|
||||
|
||||
fhreal = hsysGetRealFileHandle(stateptr, fh, NULL);
|
||||
if (fhreal == NULL)
|
||||
err = -1;
|
||||
else {
|
||||
if (fhreal == stdin || fhreal == stdout || fhreal == stderr) {
|
||||
stateptr->last_errno = errno;
|
||||
DebugPrintF(("\tskipping close of std*\n"));
|
||||
err = 0;
|
||||
}
|
||||
else {
|
||||
err = fclose(fhreal);
|
||||
if (err == 0)
|
||||
stateptr->OSptr->FileTable[fh]=NULL;
|
||||
stateptr->last_errno = errno;
|
||||
DebugCheckErr("fclose", TRUE, err, stateptr->last_errno);
|
||||
}
|
||||
}
|
||||
return msgsend(CI_CLIB,"%w%w%w%w%w", CL_Close|HtoT, DebugID,
|
||||
OSInfo1, OSInfo2, err);
|
||||
}
|
||||
|
||||
case CL_Write:
|
||||
{
|
||||
/* Write(word handle, word nbtotal, word nbytes, bytes data)
|
||||
* return(word nbytes)
|
||||
* WriteX(word nbytes, bytes data)
|
||||
* return(word nbytes)
|
||||
*/
|
||||
unsigned char *rwdata = NULL, *rwhead = NULL;
|
||||
unsigned char *write_source = NULL;
|
||||
char flags;
|
||||
FILE *fhreal;
|
||||
unsigned int ack_reason = CL_Write; /* first ack is for CL_Write */
|
||||
|
||||
err = -1; /* err == 0 is fwrite() error indication */
|
||||
unpack_message(buffp, "%w%w%w", &fh, &nbtotal, &nbytes);
|
||||
DebugPrintF(("CL_Write: fh %d nbtotal %u nbytes %u\n",
|
||||
fh, nbtotal, nbytes));
|
||||
|
||||
fhreal = hsysGetRealFileHandle(stateptr, fh, &flags);
|
||||
nbtogo = nbtotal;
|
||||
|
||||
/* deal with the file handle */
|
||||
if (fhreal == NULL)
|
||||
err = 0;
|
||||
else {
|
||||
if (flags & READOP)
|
||||
fseek(fhreal,0,SEEK_CUR);
|
||||
stateptr->OSptr->FileFlags[fh] = (flags & BINARY) | WRITEOP;
|
||||
|
||||
nbtogo -= nbytes;
|
||||
|
||||
if (nbtogo > 0) {
|
||||
write_source = rwdata = rwhead = (unsigned char *)malloc(nbtotal);
|
||||
if (rwhead == NULL) {
|
||||
fprintf(stderr, "OUT OF MEMORY at line %d in %s\n",
|
||||
__LINE__, __FILE__);
|
||||
return -1;
|
||||
}
|
||||
memcpy(rwdata, buffp+12, nbytes);
|
||||
rwdata += nbytes;
|
||||
}
|
||||
else
|
||||
write_source = buffp+12;
|
||||
}
|
||||
|
||||
do {
|
||||
/* at least once!! */
|
||||
|
||||
if (nbtogo == 0 && err != 0) {
|
||||
/* Do the actual write! */
|
||||
if (fhreal == stdout || fhreal == stderr) {
|
||||
stateptr->hostif->write(stateptr->hostif->hostosarg,
|
||||
(char *)write_source, nbtotal);
|
||||
}
|
||||
else
|
||||
err = fwrite(write_source, 1, nbtotal, fhreal);
|
||||
stateptr->last_errno = errno;
|
||||
DebugCheckErr("fwrite", TRUE, (err == 0), stateptr->last_errno);
|
||||
}
|
||||
|
||||
DevSW_FreePacket(packet);
|
||||
if (msgsend(CI_CLIB,"%w%w%w%w%w%w", ack_reason|HtoT,
|
||||
DebugID, OSInfo1, OSInfo2, (err == 0), nbtogo))
|
||||
{
|
||||
fprintf(stderr, "COULD NOT REPLY at line %d in %s\n",
|
||||
__LINE__, __FILE__);
|
||||
if (rwhead != NULL)
|
||||
free(rwhead);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nbtogo == 0 || err == 0) {
|
||||
DebugPrintF(("\twrite complete - returning\n"));
|
||||
if (rwhead != NULL)
|
||||
free(rwhead);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
/* await extension */
|
||||
ack_reason = CL_WriteX;
|
||||
|
||||
packet = DevSW_AllocatePacket(Armsd_BufferSize);
|
||||
if (packet == NULL)
|
||||
{
|
||||
fprintf(stderr, "COULD NOT ALLOC PACKET at line %d in %s\n",
|
||||
__LINE__, __FILE__);
|
||||
if (rwhead != NULL)
|
||||
free(rwhead);
|
||||
return -1;
|
||||
}
|
||||
Adp_ChannelRegisterRead(CI_CLIB, NULL, NULL);
|
||||
Adp_ChannelRead(CI_CLIB, &packet);
|
||||
Adp_ChannelRegisterRead(CI_CLIB,
|
||||
(ChannelCallback)HandleSysMessage,
|
||||
stateptr);
|
||||
|
||||
buffhead = packet->pk_buffer;
|
||||
unpack_message(BUFFERDATA(buffhead), "%w%w%w%w%w", &reason_code,
|
||||
&DebugID, &OSInfo1, &OSInfo2, &nbytes);
|
||||
if (reason_code != (CL_WriteX|TtoH)) {
|
||||
DevSW_FreePacket(packet);
|
||||
free(rwhead);
|
||||
fprintf(stderr, "EXPECTING CL_WriteX GOT %u at line %d in %s\n",
|
||||
reason_code, __LINE__, __FILE__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DebugPrintF(("CL_WriteX: nbytes %u\n", nbytes));
|
||||
memcpy(rwdata, BUFFERDATA(buffhead)+20, nbytes);
|
||||
rwdata += nbytes;
|
||||
nbtogo -= nbytes;
|
||||
}
|
||||
|
||||
} while (TRUE); /* will return when done */
|
||||
}
|
||||
|
||||
case CL_WriteX: /*
|
||||
* NOTE: if we've got here something has gone wrong
|
||||
* CL_WriteX's should all be picked up within the
|
||||
* CL_Write loop, probably best to return an error here
|
||||
* do this for the moment just so we do actually return
|
||||
*/
|
||||
fprintf(stderr, "ERROR: unexpected CL_WriteX message received\n");
|
||||
return -1;
|
||||
|
||||
case CL_Read:
|
||||
{
|
||||
/* Read(word handle, word nbtotal)
|
||||
* return(word nbytes, word nbmore, bytes data)
|
||||
*/
|
||||
/* ReadX()
|
||||
* return(word nbytes, word nbmore, bytes data) */
|
||||
unsigned char *rwdata, *rwhead;
|
||||
int gotlen;
|
||||
unsigned int max_data_in_buffer=Armsd_BufferSize-28;
|
||||
char flags;
|
||||
FILE *fhreal;
|
||||
unsigned int nbleft = 0, reason = CL_Read;
|
||||
|
||||
err = NoError;
|
||||
|
||||
unpack_message(buffp, "%w%w", &fh, &nbtotal);
|
||||
DebugPrintF(("CL_Read: fh %d, nbtotal %d: ", fh, nbtotal));
|
||||
|
||||
rwdata = rwhead = (unsigned char *)malloc(nbtotal);
|
||||
if (rwdata == NULL) {
|
||||
fprintf(stderr, "OUT OF MEMORY at line %d in %s\n",
|
||||
__LINE__, __FILE__);
|
||||
DevSW_FreePacket(packet);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* perform the actual read */
|
||||
fhreal = hsysGetRealFileHandle(stateptr, fh, &flags);
|
||||
if (fhreal == NULL)
|
||||
{
|
||||
/* bad file handle */
|
||||
err = -1;
|
||||
nbytes = 0;
|
||||
gotlen = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flags & WRITEOP)
|
||||
fseek(fhreal,0,SEEK_CUR);
|
||||
stateptr->OSptr->FileFlags[fh] = (flags & BINARY) | WRITEOP;
|
||||
if (isatty_(fhreal)) {
|
||||
/* reading from a tty, so do some nasty stuff, reading into rwdata */
|
||||
if (angel_hostif->gets(stateptr->hostif->hostosarg, (char *)rwdata,
|
||||
nbtotal) != 0)
|
||||
gotlen = strlen((char *)rwdata);
|
||||
else
|
||||
gotlen = 0;
|
||||
stateptr->last_errno = errno;
|
||||
DebugPrintF(("ttyread %d\n", gotlen));
|
||||
}
|
||||
else {
|
||||
/* not a tty, reading from a real file */
|
||||
gotlen = fread(rwdata, 1, nbtotal, fhreal);
|
||||
stateptr->last_errno = errno;
|
||||
DebugCheckErr("fread", FALSE, (gotlen == 0), stateptr->last_errno);
|
||||
DebugPrintF(("(%d)\n", gotlen));
|
||||
}
|
||||
}
|
||||
|
||||
nbtogo = gotlen;
|
||||
|
||||
do {
|
||||
/* at least once */
|
||||
|
||||
if ((unsigned int) nbtogo <= max_data_in_buffer)
|
||||
nbytes = nbtogo;
|
||||
else
|
||||
nbytes = max_data_in_buffer;
|
||||
nbtogo -= nbytes;
|
||||
|
||||
/* last ReadX needs subtle adjustment to returned nbtogo */
|
||||
if (nbtogo == 0 && err == NoError && reason == CL_ReadX)
|
||||
nbleft = nbtotal - gotlen;
|
||||
else
|
||||
nbleft = nbtogo;
|
||||
|
||||
count = msgbuild(BUFFERDATA(buffhead), "%w%w%w%w%w%w%w",
|
||||
reason|HtoT, 0, ADP_HandleUnknown,
|
||||
ADP_HandleUnknown, err, nbytes, nbleft);
|
||||
|
||||
if (err == NoError) {
|
||||
/* copy data into buffptr */
|
||||
memcpy(BUFFERDATA(buffhead)+28, rwdata, nbytes);
|
||||
rwdata += nbytes;
|
||||
count += nbytes;
|
||||
}
|
||||
|
||||
DebugPrintF(("\treplying err %d, nbytes %d, nbtogo %d\n",
|
||||
err, nbytes, nbtogo));
|
||||
|
||||
packet->pk_length = count;
|
||||
Adp_ChannelWrite(CI_CLIB, packet);
|
||||
|
||||
if (nbtogo == 0 || err != NoError) {
|
||||
/* done */
|
||||
free(rwhead);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
/* await extension */
|
||||
reason = CL_ReadX;
|
||||
|
||||
packet = DevSW_AllocatePacket(Armsd_BufferSize);
|
||||
if (packet == NULL) {
|
||||
fprintf(stderr, "COULD NOT ALLOC PACKET at line %d in %s\n",
|
||||
__LINE__, __FILE__);
|
||||
free(rwhead);
|
||||
return -1;
|
||||
}
|
||||
Adp_ChannelRegisterRead(CI_CLIB, NULL, NULL);
|
||||
Adp_ChannelRead(CI_CLIB, &packet);
|
||||
Adp_ChannelRegisterRead(CI_CLIB,
|
||||
(ChannelCallback)HandleSysMessage,
|
||||
stateptr);
|
||||
buffhead = packet->pk_buffer;
|
||||
unpack_message(BUFFERDATA(buffhead),"%w", &reason_code);
|
||||
if (reason_code != (CL_ReadX|TtoH)) {
|
||||
fprintf(stderr, "EXPECTING CL_ReadX GOT %u at line %d in %s\n",
|
||||
reason_code, __LINE__, __FILE__);
|
||||
DevSW_FreePacket(packet);
|
||||
free(rwdata);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
} while (TRUE); /* will return above on error or when done */
|
||||
}
|
||||
|
||||
case CL_ReadX: /* If we're here something has probably gone wrong */
|
||||
fprintf(stderr, "ERROR: Got unexpected CL_ReadX message\n");
|
||||
return -1;
|
||||
|
||||
case CL_Seek:
|
||||
{
|
||||
unpack_message(buffp, "%w%w", &fh, &posn);
|
||||
DebugPrintF(("CL_Seek: fh %d, posn %ld\n", fh, posn));
|
||||
DevSW_FreePacket(packet);
|
||||
|
||||
fhreal = hsysGetRealFileHandle(stateptr, fh, NULL);
|
||||
if (fhreal == NULL)
|
||||
err = -1;
|
||||
else {
|
||||
err = fseek(fhreal, posn, SEEK_SET);
|
||||
stateptr->last_errno = errno;
|
||||
DebugCheckErr("fseek", TRUE, err, stateptr->last_errno);
|
||||
}
|
||||
|
||||
return msgsend(CI_CLIB, "%w%w%w%w%w", CL_Seek|HtoT,
|
||||
DebugID, OSInfo1, OSInfo2, err);
|
||||
}
|
||||
|
||||
case CL_Flen:
|
||||
{
|
||||
unpack_message(buffp, "%w", &fh);
|
||||
DebugPrintF(("CL_Flen: fh %d ", fh));
|
||||
DevSW_FreePacket(packet);
|
||||
|
||||
fhreal = hsysGetRealFileHandle(stateptr, fh, NULL);
|
||||
if (fhreal == NULL)
|
||||
fl = -1;
|
||||
else {
|
||||
posn = ftell(fhreal);
|
||||
if (fseek(fhreal, 0L, SEEK_END) < 0) {
|
||||
fl=-1;
|
||||
}
|
||||
else {
|
||||
fl = ftell(fhreal);
|
||||
fseek(fhreal, posn, SEEK_SET);
|
||||
}
|
||||
stateptr->last_errno = errno;
|
||||
}
|
||||
DebugPrintF(("returning len %ld\n", fl));
|
||||
return msgsend(CI_CLIB, "%w%w%w%w%w", CL_Flen|HtoT, DebugID, OSInfo1,
|
||||
OSInfo2, fl);
|
||||
}
|
||||
|
||||
case CL_IsTTY:
|
||||
{
|
||||
int ttyOrNot;
|
||||
unpack_message(buffp, "%w", &fh);
|
||||
DebugPrintF(("CL_IsTTY: fh %d ", fh));
|
||||
DevSW_FreePacket(packet);
|
||||
|
||||
fhreal = hsysGetRealFileHandle(stateptr, fh, NULL);
|
||||
if (fhreal == NULL)
|
||||
ttyOrNot = FALSE;
|
||||
else {
|
||||
ttyOrNot = isatty_(fhreal);
|
||||
stateptr->last_errno = errno;
|
||||
}
|
||||
DebugPrintF(("returning %s\n", ttyOrNot ? "tty (1)" : "not (0)"));
|
||||
|
||||
return msgsend(CI_CLIB, "%w%w%w%w%w",CL_IsTTY|HtoT,
|
||||
DebugID, OSInfo1, OSInfo2, ttyOrNot);
|
||||
}
|
||||
|
||||
case CL_TmpNam:
|
||||
{
|
||||
char *name;
|
||||
unsigned int tnamelen, TargetID;
|
||||
unpack_message(buffp, "%w%w", &tnamelen, &TargetID);
|
||||
DebugPrintF(("CL_TmpNam: tnamelen %d TargetID %d: ",
|
||||
tnamelen, TargetID));
|
||||
DevSW_FreePacket(packet);
|
||||
|
||||
TargetID = TargetID & 0xFF;
|
||||
if (stateptr->OSptr->TempNames[TargetID] == NULL) {
|
||||
if ((stateptr->OSptr->TempNames[TargetID] =
|
||||
(char *)malloc(L_tmpnam)) == NULL)
|
||||
{
|
||||
fprintf(stderr, "OUT OF MEMORY at line %d in %s\n",
|
||||
__LINE__, __FILE__);
|
||||
return -1;
|
||||
}
|
||||
tmpnam(stateptr->OSptr->TempNames[TargetID]);
|
||||
}
|
||||
name = stateptr->OSptr->TempNames[TargetID];
|
||||
len = strlen(name) + 1;
|
||||
packet = DevSW_AllocatePacket(Armsd_BufferSize);
|
||||
if (packet == NULL)
|
||||
{
|
||||
fprintf(stderr, "COULD NOT ALLOC PACKET at line %d in %s\n",
|
||||
__LINE__, __FILE__);
|
||||
return -1;
|
||||
}
|
||||
buffhead = packet->pk_buffer;
|
||||
if (len > tnamelen) {
|
||||
DebugPrintF(("TMPNAME TOO LONG!\n"));
|
||||
count = msgbuild(BUFFERDATA(buffhead), "%w%w%w%w%w",
|
||||
CL_TmpNam|HtoT, DebugID, OSInfo1, OSInfo2, -1);
|
||||
}
|
||||
else {
|
||||
DebugPrintF(("returning \"%s\"\n", name));
|
||||
count = msgbuild(BUFFERDATA(buffhead), "%w%w%w%w%w%w", CL_TmpNam|HtoT,
|
||||
DebugID, OSInfo1, OSInfo2, 0, len);
|
||||
strcpy((char *)BUFFERDATA(buffhead)+count, name);
|
||||
count +=len+1;
|
||||
}
|
||||
packet->pk_length = count;
|
||||
Adp_ChannelWrite(CI_CLIB, packet);/* Send message. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
case CL_Unrecognised:
|
||||
DebugPrintF(("CL_Unrecognised!!\n"));
|
||||
return 0;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "UNRECOGNISED CL code %08x\n", reason_code);
|
||||
break;
|
||||
/* Need some sort of error handling here. */
|
||||
/* A call to CL_Unrecognised should suffice */
|
||||
}
|
||||
return -1; /* Stop a potential compiler warning */
|
||||
}
|
||||
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
extern HWND hwndParent;
|
||||
|
||||
void panic(const char *format, ...)
|
||||
{
|
||||
char buf[2048];
|
||||
va_list args;
|
||||
|
||||
Adp_CloseDevice();
|
||||
|
||||
va_start(args, format);
|
||||
vsprintf(buf, format, args);
|
||||
|
||||
MessageBox(hwndParent, (LPCTSTR)buf, (LPCTSTR)"Fatal Error:", MB_OK);
|
||||
|
||||
/* SJ - Not the proper way to shutdown the app */
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
/*
|
||||
if (hwndParent != NULL)
|
||||
SendMessage(hwndParent, WM_QUIT, 0, 0);
|
||||
*/
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void panic(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
fprintf(stderr, "Fatal error: ");
|
||||
vfprintf(stderr, format, args);
|
||||
fprintf(stderr,"\n");
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* EOF hsys.c */
|
|
@ -1,99 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Host C library support header file.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef angsd_hsys_h
|
||||
#define angsd_hsys_h
|
||||
|
||||
#define HSYS_FOPEN_MAX 256
|
||||
#define NONHANDLE -1
|
||||
#define UNIQUETEMPS 256
|
||||
|
||||
#include "dbg_hif.h"
|
||||
#include "hostchan.h"
|
||||
|
||||
typedef struct {
|
||||
FILE *FileTable[HSYS_FOPEN_MAX] ;
|
||||
char FileFlags[HSYS_FOPEN_MAX] ;
|
||||
char *TempNames[UNIQUETEMPS];
|
||||
} OSblock;
|
||||
|
||||
#define NOOP 0
|
||||
#define BINARY 1
|
||||
#define READOP 2
|
||||
#define WRITEOP 4
|
||||
|
||||
typedef struct {
|
||||
const struct Dbg_HostosInterface *hostif; /* Interface to debug toolkit. */
|
||||
int last_errno; /* Number of the last error. */
|
||||
OSblock *OSptr;
|
||||
char **CommandLine ; /* Ptr to cmd line d`string held by ardi.c */
|
||||
} hsys_state;
|
||||
|
||||
/*
|
||||
* Function: HostSysInit
|
||||
* Purpose: Set up the state block, filetable and register the and C lib
|
||||
* callback fn
|
||||
*
|
||||
* Params:
|
||||
* Input: hostif, the host interface from the debug toolbox
|
||||
* cmdline, the command line used to call the image
|
||||
* state, the status block for the C lib
|
||||
*
|
||||
* Returns:
|
||||
* OK: an RDIError_* valuee
|
||||
*/
|
||||
extern int HostSysInit(
|
||||
const struct Dbg_HostosInterface *hostif, char **cmdline, hsys_state **state
|
||||
);
|
||||
|
||||
/*
|
||||
* Function: HostSysExit
|
||||
* Purpose: Close down the host side C library support
|
||||
*
|
||||
* Params:
|
||||
* Input: hstate, the status block for the C lib
|
||||
*
|
||||
* Returns: an RDIError_* valuee
|
||||
*/
|
||||
extern int HostSysExit(hsys_state *hstate);
|
||||
|
||||
/*
|
||||
* Function: HandleSysMessage
|
||||
* Purpose: Handle an incoming C library message as a callback
|
||||
*
|
||||
* Params:
|
||||
* Input: packet is the incoming data packet as described in devsw.h
|
||||
* hstate, the status block for the C lib
|
||||
*
|
||||
* Returns: an RDIError_* valuee
|
||||
*/
|
||||
extern int HandleSysMessage(Packet *packet, hsys_state* stateptr);
|
||||
|
||||
/*
|
||||
* Function: panic
|
||||
* Purpose: Print a fatal error message
|
||||
*
|
||||
* Params:
|
||||
* Input: format printf() style message describing the problem
|
||||
* ... extra arguments for printf().
|
||||
*
|
||||
* Returns: This routine does not return
|
||||
*
|
||||
* Post-conditions: Will have called exit(1);
|
||||
*/
|
||||
extern void panic(const char *format, ...);
|
||||
|
||||
#endif /* ndef angsd_hsys_h */
|
||||
|
||||
/* EOF hsys.h */
|
|
@ -1,367 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*
|
||||
* logging.c - methods for logging warnings, errors and trace info
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdarg.h> /* ANSI varargs support */
|
||||
|
||||
#ifdef TARGET
|
||||
# include "angel.h"
|
||||
# include "devconf.h"
|
||||
#else
|
||||
# include "host.h"
|
||||
#endif
|
||||
|
||||
#include "logging.h" /* Header file for this source code */
|
||||
|
||||
#ifndef UNUSED
|
||||
# define UNUSED(x) ((x)=(x))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* __rt_warning
|
||||
* ------------
|
||||
* This routine is provided as a standard method of generating
|
||||
* run-time system warnings. The actual action taken by this code can
|
||||
* be board or target application specific, e.g. internal logging,
|
||||
* debug message, etc.
|
||||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
# ifdef DEBUG_METHOD
|
||||
|
||||
# define STRINGIFY2(x) #x
|
||||
# define STRINGIFY(x) STRINGIFY2(x)
|
||||
# define DEBUG_METHOD_HEADER STRINGIFY(DEBUG_METHOD##.h)
|
||||
|
||||
# include DEBUG_METHOD_HEADER
|
||||
|
||||
# define METHOD_EXPAND_2(m, p, c) m##p(c)
|
||||
# define METHOD_EXPAND(m, p, c) METHOD_EXPAND_2(m, p, c)
|
||||
|
||||
# define CHAROUT(c) METHOD_EXPAND(DEBUG_METHOD, _PutChar, (c))
|
||||
# define PRE_DEBUG(l) METHOD_EXPAND(DEBUG_METHOD, _PreWarn, (l))
|
||||
# define POST_DEBUG(n) METHOD_EXPAND(DEBUG_METHOD, _PostWarn, (n))
|
||||
|
||||
# else
|
||||
# error Must define DEBUG_METHOD
|
||||
# endif
|
||||
|
||||
#endif /* def DEBUG */
|
||||
|
||||
/*
|
||||
* the guts of __rt_warning
|
||||
*/
|
||||
|
||||
#pragma no_check_stack
|
||||
#ifdef DEBUG
|
||||
|
||||
static const char hextab[] = "0123456789ABCDEF";
|
||||
|
||||
/*
|
||||
* If debugging, then we break va_warn into sub-functions which
|
||||
* allow us to get an easy breakpoint on the formatted string
|
||||
*/
|
||||
static int va_warn0(char *format, va_list args)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
while ((format != NULL) && (*format != '\0'))
|
||||
{
|
||||
if (*format == '%')
|
||||
{
|
||||
char fch = *(++format); /* get format character (skipping '%') */
|
||||
int ival; /* holder for integer arguments */
|
||||
char *string; /* holder for string arguments */
|
||||
int width = 0; /* No field width by default */
|
||||
int padzero = FALSE; /* By default we pad with spaces */
|
||||
|
||||
/*
|
||||
* Check if the format has a width specified. NOTE: We do
|
||||
* not use the "isdigit" function here, since it will
|
||||
* require run-time support. The current ARM Ltd header
|
||||
* defines "isdigit" as a macro, that uses a fixed
|
||||
* character description table.
|
||||
*/
|
||||
if ((fch >= '0') && (fch <= '9'))
|
||||
{
|
||||
if (fch == '0')
|
||||
{
|
||||
/* Leading zeroes padding */
|
||||
padzero = TRUE;
|
||||
fch = *(++format);
|
||||
}
|
||||
|
||||
while ((fch >= '0') && (fch <= '9'))
|
||||
{
|
||||
width = ((width * 10) + (fch - '0'));
|
||||
fch = *(++format);
|
||||
}
|
||||
}
|
||||
|
||||
if (fch == 'l')
|
||||
/* skip 'l' in "%lx", etc. */
|
||||
fch = *(++format);
|
||||
|
||||
switch (fch)
|
||||
{
|
||||
case 'c':
|
||||
/* char */
|
||||
ival = va_arg(args, int);
|
||||
CHAROUT((char)ival);
|
||||
len++;
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
case 'X':
|
||||
{
|
||||
/* hexadecimal */
|
||||
unsigned int uval = va_arg(args, unsigned int);
|
||||
int loop;
|
||||
|
||||
UNUSED(uval);
|
||||
|
||||
if ((width == 0) || (width > 8))
|
||||
width = 8;
|
||||
|
||||
for(loop = (width * 4); (loop != 0); loop -= 4)
|
||||
{
|
||||
CHAROUT(hextab[(uval >> (loop - 4)) & 0xF]);
|
||||
len++;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
/* decimal */
|
||||
ival = va_arg(args, int);
|
||||
|
||||
if (ival < 0)
|
||||
{
|
||||
ival = -ival;
|
||||
CHAROUT('-');
|
||||
len++;
|
||||
}
|
||||
|
||||
if (ival == 0)
|
||||
{
|
||||
CHAROUT('0');
|
||||
len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* The simplest method of displaying numbers is
|
||||
* to provide a small recursive routine, that
|
||||
* nests until the most-significant digit is
|
||||
* reached, and then falls back out displaying
|
||||
* individual digits. However, we want to avoid
|
||||
* using recursive code within the lo-level
|
||||
* parts of Angel (to minimise the stack
|
||||
* usage). The following number conversion is a
|
||||
* non-recursive solution.
|
||||
*/
|
||||
char buffer[16]; /* stack space used to hold number */
|
||||
int count = 0; /* pointer into buffer */
|
||||
|
||||
/*
|
||||
* Place the conversion into the buffer in
|
||||
* reverse order:
|
||||
*/
|
||||
while (ival != 0)
|
||||
{
|
||||
buffer[count++] = ('0' + ((unsigned int)ival % 10));
|
||||
ival = ((unsigned int)ival / 10);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if we are placing the data in a
|
||||
* fixed width field:
|
||||
*/
|
||||
if (width != 0)
|
||||
{
|
||||
width -= count;
|
||||
|
||||
for (; (width != 0); width--)
|
||||
{
|
||||
CHAROUT(padzero ? '0': ' ');
|
||||
len++;
|
||||
}
|
||||
}
|
||||
|
||||
/* then display the buffer in reverse order */
|
||||
for (; (count != 0); count--)
|
||||
{
|
||||
CHAROUT(buffer[count - 1]);
|
||||
len++;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 's':
|
||||
/* string */
|
||||
string = va_arg(args, char *);
|
||||
|
||||
/* we only need this test once */
|
||||
if (string != NULL)
|
||||
/* whilst we check this for every character */
|
||||
while (*string)
|
||||
{
|
||||
CHAROUT(*string);
|
||||
len++;
|
||||
string++;
|
||||
|
||||
/*
|
||||
* NOTE: We do not use "*string++" as the macro
|
||||
* parameter, since we do not know how many times
|
||||
*the parameter may be expanded within the macro.
|
||||
*/
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '\0':
|
||||
/*
|
||||
* string terminated by '%' character, bodge things
|
||||
* to prepare for default "format++" below
|
||||
*/
|
||||
format--;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
/* just display the character */
|
||||
CHAROUT(*format);
|
||||
len++;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
format++; /* step over format character */
|
||||
}
|
||||
else
|
||||
{
|
||||
CHAROUT(*format);
|
||||
len++;
|
||||
format++;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* this routine is simply here as a good breakpoint for dumping msg -
|
||||
* can be used by DEBUG_METHOD macros or functions, if required.
|
||||
*/
|
||||
# ifdef DEBUG_NEED_VA_WARN1
|
||||
static void va_warn1(int len, char *msg)
|
||||
{
|
||||
UNUSED(len); UNUSED(msg);
|
||||
}
|
||||
# endif
|
||||
|
||||
void va_warn(WarnLevel level, char *format, va_list args)
|
||||
{
|
||||
int len;
|
||||
|
||||
if ( PRE_DEBUG( level ) )
|
||||
{
|
||||
len = va_warn0(format, args);
|
||||
POST_DEBUG( len );
|
||||
}
|
||||
}
|
||||
|
||||
#else /* ndef DEBUG */
|
||||
|
||||
void va_warn(WarnLevel level, char *format, va_list args)
|
||||
{
|
||||
UNUSED(level); UNUSED(format); UNUSED(args);
|
||||
}
|
||||
|
||||
#endif /* ... else ndef(DEBUG) ... */
|
||||
#pragma check_stack
|
||||
|
||||
#pragma no_check_stack
|
||||
void __rt_warning(char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
/*
|
||||
* For a multi-threaded system we should provide a lock at this point
|
||||
* to ensure that the warning messages are sequenced properly.
|
||||
*/
|
||||
|
||||
va_start(args, format);
|
||||
va_warn(WL_WARN, format, args);
|
||||
va_end(args);
|
||||
|
||||
return;
|
||||
}
|
||||
#pragma check_stack
|
||||
|
||||
#ifdef TARGET
|
||||
|
||||
#pragma no_check_stack
|
||||
void __rt_uninterruptable_loop( void ); /* in suppasm.s */
|
||||
|
||||
void __rt_error(char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
|
||||
/* Display warning message */
|
||||
va_warn(WL_ERROR, format, args);
|
||||
|
||||
__rt_uninterruptable_loop();
|
||||
|
||||
va_end(args);
|
||||
return;
|
||||
}
|
||||
#pragma check_stack
|
||||
|
||||
#endif /* def TARGET */
|
||||
|
||||
#ifdef DO_TRACE
|
||||
|
||||
static bool trace_on = FALSE; /* must be set true in debugger if req'd */
|
||||
|
||||
#pragma no_check_stack
|
||||
void __rt_trace(char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
/*
|
||||
* For a multi-threaded system we should provide a lock at this point
|
||||
* to ensure that the warning messages are sequenced properly.
|
||||
*/
|
||||
|
||||
if (trace_on)
|
||||
{
|
||||
va_start(args, format);
|
||||
va_warn(WL_TRACE, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
#pragma check_stack
|
||||
|
||||
#endif /* def DO_TRACE */
|
||||
|
||||
|
||||
/* EOF logging.c */
|
|
@ -1,119 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*
|
||||
* logging.h - methods for logging warnings, errors and trace info
|
||||
*/
|
||||
|
||||
#ifndef angel_logging_h
|
||||
#define angel_logging_h
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
/*
|
||||
* __rt_warning
|
||||
* ------------
|
||||
* Provides a standard method of generating run-time system
|
||||
* warnings. The actual action taken by this code can be board or
|
||||
* target application specific, e.g. internal logging, debug message,
|
||||
* etc.
|
||||
*/
|
||||
extern void __rt_warning(char *format, ...);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* __rt_error
|
||||
* ----------
|
||||
* Raise an internal Angel error. The parameters are passed directly
|
||||
* to "__rt_warning" for display, and the code then raises a debugger
|
||||
* event and stops the target processing.
|
||||
*/
|
||||
extern void __rt_error(char *format, ...);
|
||||
|
||||
/*
|
||||
* Some macros for debugging and warning messages
|
||||
*/
|
||||
|
||||
typedef enum WarnLevel {
|
||||
WL_TRACE,
|
||||
WL_WARN,
|
||||
WL_ERROR
|
||||
} WarnLevel;
|
||||
|
||||
void va_warn(WarnLevel level, char *format, va_list args);
|
||||
|
||||
#ifdef _WINGDI_
|
||||
/* stupidity in MSVC <wingdi.h> (in <windows.h> in <winsock.h>) */
|
||||
# undef ERROR
|
||||
#endif
|
||||
|
||||
#ifndef ERROR
|
||||
# define ERROR_FORMAT "Error \"%s\" in %s at line %d\n"
|
||||
# define ERROR(e) __rt_error(ERROR_FORMAT, (e), __FILE__, __LINE__)
|
||||
#endif
|
||||
|
||||
#ifndef ASSERT
|
||||
# ifdef ASSERTIONS_ENABLED
|
||||
# define ASSERT(x, y) ((x) ? (void)(0) : ERROR((y)))
|
||||
# else
|
||||
# define ASSERT(x, y) ((void)(0))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef WARN
|
||||
# ifdef ASSERTIONS_ENABLED
|
||||
# define WARN_FORMAT "Warning \"%s\" in %s at line %d\n"
|
||||
# define WARN(w) __rt_warning(WARN_FORMAT, (w), __FILE__, __LINE__)
|
||||
# else
|
||||
# define WARN(w) ((void)(0))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef NO_INFO_MESSAGES
|
||||
# define __rt_info (void)
|
||||
# ifndef INFO
|
||||
# define INFO(w)
|
||||
# endif
|
||||
#else
|
||||
# define __rt_info __rt_warning
|
||||
# ifndef INFO
|
||||
# ifdef DEBUG
|
||||
# define INFO(w) __rt_warning("%s\n", (w))
|
||||
# else
|
||||
# define INFO(w) ((void)(0))
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(DEBUG) && !defined(NO_IDLE_CHITCHAT)
|
||||
# ifndef DO_TRACE
|
||||
# define DO_TRACE (1)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef DO_TRACE
|
||||
extern void __rt_trace(char *format, ...);
|
||||
#endif
|
||||
|
||||
#ifndef TRACE
|
||||
# ifdef DO_TRACE
|
||||
# define TRACE(w) __rt_trace("%s ", (w))
|
||||
# else
|
||||
# define TRACE(w) ((void)(0))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* ndef angel_logging_h */
|
||||
|
||||
/* EOF logging.h */
|
|
@ -1,280 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*
|
||||
* msgbuild.c - utilities for assembling and interpreting ADP messages
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdarg.h> /* ANSI varargs support */
|
||||
|
||||
#ifdef TARGET
|
||||
# include "angel.h"
|
||||
# include "devconf.h"
|
||||
#else
|
||||
# include "host.h"
|
||||
# include "hostchan.h"
|
||||
#endif
|
||||
|
||||
#include "channels.h"
|
||||
#include "buffers.h"
|
||||
#include "endian.h" /* Endianness support macros */
|
||||
#include "msgbuild.h" /* Header file for this source code */
|
||||
|
||||
#ifndef UNUSED
|
||||
# define UNUSED(x) ((x)=(x))
|
||||
#endif
|
||||
|
||||
#ifndef TARGET
|
||||
|
||||
extern unsigned int Armsd_BufferSize;
|
||||
|
||||
#endif /* ndef TARGET */
|
||||
|
||||
|
||||
unsigned int vmsgbuild(unsigned char *buffer, const char *format, va_list args)
|
||||
{
|
||||
unsigned int blen = 0;
|
||||
int ch;
|
||||
|
||||
/* Step through the format string */
|
||||
while ((ch = *format++) != '\0')
|
||||
{
|
||||
if (ch != '%')
|
||||
{
|
||||
if (buffer != NULL)
|
||||
*buffer++ = (unsigned char)ch;
|
||||
|
||||
blen++;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (ch = *format++)
|
||||
{
|
||||
case 'w':
|
||||
case 'W':
|
||||
/* 32bit pointer */
|
||||
case 'p':
|
||||
case 'P':
|
||||
{
|
||||
/* 32bit word / 32bit pointer */
|
||||
unsigned int na = va_arg(args, unsigned int);
|
||||
|
||||
if (buffer != NULL)
|
||||
{
|
||||
PUT32LE(buffer, na);
|
||||
buffer += sizeof(unsigned int);
|
||||
}
|
||||
|
||||
blen += sizeof(unsigned int);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'h':
|
||||
case 'H':
|
||||
{
|
||||
/* 16bit value */
|
||||
unsigned int na = va_arg(args, unsigned int);
|
||||
|
||||
if (buffer != NULL)
|
||||
{
|
||||
PUT16LE(buffer, na);
|
||||
buffer += sizeof(unsigned short);
|
||||
}
|
||||
|
||||
blen += sizeof(unsigned short);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'c':
|
||||
case 'C':
|
||||
case 'b':
|
||||
case 'B':
|
||||
/* 8bit character / 8bit byte */
|
||||
ch = va_arg(args, int);
|
||||
|
||||
/*
|
||||
* XXX
|
||||
*
|
||||
* fall through to the normal character processing
|
||||
*/
|
||||
|
||||
case '%':
|
||||
default:
|
||||
/* normal '%' character, or a different normal character */
|
||||
if (buffer != NULL)
|
||||
*buffer++ = (unsigned char)ch;
|
||||
|
||||
blen++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return blen;
|
||||
}
|
||||
|
||||
/*
|
||||
* msgbuild
|
||||
* --------
|
||||
* Simple routine to aid in construction of Angel messages. See the
|
||||
* "msgbuild.h" header file for a detailed description of the operation
|
||||
* of this routine.
|
||||
*/
|
||||
unsigned int msgbuild(unsigned char *buffer, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
unsigned int blen;
|
||||
|
||||
va_start(args, format);
|
||||
blen = vmsgbuild(buffer, format, args);
|
||||
va_end(args);
|
||||
|
||||
return blen;
|
||||
}
|
||||
|
||||
#if !defined(JTAG_ADP_SUPPORTED) && !defined(MSG_UTILS_ONLY)
|
||||
/*
|
||||
* This routine allocates a buffer, puts the data supplied as
|
||||
* parameters into the buffer and sends the message. It does *NOT*
|
||||
* wait for a reply.
|
||||
*/
|
||||
extern int msgsend(ChannelID chan, const char *format,...)
|
||||
{
|
||||
unsigned int length;
|
||||
p_Buffer buffer;
|
||||
va_list args;
|
||||
# ifndef TARGET
|
||||
Packet *packet;
|
||||
|
||||
packet = DevSW_AllocatePacket(Armsd_BufferSize);
|
||||
buffer = packet->pk_buffer;
|
||||
# else
|
||||
buffer = angel_ChannelAllocBuffer(Angel_ChanBuffSize);
|
||||
# endif
|
||||
|
||||
if (buffer != NULL)
|
||||
{
|
||||
va_start(args, format);
|
||||
|
||||
length = vmsgbuild(BUFFERDATA(buffer), format, args);
|
||||
|
||||
# ifdef TARGET
|
||||
angel_ChannelSend(CH_DEFAULT_DEV, chan, buffer, length);
|
||||
# else
|
||||
packet->pk_length = length;
|
||||
Adp_ChannelWrite(chan, packet);
|
||||
# endif
|
||||
|
||||
va_end(args);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* ndef JTAG_ADP_SUPPORTED && ndef MSG_UTILS_ONLY */
|
||||
|
||||
/*
|
||||
* unpack_message
|
||||
* --------------
|
||||
*/
|
||||
extern unsigned int unpack_message(unsigned char *buffer, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
unsigned int blen = 0;
|
||||
int ch;
|
||||
char *chp = NULL;
|
||||
|
||||
va_start(args, format);
|
||||
|
||||
/* Step through the format string. */
|
||||
while ((ch = *format++) != '\0')
|
||||
{
|
||||
if (ch != '%')
|
||||
{
|
||||
if (buffer != NULL)
|
||||
ch = (unsigned char)*buffer++;
|
||||
|
||||
blen++;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (ch = *format++)
|
||||
{
|
||||
case 'w':
|
||||
case 'W':
|
||||
{
|
||||
/* 32bit word. */
|
||||
unsigned int *nap = va_arg(args, unsigned int*);
|
||||
|
||||
if (buffer != NULL)
|
||||
{
|
||||
*nap = PREAD32(LE, buffer);
|
||||
buffer += sizeof(unsigned int);
|
||||
}
|
||||
|
||||
blen += sizeof(unsigned int);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'h':
|
||||
case 'H':
|
||||
{
|
||||
/* 16bit value. */
|
||||
unsigned int *nap = va_arg(args, unsigned int*);
|
||||
|
||||
if (buffer != NULL)
|
||||
{
|
||||
*nap = PREAD16(LE,buffer);
|
||||
buffer += sizeof(unsigned short);
|
||||
}
|
||||
|
||||
blen += sizeof(unsigned short);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'c':
|
||||
case 'C':
|
||||
case 'b':
|
||||
case 'B':
|
||||
/* 8-bit character, or 8-bit byte */
|
||||
chp = va_arg(args, char*);
|
||||
|
||||
/*
|
||||
* XXX
|
||||
*
|
||||
* fall through to the normal character processing.
|
||||
*/
|
||||
|
||||
case '%':
|
||||
default:
|
||||
/* normal '%' character, or a different normal character */
|
||||
if (buffer != NULL)
|
||||
*chp = (unsigned char)*buffer++;
|
||||
|
||||
blen++;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
return(blen);
|
||||
}
|
||||
|
||||
|
||||
/* EOF msgbuild.c */
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*
|
||||
* msgbuild.h - utilities for assembling and interpreting ADP messages
|
||||
*/
|
||||
|
||||
#ifndef angel_msgbuild_h
|
||||
#define angel_msgbuild_h
|
||||
#include <stdarg.h>
|
||||
#include "channels.h"
|
||||
|
||||
/*
|
||||
* msgbuild
|
||||
* --------
|
||||
* We use a "varargs" function to enable a description of how the
|
||||
* final message should look to be provided. We use a function rather
|
||||
* than in-line macros to keep the size of Angel small.
|
||||
*
|
||||
* The "buffer" pointer is the starting point from where the data will
|
||||
* be written. Note: If a NULL pointer is passed then no data will be
|
||||
* written, but the size information will be returned. This allows
|
||||
* code to call this routine with a NULL "buffer" pointer to ascertain
|
||||
* whether the pointer they are passing contains enough space for the
|
||||
* message being constructed.
|
||||
*
|
||||
* The "format" string should contain sequences of the following
|
||||
* tokens:
|
||||
* %w - insert 32bit word value
|
||||
* %p - insert 32bit target pointer value
|
||||
* %h - insert 16bit value
|
||||
* %b - insert 8bit byte value
|
||||
*
|
||||
* The return parameter is the final byte length of the data written.
|
||||
*/
|
||||
unsigned int msgbuild(unsigned char *buffer, const char *format, ...);
|
||||
unsigned int vmsgbuild(unsigned char *buffer, const char *format,
|
||||
va_list args);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* msgsend
|
||||
* -------
|
||||
* As for msgbuild except that it allocates a buffer, formats the data as
|
||||
* for msgbuild and transmits the packet. Returns 0 if successful non 0 if ot
|
||||
* fails.
|
||||
* Not for use on cooked channels e.g. debug channels only.
|
||||
*/
|
||||
extern int msgsend(ChannelID chan, const char *format, ...);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Unpack_message
|
||||
* --------------
|
||||
* This basically does the opposite of msg_build, it takes a message, and
|
||||
* a scanf type format string (but much cut down functionality) and returns
|
||||
* the arguments in the message.
|
||||
*/
|
||||
extern unsigned int unpack_message(unsigned char *buffer, const char *format, ...);
|
||||
|
||||
#endif /* ndef angel_msgbuild_h */
|
||||
|
||||
/* EOF msgbuild.h */
|
|
@ -1,323 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*
|
||||
* Project: ANGEL
|
||||
*
|
||||
* Title: Parameter negotiation utility functions
|
||||
*/
|
||||
|
||||
#include "params.h"
|
||||
|
||||
#include "endian.h"
|
||||
#include "logging.h"
|
||||
|
||||
|
||||
/*
|
||||
* Function: Angel_FindParam
|
||||
* Purpose: find the value of a given parameter from a config.
|
||||
*
|
||||
* see params.h for details
|
||||
*/
|
||||
bool Angel_FindParam( ADP_Parameter type,
|
||||
const ParameterConfig *config,
|
||||
unsigned int *value )
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for ( i = 0; i < config->num_parameters; ++i )
|
||||
if ( config->param[i].type == type )
|
||||
{
|
||||
*value = config->param[i].value;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
#if !defined(TARGET) || !defined(MINIMAL_ANGEL) || MINIMAL_ANGEL == 0
|
||||
|
||||
ParameterList *Angel_FindParamList( const ParameterOptions *options,
|
||||
ADP_Parameter type )
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for ( i = 0; i < options->num_param_lists; ++i )
|
||||
if ( options->param_list[i].type == type )
|
||||
return &options->param_list[i];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
#if defined(TARGET) || defined(TEST_PARAMS)
|
||||
/*
|
||||
* Function: Angel_MatchParams
|
||||
* Purpose: find a configuration from the requested options which is
|
||||
* the best match from the supported options.
|
||||
*
|
||||
* see params.h for details
|
||||
*/
|
||||
const ParameterConfig *Angel_MatchParams( const ParameterOptions *requested,
|
||||
const ParameterOptions *supported )
|
||||
{
|
||||
static Parameter chosen_params[AP_NUM_PARAMS];
|
||||
static ParameterConfig chosen_config = {
|
||||
AP_NUM_PARAMS,
|
||||
chosen_params
|
||||
};
|
||||
unsigned int i;
|
||||
|
||||
ASSERT( requested != NULL, "requested is NULL" );
|
||||
ASSERT( requested != NULL, "requested is NULL" );
|
||||
ASSERT( supported->num_param_lists <= AP_NUM_PARAMS, "supp_num too big" );
|
||||
|
||||
if ( requested->num_param_lists > supported->num_param_lists )
|
||||
{
|
||||
WARN( "req_num exceeds supp_num" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for ( i = 0; i < requested->num_param_lists; ++i )
|
||||
{
|
||||
bool match;
|
||||
unsigned int j;
|
||||
|
||||
const ParameterList *req_list = &requested->param_list[i];
|
||||
ADP_Parameter req_type = req_list->type;
|
||||
const ParameterList *sup_list = Angel_FindParamList(
|
||||
supported, req_type );
|
||||
|
||||
if ( sup_list == NULL )
|
||||
{
|
||||
#ifdef ASSERTIONS_ENABLED
|
||||
__rt_warning( "option %x not supported\n", req_type );
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for ( j = 0, match = FALSE;
|
||||
(j < req_list->num_options) && !match;
|
||||
++j
|
||||
)
|
||||
{
|
||||
unsigned int k;
|
||||
|
||||
for ( k = 0;
|
||||
(k < sup_list->num_options) && !match;
|
||||
++k
|
||||
)
|
||||
{
|
||||
if ( req_list->option[j] == sup_list->option[k] )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
__rt_info( "chose value %d for option %x\n",
|
||||
req_list->option[j], req_type );
|
||||
#endif
|
||||
match = TRUE;
|
||||
chosen_config.param[i].type = req_type;
|
||||
chosen_config.param[i].value = req_list->option[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !match )
|
||||
{
|
||||
#ifdef ASSERTIONS_ENABLED
|
||||
__rt_warning( "no match found for option %x\n", req_type );
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
chosen_config.num_parameters = i;
|
||||
INFO( "match succeeded" );
|
||||
return &chosen_config;
|
||||
}
|
||||
#endif /* defined(TARGET) || defined(TEST_PARAMS) */
|
||||
|
||||
|
||||
#if !defined(TARGET) || defined(TEST_PARAMS)
|
||||
/*
|
||||
* Function: Angel_StoreParam
|
||||
* Purpose: store the value of a given parameter to a config.
|
||||
*
|
||||
* see params.h for details
|
||||
*/
|
||||
bool Angel_StoreParam( ParameterConfig *config,
|
||||
ADP_Parameter type,
|
||||
unsigned int value )
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for ( i = 0; i < config->num_parameters; ++i )
|
||||
if ( config->param[i].type == type )
|
||||
{
|
||||
config->param[i].value = value;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
#endif /* !defined(TARGET) || defined(TEST_PARAMS) */
|
||||
|
||||
|
||||
#if defined(TARGET) || defined(LINK_RECOVERY) || defined(TEST_PARAMS)
|
||||
/*
|
||||
* Function: Angel_BuildParamConfigMessage
|
||||
* Purpose: write a parameter config to a buffer in ADP format.
|
||||
*
|
||||
* see params.h for details
|
||||
*/
|
||||
unsigned int Angel_BuildParamConfigMessage( unsigned char *buffer,
|
||||
const ParameterConfig *config )
|
||||
{
|
||||
unsigned char *start = buffer;
|
||||
unsigned int i;
|
||||
|
||||
PUT32LE( buffer, config->num_parameters );
|
||||
buffer += sizeof( word );
|
||||
|
||||
for ( i = 0; i < config->num_parameters; ++i )
|
||||
{
|
||||
PUT32LE( buffer, config->param[i].type );
|
||||
buffer += sizeof( word );
|
||||
PUT32LE( buffer, config->param[i].value );
|
||||
buffer += sizeof( word );
|
||||
}
|
||||
|
||||
return (buffer - start);
|
||||
}
|
||||
#endif /* defined(TARGET) || defined(LINK_RECOVERY) || defined(TEST_PARAMS) */
|
||||
|
||||
|
||||
#if !defined(TARGET) || defined(TEST_PARAMS)
|
||||
/*
|
||||
* Function: Angel_BuildParamOptionsMessage
|
||||
* Purpose: write a parameter Options to a buffer in ADP format.
|
||||
*
|
||||
* see params.h for details
|
||||
*/
|
||||
unsigned int Angel_BuildParamOptionsMessage( unsigned char *buffer,
|
||||
const ParameterOptions *options )
|
||||
{
|
||||
unsigned char *start = buffer;
|
||||
unsigned int i, j;
|
||||
|
||||
PUT32LE( buffer, options->num_param_lists );
|
||||
buffer += sizeof( word );
|
||||
|
||||
for ( i = 0; i < options->num_param_lists; ++i )
|
||||
{
|
||||
PUT32LE( buffer, options->param_list[i].type );
|
||||
buffer += sizeof( word );
|
||||
PUT32LE( buffer, options->param_list[i].num_options );
|
||||
buffer += sizeof( word );
|
||||
for ( j = 0; j < options->param_list[i].num_options; ++j )
|
||||
{
|
||||
PUT32LE( buffer, options->param_list[i].option[j] );
|
||||
buffer += sizeof( word );
|
||||
}
|
||||
}
|
||||
|
||||
return (buffer - start);
|
||||
}
|
||||
#endif /* !defined(TARGET) || defined(TEST_PARAMS) */
|
||||
|
||||
|
||||
#if !defined(TARGET) || defined(LINK_RECOVERY) || defined(TEST_PARAMS)
|
||||
/*
|
||||
* Function: Angel_ReadParamConfigMessage
|
||||
* Purpose: read a parameter config from a buffer where it is in ADP format.
|
||||
*
|
||||
* see params.h for details
|
||||
*/
|
||||
bool Angel_ReadParamConfigMessage( const unsigned char *buffer,
|
||||
ParameterConfig *config )
|
||||
{
|
||||
unsigned int word;
|
||||
unsigned int i;
|
||||
|
||||
word = GET32LE( buffer );
|
||||
buffer += sizeof( word );
|
||||
if ( word > config->num_parameters )
|
||||
{
|
||||
WARN( "not enough space" );
|
||||
return FALSE;
|
||||
}
|
||||
config->num_parameters = word;
|
||||
|
||||
for ( i = 0; i < config->num_parameters; ++i )
|
||||
{
|
||||
config->param[i].type = (ADP_Parameter)GET32LE( buffer );
|
||||
buffer += sizeof( word );
|
||||
config->param[i].value = GET32LE( buffer );
|
||||
buffer += sizeof( word );
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif /* !defined(TARGET) || defined(LINK_RECOVERY) || defined(TEST_PARAMS) */
|
||||
|
||||
|
||||
#if defined(TARGET) || defined(TEST_PARAMS)
|
||||
/*
|
||||
* Function: Angel_ReadParamOptionsMessage
|
||||
* Purpose: read a parameter options block from a buffer
|
||||
* where it is in ADP format.
|
||||
*
|
||||
* see params.h for details
|
||||
*/
|
||||
bool Angel_ReadParamOptionsMessage( const unsigned char *buffer,
|
||||
ParameterOptions *options )
|
||||
{
|
||||
unsigned int word;
|
||||
unsigned int i, j;
|
||||
|
||||
word = GET32LE( buffer );
|
||||
buffer += sizeof( word );
|
||||
if ( word > options->num_param_lists )
|
||||
{
|
||||
WARN( "not enough space" );
|
||||
return FALSE;
|
||||
}
|
||||
options->num_param_lists = word;
|
||||
|
||||
for ( i = 0; i < options->num_param_lists; ++i )
|
||||
{
|
||||
ParameterList *list = &options->param_list[i];
|
||||
|
||||
list->type = (ADP_Parameter)GET32LE( buffer );
|
||||
buffer += sizeof( word );
|
||||
word = GET32LE( buffer );
|
||||
buffer += sizeof( word );
|
||||
if ( word > list->num_options )
|
||||
{
|
||||
WARN( "not enough list space" );
|
||||
return FALSE;
|
||||
}
|
||||
list->num_options = word;
|
||||
|
||||
for ( j = 0; j < list->num_options; ++j )
|
||||
{
|
||||
list->option[j] = GET32LE( buffer );
|
||||
buffer += sizeof( word );
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif /* defined(TARGET) || defined(TEST_PARAMS) */
|
||||
|
||||
#endif /* !define(TARGET) || !defined(MINIMAL_ANGEL) || MINIMAL_ANGEL == 0 */
|
||||
|
||||
/* EOF params.c */
|
|
@ -1,179 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*
|
||||
* Project: ANGEL
|
||||
*
|
||||
* Title: Parameter negotiation structures and utilities
|
||||
*/
|
||||
|
||||
#ifndef angel_params_h
|
||||
#define angel_params_h
|
||||
|
||||
#include "angel.h"
|
||||
#include "adp.h"
|
||||
|
||||
#ifndef TARGET
|
||||
# include "host.h"
|
||||
#endif
|
||||
|
||||
/* A single parameter, with tag */
|
||||
typedef struct Parameter {
|
||||
ADP_Parameter type;
|
||||
unsigned int value;
|
||||
} Parameter;
|
||||
|
||||
/* A list of parameter values, with tag */
|
||||
typedef struct ParameterList {
|
||||
ADP_Parameter type;
|
||||
unsigned int num_options;
|
||||
unsigned int *option; /* points to array of values */
|
||||
} ParameterList;
|
||||
|
||||
/* A configuration of one or more parameters */
|
||||
typedef struct ParameterConfig {
|
||||
unsigned int num_parameters;
|
||||
Parameter *param; /* pointer to array of Parameters */
|
||||
} ParameterConfig;
|
||||
|
||||
/* A set of parameter options */
|
||||
typedef struct ParameterOptions {
|
||||
unsigned int num_param_lists;
|
||||
ParameterList *param_list; /* pointer to array of ParamLists */
|
||||
} ParameterOptions;
|
||||
|
||||
/*
|
||||
* Function: Angel_MatchParams
|
||||
* Purpose: find a configuration from the requested options which is
|
||||
* the best match from the supported options.
|
||||
*
|
||||
* Params:
|
||||
* Input: requested The offered set of parameters.
|
||||
* supported The supported set of parameters.
|
||||
*
|
||||
* Returns: ptr to config A match has been made, ptr to result
|
||||
* will remain valid until next call to
|
||||
* this function.
|
||||
* NULL Match not possible
|
||||
*/
|
||||
const ParameterConfig *Angel_MatchParams( const ParameterOptions *requested,
|
||||
const ParameterOptions *supported );
|
||||
|
||||
/*
|
||||
* Function: Angel_FindParam
|
||||
* Purpose: find the value of a given parameter from a config.
|
||||
*
|
||||
* Params:
|
||||
* Input: type parameter type to find
|
||||
* config config to search
|
||||
* Output: value parameter value if found
|
||||
*
|
||||
* Returns: TRUE parameter found
|
||||
* FALSE parameter not found
|
||||
*/
|
||||
bool Angel_FindParam( ADP_Parameter type,
|
||||
const ParameterConfig *config,
|
||||
unsigned int *value );
|
||||
|
||||
/*
|
||||
* Function: Angel_StoreParam
|
||||
* Purpose: store the value of a given parameter in a config.
|
||||
*
|
||||
* Params:
|
||||
* In/Out: config config to store in
|
||||
* Input: type parameter type to store
|
||||
* value parameter value if found
|
||||
*
|
||||
* Returns: TRUE parameter found and new value stored
|
||||
* FALSE parameter not found
|
||||
*/
|
||||
bool Angel_StoreParam( ParameterConfig *config,
|
||||
ADP_Parameter type,
|
||||
unsigned int value );
|
||||
|
||||
/*
|
||||
* Function: Angel_FindParamList
|
||||
* Purpose: find the parameter list of a given parameter from an options.
|
||||
*
|
||||
* Params:
|
||||
* Input: type parameter type to find
|
||||
* options options block to search
|
||||
*
|
||||
* Returns: pointer to list
|
||||
* NULL parameter not found
|
||||
*/
|
||||
ParameterList *Angel_FindParamList( const ParameterOptions *options,
|
||||
ADP_Parameter type );
|
||||
|
||||
/*
|
||||
* Function: Angel_BuildParamConfigMessage
|
||||
* Purpose: write a parameter config to a buffer in ADP format.
|
||||
*
|
||||
* Params:
|
||||
* Input: buffer where to write to
|
||||
* config the parameter config to write
|
||||
*
|
||||
* Returns: number of characters written to buffer
|
||||
*/
|
||||
unsigned int Angel_BuildParamConfigMessage( unsigned char *buffer,
|
||||
const ParameterConfig *config );
|
||||
|
||||
/*
|
||||
* Function: Angel_BuildParamOptionsMessage
|
||||
* Purpose: write a parameter Options to a buffer in ADP format.
|
||||
*
|
||||
* Params:
|
||||
* Input: buffer where to write to
|
||||
* options the options block to write
|
||||
*
|
||||
* Returns: number of characters written to buffer
|
||||
*/
|
||||
unsigned int Angel_BuildParamOptionsMessage( unsigned char *buffer,
|
||||
const ParameterOptions *options );
|
||||
|
||||
/*
|
||||
* Function: Angel_ReadParamConfigMessage
|
||||
* Purpose: read a parameter config from a buffer where it is in ADP format.
|
||||
*
|
||||
* Params:
|
||||
* Input: buffer where to read from
|
||||
* In/Out: config the parameter config to read to, which must
|
||||
* be set up on entry with a valid array, and
|
||||
* the size of the array in num_parameters.
|
||||
*
|
||||
* Returns: TRUE okay
|
||||
* FALSE not enough space in config
|
||||
*/
|
||||
bool Angel_ReadParamConfigMessage( const unsigned char *buffer,
|
||||
ParameterConfig *config );
|
||||
|
||||
/*
|
||||
* Function: Angel_ReadParamOptionsMessage
|
||||
* Purpose: read a parameter options from a buffer
|
||||
* where it is in ADP format.
|
||||
*
|
||||
* Params:
|
||||
* Input: buffer where to read from
|
||||
* In/Out: options the parameter options block to read to,
|
||||
* which must be set up on entry with a valid
|
||||
* array, and the size of the array in
|
||||
* num_parameters. Each param_list must
|
||||
* also be set up in the same way.
|
||||
*
|
||||
* Returns: TRUE okay
|
||||
* FALSE not enough space in options
|
||||
*/
|
||||
bool Angel_ReadParamOptionsMessage( const unsigned char *buffer,
|
||||
ParameterOptions *options );
|
||||
|
||||
#endif /* ndef angel_params_h */
|
||||
|
||||
/* EOF params.h */
|
|
@ -1,359 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/*-*-C-*-
|
||||
*
|
||||
*
|
||||
*
|
||||
* Project: ANGEL
|
||||
*
|
||||
* Title: Character reception engine
|
||||
*/
|
||||
|
||||
#include <stdarg.h> /* ANSI varargs support */
|
||||
#include "angel.h" /* Angel system definitions */
|
||||
#include "endian.h" /* Endian independant memory access macros */
|
||||
#include "crc.h" /* crc generation definitions and headers */
|
||||
#include "rxtx.h"
|
||||
#include "channels.h"
|
||||
#include "buffers.h"
|
||||
#ifdef TARGET
|
||||
# include "devdriv.h"
|
||||
#endif
|
||||
#include "logging.h"
|
||||
|
||||
static re_status unexp_stx(struct re_state *rxstate);
|
||||
static re_status unexp_etx(struct re_state *rxstate);
|
||||
|
||||
/* bitfield for the rx_engine state */
|
||||
typedef enum rx_state_flag{
|
||||
RST_STX,
|
||||
RST_TYP,
|
||||
RST_LEN,
|
||||
RST_DAT,
|
||||
RST_CRC,
|
||||
RST_ETX,
|
||||
RST_ESC = (0x1 << 0x3)
|
||||
} rx_state_flag;
|
||||
|
||||
void Angel_RxEngineInit(const struct re_config *rxconfig,
|
||||
struct re_state *rxstate)
|
||||
{
|
||||
rxstate->rx_state = RST_STX;
|
||||
rxstate->field_c = 0;
|
||||
rxstate->index = 0;
|
||||
rxstate->crc = 0;
|
||||
rxstate->error = RE_OKAY;
|
||||
rxstate->config = rxconfig;
|
||||
}
|
||||
|
||||
re_status Angel_RxEngine(unsigned char new_ch, struct data_packet *packet,
|
||||
struct re_state *rxstate)
|
||||
{
|
||||
/*
|
||||
* TODO: add the flow control bits in
|
||||
* Note: We test for the data field in a seperate case so we can
|
||||
* completely avoid entering the switch for most chars
|
||||
*/
|
||||
|
||||
/* see if we're expecting a escaped char */
|
||||
if ((rxstate->rx_state & RST_ESC) == RST_ESC)
|
||||
{
|
||||
/* unescape the char and unset the flag*/
|
||||
new_ch &= ~serial_ESCAPE;
|
||||
#ifdef DO_TRACE
|
||||
__rt_trace("rxe-echar-%2x ", new_ch);
|
||||
#endif
|
||||
rxstate->rx_state &= ~RST_ESC;
|
||||
}
|
||||
else if ( (1 << new_ch) & rxstate->config->esc_set )
|
||||
{
|
||||
/* see if the incoming char is a special one */
|
||||
if (new_ch == rxstate->config->esc)
|
||||
{
|
||||
#ifdef DO_TRACE
|
||||
__rt_trace("rxe-esc ");
|
||||
#endif
|
||||
rxstate->rx_state |= RST_ESC;
|
||||
return RS_IN_PKT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* must be a normal packet so do some unexpected etx/stx checking
|
||||
* we haven't been told to escape or received an escape so unless
|
||||
* we are expecting an stx or etx then we can take the unexpected
|
||||
* stx/etx trap
|
||||
*/
|
||||
if ((new_ch == (rxstate->config->stx)) && (rxstate->rx_state != RST_STX))
|
||||
return unexp_stx(rxstate);
|
||||
if ((new_ch == (rxstate->config->etx)) && (rxstate->rx_state != RST_ETX))
|
||||
return unexp_etx(rxstate);
|
||||
}
|
||||
}
|
||||
|
||||
if (rxstate->rx_state == RST_DAT)
|
||||
{
|
||||
/*
|
||||
* do this to speed up the common case, no real penalty for
|
||||
* other cases
|
||||
*/
|
||||
#ifdef DO_TRACE
|
||||
__rt_trace("rxe-dat ");
|
||||
#endif
|
||||
|
||||
rxstate->crc = crc32(&new_ch, 1, rxstate->crc);
|
||||
(packet->data)[rxstate->index++] = (unsigned int)new_ch & 0xff;
|
||||
|
||||
if (rxstate->index == packet->len)
|
||||
rxstate->rx_state = RST_CRC;
|
||||
|
||||
return RS_IN_PKT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now that the common case is out of the way we can test for everything
|
||||
* else without worrying quite so much about the speed, changing the
|
||||
* order to len,crc,stx,etx,typ might gain a tiny bit of speed but lets
|
||||
* leave that for the moment
|
||||
*/
|
||||
switch (rxstate->rx_state)
|
||||
{
|
||||
case RST_STX:
|
||||
if (new_ch == rxstate->config->stx)
|
||||
{
|
||||
rxstate->rx_state = RST_TYP;
|
||||
rxstate->error = RE_OKAY;
|
||||
rxstate->crc = startCRC32;
|
||||
rxstate->index = 0;
|
||||
return RS_IN_PKT;
|
||||
}
|
||||
else
|
||||
{
|
||||
rxstate->error = RE_OKAY;
|
||||
return RS_WAIT_PKT;
|
||||
}
|
||||
|
||||
case RST_TYP:
|
||||
packet->type = (DevChanID)new_ch;
|
||||
rxstate->rx_state = RST_LEN;
|
||||
rxstate->error = RE_OKAY;
|
||||
rxstate->field_c = 0; /* set up here for the length that follows */
|
||||
#ifdef DO_TRACE
|
||||
__rt_trace("rxe-type-%2x ", packet->type);
|
||||
#endif
|
||||
rxstate->crc = crc32(&new_ch, 1, rxstate->crc);
|
||||
|
||||
return RS_IN_PKT;
|
||||
|
||||
case RST_LEN:
|
||||
rxstate->crc = crc32(&new_ch, 1, rxstate->crc);
|
||||
|
||||
if (rxstate->field_c++ == 0)
|
||||
{
|
||||
/* first length byte */
|
||||
packet->len = ((unsigned int)new_ch) << 8;
|
||||
return RS_IN_PKT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* got the whole legth */
|
||||
packet->len |= new_ch;
|
||||
#ifdef DO_TRACE
|
||||
__rt_trace("rxe-len-%4x\n", packet->len);
|
||||
#endif
|
||||
|
||||
/* check that the length is ok */
|
||||
if (packet->len == 0)
|
||||
{
|
||||
/* empty pkt */
|
||||
rxstate->field_c = 0;
|
||||
rxstate->rx_state = RST_CRC;
|
||||
return RS_IN_PKT;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (packet->data == NULL)
|
||||
{
|
||||
/* need to alloc the data buffer */
|
||||
if (!rxstate->config->ba_callback(
|
||||
packet, rxstate->config->ba_data)) {
|
||||
rxstate->rx_state = RST_STX;
|
||||
rxstate->error = RE_INTERNAL;
|
||||
return RS_BAD_PKT;
|
||||
}
|
||||
}
|
||||
|
||||
if (packet->len > packet->buf_len)
|
||||
{
|
||||
/* pkt bigger than buffer */
|
||||
rxstate->field_c = 0;
|
||||
rxstate->rx_state = RST_STX;
|
||||
rxstate->error = RE_LEN;
|
||||
return RS_BAD_PKT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* packet ok */
|
||||
rxstate->field_c = 0;
|
||||
rxstate->rx_state = RST_DAT;
|
||||
return RS_IN_PKT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case RST_DAT:
|
||||
/* dummy case (dealt with earlier) */
|
||||
#ifdef ASSERTIONS_ENABLED
|
||||
__rt_warning("ERROR: hit RST_dat in switch\n");
|
||||
#endif
|
||||
rxstate->rx_state = RST_STX;
|
||||
rxstate->error = RE_INTERNAL;
|
||||
return RS_BAD_PKT;
|
||||
|
||||
case RST_CRC:
|
||||
if (rxstate->field_c == 0)
|
||||
packet->crc = 0;
|
||||
|
||||
packet->crc |= (new_ch & 0xFF) << ((3 - rxstate->field_c) * 8);
|
||||
rxstate->field_c++;
|
||||
|
||||
if (rxstate->field_c == 4)
|
||||
{
|
||||
/* last crc field */
|
||||
rxstate->field_c = 0;
|
||||
rxstate->rx_state = RST_ETX;
|
||||
#ifdef DO_TRACE
|
||||
__rt_trace("rxe-rcrc-%8x ", packet->crc);
|
||||
#endif
|
||||
}
|
||||
|
||||
return RS_IN_PKT;
|
||||
|
||||
case RST_ETX:
|
||||
if (new_ch == rxstate->config->etx)
|
||||
{
|
||||
#if defined(DEBUG) && !defined(NO_PKT_DATA)
|
||||
{
|
||||
int c;
|
||||
# ifdef DO_TRACE
|
||||
__rt_trace("\n");
|
||||
# endif
|
||||
__rt_info("RXE Data =");
|
||||
for (c=0; c < packet->len; c++)
|
||||
__rt_info("%02x", packet->data[c]);
|
||||
__rt_info("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* check crc */
|
||||
if (rxstate->crc == packet->crc)
|
||||
{
|
||||
/* crc ok */
|
||||
rxstate->rx_state = RST_STX;
|
||||
rxstate->field_c = 0;
|
||||
return RS_GOOD_PKT;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef ASSERTIONS_ENABLED
|
||||
__rt_warning("Bad crc, rx calculates it should be 0x%x\n", rxstate->crc);
|
||||
#endif
|
||||
rxstate->rx_state = RST_STX;
|
||||
rxstate->error = RE_CRC;
|
||||
return RS_BAD_PKT;
|
||||
}
|
||||
}
|
||||
else if (new_ch == rxstate->config->stx)
|
||||
return unexp_stx(rxstate);
|
||||
else
|
||||
{
|
||||
rxstate->rx_state = RST_STX;
|
||||
rxstate->error = RE_NETX;
|
||||
return RS_BAD_PKT;
|
||||
}
|
||||
|
||||
default:
|
||||
#ifdef ASSERTIONS_ENABLED
|
||||
__rt_warning("ERROR fell through rxengine\n");
|
||||
#endif
|
||||
rxstate->rx_state = RST_STX;
|
||||
rxstate->error = RE_INTERNAL;
|
||||
return RS_BAD_PKT;
|
||||
}
|
||||
}
|
||||
|
||||
static re_status unexp_stx(struct re_state *rxstate)
|
||||
{
|
||||
#ifdef ASSERTIONS_ENABLED
|
||||
__rt_warning("Unexpected stx\n");
|
||||
#endif
|
||||
rxstate->crc = startCRC32;
|
||||
rxstate->index = 0;
|
||||
rxstate->rx_state = RST_TYP;
|
||||
rxstate->error = RE_U_STX;
|
||||
rxstate->field_c = 0;
|
||||
return RS_BAD_PKT;
|
||||
}
|
||||
|
||||
static re_status unexp_etx(struct re_state *rxstate)
|
||||
{
|
||||
#ifdef ASSERTIONS_ENABLED
|
||||
__rt_warning("Unexpected etx, rxstate: index= 0x%2x, field_c=0x%2x, state=0x%2x\n", rxstate->index, rxstate->field_c, rxstate->rx_state);
|
||||
#endif
|
||||
rxstate->crc = 0;
|
||||
rxstate->index = 0;
|
||||
rxstate->rx_state = RST_STX;
|
||||
rxstate->error = RE_U_ETX;
|
||||
rxstate->field_c = 0;
|
||||
return RS_BAD_PKT;
|
||||
}
|
||||
|
||||
/*
|
||||
* This can be used as the buffer allocation callback for the rx engine,
|
||||
* and makes use of angel_DD_GetBuffer() [in devdrv.h].
|
||||
*
|
||||
* Saves duplicating this callback function in every device driver that
|
||||
* uses the rx engine.
|
||||
*
|
||||
* Note that this REQUIRES that the device id is installed as ba_data
|
||||
* in the rx engine config structure for the driver.
|
||||
*/
|
||||
bool angel_DD_RxEng_BufferAlloc( struct data_packet *packet, void *cb_data )
|
||||
{
|
||||
#ifdef TARGET
|
||||
DeviceID devid = (DeviceID)cb_data;
|
||||
#else
|
||||
IGNORE(cb_data);
|
||||
#endif
|
||||
|
||||
if ( packet->type < DC_NUM_CHANNELS )
|
||||
{
|
||||
/* request a buffer down from the channels layer */
|
||||
#ifdef TARGET
|
||||
packet->data = angel_DD_GetBuffer( devid, packet->type,
|
||||
packet->len );
|
||||
#else
|
||||
packet->data = malloc(packet->len);
|
||||
#endif
|
||||
if ( packet->data == NULL )
|
||||
return FALSE;
|
||||
else
|
||||
{
|
||||
packet->buf_len = packet->len;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* bad type field */
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* EOF rx.c */
|
|
@ -1,261 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/*-*-C-*-
|
||||
*
|
||||
*
|
||||
*
|
||||
* Project: ANGEL
|
||||
*
|
||||
* Title: Definitions required for the rx and tx engines
|
||||
*/
|
||||
|
||||
#ifndef angel_rxtx_h
|
||||
#define angel_rxtx_h
|
||||
|
||||
|
||||
/*
|
||||
* we need a definition for bool, which is "system" dependent
|
||||
*/
|
||||
#ifdef TARGET
|
||||
# include "angel.h"
|
||||
#else
|
||||
# include "host.h"
|
||||
#endif
|
||||
|
||||
#include "devclnt.h"
|
||||
|
||||
/* return status codes for the rx engine */
|
||||
typedef enum re_status {
|
||||
RS_WAIT_PKT,
|
||||
RS_IN_PKT,
|
||||
RS_BAD_PKT,
|
||||
RS_GOOD_PKT
|
||||
} re_status;
|
||||
|
||||
/* return status codes for the tx engine */
|
||||
typedef enum te_status {
|
||||
TS_IDLE,
|
||||
TS_IN_PKT,
|
||||
TS_DONE_PKT
|
||||
} te_status;
|
||||
|
||||
|
||||
/*
|
||||
* required serial definitions, they should all be <32, refer to the
|
||||
* re_config struct comments for more details
|
||||
*/
|
||||
#define serial_STX (0x1c) /* data packet start */
|
||||
#define serial_ETX (0x1d) /* packet end */
|
||||
#define serial_ESC (0x1b) /* standard escape character */
|
||||
#define serial_XON (0x11) /* software flow control - enable transmission */
|
||||
#define serial_XOFF (0x13) /* software flow control - disable transmission */
|
||||
|
||||
/*
|
||||
* All other characters are transmitted clean. If any of the above
|
||||
* characters need to be transmitted as part of the serial data stream
|
||||
* then the character will be preceded by the "serial_ESC" character,
|
||||
* and then the required character transmitted (OR-ed with the
|
||||
* "serial_ESCAPE" value, to ensure that the serial stream never has
|
||||
* any of the exceptional characters generated by data transfers).
|
||||
*/
|
||||
|
||||
#define serial_ESCAPE (0x40) /* OR-ed with escaped characters */
|
||||
|
||||
/* bad packet error codes */
|
||||
typedef enum re_error {
|
||||
RE_OKAY,
|
||||
RE_U_STX,
|
||||
RE_U_ETX,
|
||||
RE_LEN,
|
||||
RE_CRC,
|
||||
RE_NETX,
|
||||
RE_INTERNAL
|
||||
} re_error;
|
||||
|
||||
/* a decoded packet */
|
||||
struct data_packet {
|
||||
unsigned short buf_len; /* should be set by caller */
|
||||
DevChanID type; /* valid when status is RS_GOOD_PKT */
|
||||
unsigned short len; /* --"-- */
|
||||
unsigned int crc; /* crc for the unescaped pkt */
|
||||
unsigned char *data; /* should be set by caller */
|
||||
};
|
||||
|
||||
/*
|
||||
* Purpose: typedef for flow control function
|
||||
*
|
||||
* Params:
|
||||
* Input: fc_char the flow control character in question
|
||||
* In/Out: cb_data callback data as set in the fc_data
|
||||
* field of re_config, typically device id
|
||||
*
|
||||
* This callback would tpyically respond to received XON and XOFF
|
||||
* characters by controlling the transmit side of the device.
|
||||
*/
|
||||
typedef void (*fc_cb_func)(char fc_char, void *cb_data);
|
||||
|
||||
|
||||
/*
|
||||
* Purpose: typedef for the function to alloc the data buffer
|
||||
*
|
||||
* Params:
|
||||
* In/Out: packet the data packet: len and type will be set on
|
||||
* entry, and buf_len and data should
|
||||
* be set by this routine if successful.
|
||||
* cb_data callback data as set in the ba_data
|
||||
* field of re_config, typically device id
|
||||
*
|
||||
* Returns: TRUE buffer allocated okay
|
||||
* FALSE couldn't allocate buffer of required size
|
||||
* for given type
|
||||
*
|
||||
* This callback should attempt to acquire a buffer for the data portion
|
||||
* of the packet which is currently being received, based on the len and
|
||||
* type fields supplied in packet.
|
||||
*
|
||||
* angel_DD_RxEng_BufferAlloc() is supplied for use as this callback,
|
||||
* and will be sufficient for most devices.
|
||||
*/
|
||||
typedef bool (*BufferAlloc_CB_Fn)(struct data_packet *packet, void *cb_data);
|
||||
|
||||
|
||||
/*
|
||||
* The static info needed by the engine, may vary per device.
|
||||
*
|
||||
* fc_set and esc_set are bitmaps, e.g. bit 3 == charcode 3 == ASCII ETX.
|
||||
* Thus any of the first 32 charcodes can be set for flow control or to
|
||||
* be escaped.
|
||||
*
|
||||
* Note that esc_set should include all of fc_set, and should have bits
|
||||
* set for stx, etx and esc, as a minimum.
|
||||
*
|
||||
* If character codes > 31 need to be used then fc_set and esc_set
|
||||
* and their handling can be extended to use arrays and bit manipulation
|
||||
* macros, potentially up to the full 256 possible chars.
|
||||
*
|
||||
* Note too that this could/should be shared with the tx engine.
|
||||
*/
|
||||
|
||||
struct re_config {
|
||||
unsigned char stx; /* the STX char for this device */
|
||||
unsigned char etx; /* the ETX --"-- */
|
||||
unsigned char esc; /* the ESC --"-- */
|
||||
unsigned int fc_set; /* bitmap of flow control chars */
|
||||
unsigned int esc_set; /* bitmap of special chars */
|
||||
fc_cb_func fc_callback; /* flow control callback func */
|
||||
void *fc_data; /* data to pass to fc_callback */
|
||||
BufferAlloc_CB_Fn ba_callback; /* buffer alloc callback */
|
||||
void *ba_data; /* data to pass to ba_calback */
|
||||
};
|
||||
|
||||
/* the dynamic info needed by the rx engine */
|
||||
struct re_state {
|
||||
unsigned char rx_state; /* 3 bits pkt state, 1 prepro state */
|
||||
unsigned short field_c; /* chars left in current field */
|
||||
unsigned short index; /* index into buffer */
|
||||
unsigned int crc; /* crc accumulator */
|
||||
re_error error; /* valid only if status is RS_BAD_PKT */
|
||||
const struct re_config *config; /* pointer to static config */
|
||||
};
|
||||
|
||||
/* dynamic state info needed by the tx engine */
|
||||
struct te_state {
|
||||
unsigned short field_c; /* position in current field */
|
||||
unsigned char tx_state; /* encodes n,e, and f (2+1+2=5 bits) */
|
||||
unsigned char encoded; /* escape-encoded char for transmission */
|
||||
const struct re_config *config; /* pointer to static config */
|
||||
unsigned int crc; /* space for CRC (before escaping) */
|
||||
};
|
||||
|
||||
/*
|
||||
* Function: Angel_RxEngineInit
|
||||
* Purpose: Initialise state (during device init) for engine.
|
||||
*
|
||||
* Params:
|
||||
* Input: config static config info
|
||||
* In/Out: state internal state
|
||||
*/
|
||||
|
||||
void Angel_RxEngineInit(const struct re_config *config,
|
||||
struct re_state *state);
|
||||
|
||||
/*
|
||||
* Function: Angel_RxEngine
|
||||
* Purpose: Rx Engine for character-based devices
|
||||
*
|
||||
* Params:
|
||||
* Input: new_ch the latest character
|
||||
*
|
||||
* In/Out: packet details of packet
|
||||
* packet.buf_len and packet.data must
|
||||
* be set on entry!
|
||||
* state internal state, intially set by
|
||||
* angel_RxEngineInit()
|
||||
*
|
||||
* Returns: re_status (see above)
|
||||
*
|
||||
*/
|
||||
|
||||
re_status Angel_RxEngine(unsigned char new_ch, struct data_packet *packet,
|
||||
struct re_state *state);
|
||||
|
||||
/*
|
||||
* This can be used as the buffer allocation callback for the rx engine,
|
||||
* and will make use of angel_DD_GetBuffer() [in devdrv.h].
|
||||
*
|
||||
* Saves duplicating this callback function in every device driver that
|
||||
* uses the rx engine.
|
||||
*
|
||||
* Note that this REQUIRES that the device id is installed as ba_data
|
||||
* in the rx engine config structure for the driver.
|
||||
*/
|
||||
bool angel_DD_RxEng_BufferAlloc( struct data_packet *packet, void *cb_data );
|
||||
|
||||
/*
|
||||
* Function: Angel_TxEngineInit
|
||||
* Purpose: Set up tx engine at start of new packet, calculate CRC etc.
|
||||
* (This should perform the actions described under
|
||||
* "Initialisation" above)
|
||||
*
|
||||
* Params:
|
||||
* Input: config static config info
|
||||
* packet the packet to transmit
|
||||
* In/Out: state internal state
|
||||
*/
|
||||
|
||||
void Angel_TxEngineInit(const struct re_config *config,
|
||||
const struct data_packet *packet,
|
||||
struct te_state *state);
|
||||
|
||||
/*
|
||||
* Function: Angel_TxEngine
|
||||
* Purpose: Tx Engine for character-based devices
|
||||
*
|
||||
* Params:
|
||||
* Input: packet details of packet
|
||||
* packet.len, packet.data and
|
||||
* packet.type must
|
||||
* be set on entry!
|
||||
* In/Out: state internal state, intially set by
|
||||
* angel_TxEngineStart()
|
||||
* Output: tx_ch the character to be transmitted
|
||||
* (NOT SET if return code is TS_IDLE)
|
||||
*
|
||||
* Returns: te_status (see above)
|
||||
*/
|
||||
|
||||
te_status Angel_TxEngine(const struct data_packet *packet,
|
||||
struct te_state *state,
|
||||
unsigned char *tx_ch);
|
||||
|
||||
|
||||
|
||||
#endif /* !defined(angel_rxtx_h) */
|
||||
|
||||
/* EOF rxtx.h */
|
|
@ -1,647 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*
|
||||
* serdrv.c - Synchronous Serial Driver for Angel.
|
||||
* This is nice and simple just to get something going.
|
||||
*/
|
||||
|
||||
#ifdef __hpux
|
||||
# define _POSIX_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "crc.h"
|
||||
#include "devices.h"
|
||||
#include "buffers.h"
|
||||
#include "rxtx.h"
|
||||
#include "hostchan.h"
|
||||
#include "params.h"
|
||||
#include "logging.h"
|
||||
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
# undef ERROR
|
||||
# undef IGNORE
|
||||
# include <windows.h>
|
||||
# include "angeldll.h"
|
||||
# include "comb_api.h"
|
||||
#else
|
||||
# ifdef __hpux
|
||||
# define _TERMIOS_INCLUDED
|
||||
# include <sys/termio.h>
|
||||
# undef _TERMIOS_INCLUDED
|
||||
# else
|
||||
# include <termios.h>
|
||||
# endif
|
||||
# include "unixcomm.h"
|
||||
#endif
|
||||
|
||||
#ifndef UNUSED
|
||||
# define UNUSED(x) (x = x) /* Silence compiler warnings */
|
||||
#endif
|
||||
|
||||
#define MAXREADSIZE 512
|
||||
#define MAXWRITESIZE 512
|
||||
|
||||
#define SERIAL_FC_SET ((1<<serial_XON)|(1<<serial_XOFF))
|
||||
#define SERIAL_CTL_SET ((1<<serial_STX)|(1<<serial_ETX)|(1<<serial_ESC))
|
||||
#define SERIAL_ESC_SET (SERIAL_FC_SET|SERIAL_CTL_SET)
|
||||
|
||||
static const struct re_config config = {
|
||||
serial_STX, serial_ETX, serial_ESC, /* self-explanatory? */
|
||||
SERIAL_FC_SET, /* set of flow-control characters */
|
||||
SERIAL_ESC_SET, /* set of characters to be escaped */
|
||||
NULL /* serial_flow_control */, NULL , /* what to do with FC chars */
|
||||
angel_DD_RxEng_BufferAlloc, NULL /* how to get a buffer */
|
||||
};
|
||||
|
||||
static struct re_state rxstate;
|
||||
|
||||
typedef struct writestate {
|
||||
unsigned int wbindex;
|
||||
/* static te_status testatus;*/
|
||||
unsigned char writebuf[MAXWRITESIZE];
|
||||
struct te_state txstate;
|
||||
} writestate;
|
||||
|
||||
static struct writestate wstate;
|
||||
|
||||
/*
|
||||
* The set of parameter options supported by the device
|
||||
*/
|
||||
static unsigned int baud_options[] = {
|
||||
#ifdef __hpux
|
||||
115200, 57600,
|
||||
#endif
|
||||
38400, 19200, 9600
|
||||
};
|
||||
|
||||
static ParameterList param_list[] = {
|
||||
{ AP_BAUD_RATE,
|
||||
sizeof(baud_options)/sizeof(unsigned int),
|
||||
baud_options }
|
||||
};
|
||||
|
||||
static const ParameterOptions serial_options = {
|
||||
sizeof(param_list)/sizeof(ParameterList), param_list };
|
||||
|
||||
/*
|
||||
* The default parameter config for the device
|
||||
*/
|
||||
static Parameter param_default[] = {
|
||||
{ AP_BAUD_RATE, 9600 }
|
||||
};
|
||||
|
||||
static ParameterConfig serial_defaults = {
|
||||
sizeof(param_default)/sizeof(Parameter), param_default };
|
||||
|
||||
/*
|
||||
* The user-modified options for the device
|
||||
*/
|
||||
static unsigned int user_baud_options[sizeof(baud_options)/sizeof(unsigned)];
|
||||
|
||||
static ParameterList param_user_list[] = {
|
||||
{ AP_BAUD_RATE,
|
||||
sizeof(user_baud_options)/sizeof(unsigned),
|
||||
user_baud_options }
|
||||
};
|
||||
|
||||
static ParameterOptions user_options = {
|
||||
sizeof(param_user_list)/sizeof(ParameterList), param_user_list };
|
||||
|
||||
static bool user_options_set;
|
||||
|
||||
/* forward declarations */
|
||||
static int serial_reset( void );
|
||||
static int serial_set_params( const ParameterConfig *config );
|
||||
static int SerialMatch(const char *name, const char *arg);
|
||||
|
||||
static void process_baud_rate( unsigned int target_baud_rate )
|
||||
{
|
||||
const ParameterList *full_list;
|
||||
ParameterList *user_list;
|
||||
|
||||
/* create subset of full options */
|
||||
full_list = Angel_FindParamList( &serial_options, AP_BAUD_RATE );
|
||||
user_list = Angel_FindParamList( &user_options, AP_BAUD_RATE );
|
||||
|
||||
if ( full_list != NULL && user_list != NULL )
|
||||
{
|
||||
unsigned int i, j;
|
||||
unsigned int def_baud = 0;
|
||||
|
||||
/* find lower or equal to */
|
||||
for ( i = 0; i < full_list->num_options; ++i )
|
||||
if ( target_baud_rate >= full_list->option[i] )
|
||||
{
|
||||
/* copy remaining */
|
||||
for ( j = 0; j < (full_list->num_options - i); ++j )
|
||||
user_list->option[j] = full_list->option[i+j];
|
||||
user_list->num_options = j;
|
||||
|
||||
/* check this is not the default */
|
||||
Angel_FindParam( AP_BAUD_RATE, &serial_defaults, &def_baud );
|
||||
if ( (j == 1) && (user_list->option[0] == def_baud) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf( "user selected default\n" );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
user_options_set = TRUE;
|
||||
#ifdef DEBUG
|
||||
printf( "user options are: " );
|
||||
for ( j = 0; j < user_list->num_options; ++j )
|
||||
printf( "%u ", user_list->option[j] );
|
||||
printf( "\n" );
|
||||
#endif
|
||||
}
|
||||
|
||||
break; /* out of i loop */
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if ( i >= full_list->num_options )
|
||||
printf( "couldn't match baud rate %u\n", target_baud_rate );
|
||||
#endif
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else
|
||||
printf( "failed to find lists\n" );
|
||||
#endif
|
||||
}
|
||||
|
||||
static int SerialOpen(const char *name, const char *arg)
|
||||
{
|
||||
const char *port_name = name;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("SerialOpen: name %s arg %s\n", name, arg ? arg : "<NULL>");
|
||||
#endif
|
||||
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
if (IsOpenSerial()) return -1;
|
||||
#else
|
||||
if (Unix_IsSerialInUse()) return -1;
|
||||
#endif
|
||||
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
if (SerialMatch(name, arg) != adp_ok)
|
||||
return adp_failed;
|
||||
#else
|
||||
port_name = Unix_MatchValidSerialDevice(port_name);
|
||||
# ifdef DEBUG
|
||||
printf("translated port to %s\n", port_name == 0 ? "NULL" : port_name);
|
||||
# endif
|
||||
if (port_name == 0) return adp_failed;
|
||||
#endif
|
||||
|
||||
user_options_set = FALSE;
|
||||
|
||||
/* interpret and store the arguments */
|
||||
if ( arg != NULL )
|
||||
{
|
||||
unsigned int target_baud_rate;
|
||||
target_baud_rate = (unsigned int)strtoul(arg, NULL, 10);
|
||||
if (target_baud_rate > 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf( "user selected baud rate %u\n", target_baud_rate );
|
||||
#endif
|
||||
process_baud_rate( target_baud_rate );
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else
|
||||
printf( "could not understand baud rate %s\n", arg );
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
{
|
||||
int port = IsValidDevice(name);
|
||||
if (OpenSerial(port, FALSE) != COM_OK)
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
if (Unix_OpenSerial(port_name) < 0)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
serial_reset();
|
||||
|
||||
#if defined(__unix) || defined(__CYGWIN32__)
|
||||
Unix_ioctlNonBlocking();
|
||||
#endif
|
||||
|
||||
Angel_RxEngineInit(&config, &rxstate);
|
||||
/*
|
||||
* DANGER!: passing in NULL as the packet is ok for now as it is just
|
||||
* IGNOREd but this may well change
|
||||
*/
|
||||
Angel_TxEngineInit(&config, NULL, &wstate.txstate);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int SerialMatch(const char *name, const char *arg)
|
||||
{
|
||||
UNUSED(arg);
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
if (IsValidDevice(name) == COM_DEVICENOTVALID)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
#else
|
||||
return Unix_MatchValidSerialDevice(name) == 0 ? -1 : 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SerialClose(void)
|
||||
{
|
||||
#ifdef DO_TRACE
|
||||
printf("SerialClose()\n");
|
||||
#endif
|
||||
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
CloseSerial();
|
||||
#else
|
||||
Unix_CloseSerial();
|
||||
#endif
|
||||
}
|
||||
|
||||
static int SerialRead(DriverCall *dc, bool block) {
|
||||
static unsigned char readbuf[MAXREADSIZE];
|
||||
static int rbindex=0;
|
||||
|
||||
int nread;
|
||||
int read_errno;
|
||||
int c=0;
|
||||
re_status restatus;
|
||||
int ret_code = -1; /* assume bad packet or error */
|
||||
|
||||
/* must not overflow buffer and must start after the existing data */
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
{
|
||||
BOOL dummy = FALSE;
|
||||
nread = BytesInRXBufferSerial();
|
||||
|
||||
if (nread > MAXREADSIZE - rbindex)
|
||||
nread = MAXREADSIZE - rbindex;
|
||||
|
||||
if ((read_errno = ReadSerial(readbuf+rbindex, nread, &dummy)) == COM_READFAIL)
|
||||
{
|
||||
MessageBox(GetFocus(), "Read error\n", "Angel", MB_OK | MB_ICONSTOP);
|
||||
return -1; /* SJ - This really needs to return a value, which is picked up in */
|
||||
/* DevSW_Read as meaning stop debugger but don't kill. */
|
||||
}
|
||||
else if (pfnProgressCallback != NULL && read_errno == COM_OK)
|
||||
{
|
||||
progressInfo.nRead += nread;
|
||||
(*pfnProgressCallback)(&progressInfo);
|
||||
}
|
||||
}
|
||||
#else
|
||||
nread = Unix_ReadSerial(readbuf+rbindex, MAXREADSIZE-rbindex, block);
|
||||
read_errno = errno;
|
||||
#endif
|
||||
|
||||
if ((nread > 0) || (rbindex > 0)) {
|
||||
|
||||
#ifdef DO_TRACE
|
||||
printf("[%d@%d] ", nread, rbindex);
|
||||
#endif
|
||||
|
||||
if (nread>0)
|
||||
rbindex = rbindex+nread;
|
||||
|
||||
do {
|
||||
restatus = Angel_RxEngine(readbuf[c], &(dc->dc_packet), &rxstate);
|
||||
#ifdef DO_TRACE
|
||||
printf("<%02X ",readbuf[c]);
|
||||
if (!(++c % 16))
|
||||
printf("\n");
|
||||
#else
|
||||
c++;
|
||||
#endif
|
||||
} while (c<rbindex &&
|
||||
((restatus == RS_IN_PKT) || (restatus == RS_WAIT_PKT)));
|
||||
|
||||
#ifdef DO_TRACE
|
||||
if (c % 16)
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
switch(restatus) {
|
||||
|
||||
case RS_GOOD_PKT:
|
||||
ret_code = 1;
|
||||
/* fall through to: */
|
||||
|
||||
case RS_BAD_PKT:
|
||||
/*
|
||||
* We now need to shuffle any left over data down to the
|
||||
* beginning of our private buffer ready to be used
|
||||
*for the next packet
|
||||
*/
|
||||
#ifdef DO_TRACE
|
||||
printf("SerialRead() processed %d, moving down %d\n", c, rbindex-c);
|
||||
#endif
|
||||
if (c != rbindex) memmove((char *) readbuf, (char *) (readbuf+c),
|
||||
rbindex-c);
|
||||
rbindex -= c;
|
||||
break;
|
||||
|
||||
case RS_IN_PKT:
|
||||
case RS_WAIT_PKT:
|
||||
rbindex = 0; /* will have processed all we had */
|
||||
ret_code = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
printf("Bad re_status in serialRead()\n");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
} else if (nread == 0)
|
||||
ret_code = 0; /* nothing to read */
|
||||
else if (read_errno == ERRNO_FOR_BLOCKED_IO) /* nread < 0 */
|
||||
ret_code = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
if ((nread<0) && (read_errno!=ERRNO_FOR_BLOCKED_IO))
|
||||
perror("read() error in serialRead()");
|
||||
#endif
|
||||
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
|
||||
static int SerialWrite(DriverCall *dc) {
|
||||
int nwritten = 0;
|
||||
te_status testatus = TS_IN_PKT;
|
||||
|
||||
if (dc->dc_context == NULL) {
|
||||
Angel_TxEngineInit(&config, &(dc->dc_packet), &(wstate.txstate));
|
||||
wstate.wbindex = 0;
|
||||
dc->dc_context = &wstate;
|
||||
}
|
||||
|
||||
while ((testatus == TS_IN_PKT) && (wstate.wbindex < MAXWRITESIZE))
|
||||
{
|
||||
/* send the raw data through the tx engine to escape and encapsulate */
|
||||
testatus = Angel_TxEngine(&(dc->dc_packet), &(wstate.txstate),
|
||||
&(wstate.writebuf)[wstate.wbindex]);
|
||||
if (testatus != TS_IDLE) wstate.wbindex++;
|
||||
}
|
||||
|
||||
if (testatus == TS_IDLE) {
|
||||
#ifdef DEBUG
|
||||
printf("SerialWrite: testatus is TS_IDLE during preprocessing\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DO_TRACE
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (i<wstate.wbindex)
|
||||
{
|
||||
printf(">%02X ",wstate.writebuf[i]);
|
||||
|
||||
if (!(++i % 16))
|
||||
printf("\n");
|
||||
}
|
||||
if (i % 16)
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
if (WriteSerial(wstate.writebuf, wstate.wbindex) == COM_OK)
|
||||
{
|
||||
nwritten = wstate.wbindex;
|
||||
if (pfnProgressCallback != NULL)
|
||||
{
|
||||
progressInfo.nWritten += nwritten;
|
||||
(*pfnProgressCallback)(&progressInfo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox(GetFocus(), "Write error\n", "Angel", MB_OK | MB_ICONSTOP);
|
||||
return -1; /* SJ - This really needs to return a value, which is picked up in */
|
||||
/* DevSW_Read as meaning stop debugger but don't kill. */
|
||||
}
|
||||
#else
|
||||
nwritten = Unix_WriteSerial(wstate.writebuf, wstate.wbindex);
|
||||
|
||||
if (nwritten < 0) {
|
||||
nwritten=0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
if (nwritten > 0)
|
||||
printf("Wrote %#04x bytes\n", nwritten);
|
||||
#endif
|
||||
|
||||
if ((unsigned) nwritten == wstate.wbindex &&
|
||||
(testatus == TS_DONE_PKT || testatus == TS_IDLE)) {
|
||||
|
||||
/* finished sending the packet */
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("SerialWrite: calling Angel_TxEngineInit after sending packet (len=%i)\n",wstate.wbindex);
|
||||
#endif
|
||||
testatus = TS_IN_PKT;
|
||||
wstate.wbindex = 0;
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
#ifdef DEBUG
|
||||
printf("SerialWrite: Wrote part of packet wbindex=%i, nwritten=%i\n",
|
||||
wstate.wbindex, nwritten);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* still some data left to send shuffle whats left down and reset
|
||||
* the ptr
|
||||
*/
|
||||
memmove((char *) wstate.writebuf, (char *) (wstate.writebuf+nwritten),
|
||||
wstate.wbindex-nwritten);
|
||||
wstate.wbindex -= nwritten;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int serial_reset( void )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf( "serial_reset\n" );
|
||||
#endif
|
||||
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
FlushSerial();
|
||||
#else
|
||||
Unix_ResetSerial();
|
||||
#endif
|
||||
|
||||
return serial_set_params( &serial_defaults );
|
||||
}
|
||||
|
||||
|
||||
static int find_baud_rate( unsigned int *speed )
|
||||
{
|
||||
static struct {
|
||||
unsigned int baud;
|
||||
int termiosValue;
|
||||
} possibleBaudRates[] = {
|
||||
#if defined(__hpux)
|
||||
{115200,_B115200}, {57600,_B57600},
|
||||
#endif
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
{38400,CBR_38400}, {19200,CBR_19200}, {9600, CBR_9600}, {0,0}
|
||||
#else
|
||||
{38400,B38400}, {19200,B19200}, {9600, B9600}, {0,0}
|
||||
#endif
|
||||
};
|
||||
unsigned int i;
|
||||
|
||||
/* look for lower or matching -- will always terminate at 0 end marker */
|
||||
for ( i = 0; possibleBaudRates[i].baud > *speed; ++i )
|
||||
/* do nothing */ ;
|
||||
|
||||
if ( possibleBaudRates[i].baud > 0 )
|
||||
*speed = possibleBaudRates[i].baud;
|
||||
|
||||
return possibleBaudRates[i].termiosValue;
|
||||
}
|
||||
|
||||
|
||||
static int serial_set_params( const ParameterConfig *config )
|
||||
{
|
||||
unsigned int speed;
|
||||
int termios_value;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "serial_set_params\n" );
|
||||
#endif
|
||||
|
||||
if ( ! Angel_FindParam( AP_BAUD_RATE, config, &speed ) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf( "speed not found in config\n" );
|
||||
#endif
|
||||
return DE_OKAY;
|
||||
}
|
||||
|
||||
termios_value = find_baud_rate( &speed );
|
||||
if ( termios_value == 0 )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf( "speed not valid: %u\n", speed );
|
||||
#endif
|
||||
return DE_OKAY;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "setting speed to %u\n", speed );
|
||||
#endif
|
||||
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
SetBaudRate((WORD)termios_value);
|
||||
#else
|
||||
Unix_SetSerialBaudRate(termios_value);
|
||||
#endif
|
||||
|
||||
return DE_OKAY;
|
||||
}
|
||||
|
||||
|
||||
static int serial_get_user_params( ParameterOptions **p_options )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf( "serial_get_user_params\n" );
|
||||
#endif
|
||||
|
||||
if ( user_options_set )
|
||||
{
|
||||
*p_options = &user_options;
|
||||
}
|
||||
else
|
||||
{
|
||||
*p_options = NULL;
|
||||
}
|
||||
|
||||
return DE_OKAY;
|
||||
}
|
||||
|
||||
|
||||
static int serial_get_default_params( ParameterConfig **p_config )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf( "serial_get_default_params\n" );
|
||||
#endif
|
||||
|
||||
*p_config = (ParameterConfig *) &serial_defaults;
|
||||
return DE_OKAY;
|
||||
}
|
||||
|
||||
|
||||
static int SerialIoctl(const int opcode, void *args) {
|
||||
|
||||
int ret_code;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "SerialIoctl: op %d arg %p\n", opcode, args ? args : "<NULL>");
|
||||
#endif
|
||||
|
||||
switch (opcode)
|
||||
{
|
||||
case DC_RESET:
|
||||
ret_code = serial_reset();
|
||||
break;
|
||||
|
||||
case DC_SET_PARAMS:
|
||||
ret_code = serial_set_params((const ParameterConfig *)args);
|
||||
break;
|
||||
|
||||
case DC_GET_USER_PARAMS:
|
||||
ret_code = serial_get_user_params((ParameterOptions **)args);
|
||||
break;
|
||||
|
||||
case DC_GET_DEFAULT_PARAMS:
|
||||
ret_code = serial_get_default_params((ParameterConfig **)args);
|
||||
break;
|
||||
|
||||
default:
|
||||
ret_code = DE_BAD_OP;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
DeviceDescr angel_SerialDevice = {
|
||||
"SERIAL",
|
||||
SerialOpen,
|
||||
SerialMatch,
|
||||
SerialClose,
|
||||
SerialRead,
|
||||
SerialWrite,
|
||||
SerialIoctl
|
||||
};
|
|
@ -1,728 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*
|
||||
* serpardv.c - Serial/Parallel Driver for Angel.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "crc.h"
|
||||
#include "devices.h"
|
||||
#include "buffers.h"
|
||||
#include "rxtx.h"
|
||||
#include "hostchan.h"
|
||||
#include "params.h"
|
||||
#include "logging.h"
|
||||
#include "hsys.h"
|
||||
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
# undef ERROR
|
||||
# undef IGNORE
|
||||
# include <windows.h>
|
||||
# include "angeldll.h"
|
||||
# include "comb_api.h"
|
||||
#else
|
||||
# ifdef __hpux
|
||||
# define _TERMIOS_INCLUDED
|
||||
# include <sys/termio.h>
|
||||
# undef _TERMIOS_INCLUDED
|
||||
# else
|
||||
# include <termios.h>
|
||||
# endif
|
||||
# include "unixcomm.h"
|
||||
#endif
|
||||
|
||||
#ifndef UNUSED
|
||||
# define UNUSED(x) (x = x) /* Silence compiler warnings */
|
||||
#endif
|
||||
|
||||
#define MAXREADSIZE 512
|
||||
#define MAXWRITESIZE 512
|
||||
|
||||
#define SERPAR_FC_SET ((1 << serial_XON) | (1 << serial_XOFF))
|
||||
#define SERPAR_CTL_SET ((1 << serial_STX) | (1 << serial_ETX) | \
|
||||
(1 << serial_ESC))
|
||||
#define SERPAR_ESC_SET (SERPAR_FC_SET | SERPAR_CTL_SET)
|
||||
|
||||
static const struct re_config config = {
|
||||
serial_STX, serial_ETX, serial_ESC, /* self-explanatory? */
|
||||
SERPAR_FC_SET, /* set of flow-control characters */
|
||||
SERPAR_ESC_SET, /* set of characters to be escaped */
|
||||
NULL, /* serial_flow_control */
|
||||
NULL, /* what to do with FC chars */
|
||||
angel_DD_RxEng_BufferAlloc, NULL /* how to get a buffer */
|
||||
};
|
||||
|
||||
static struct re_state rxstate;
|
||||
|
||||
/*
|
||||
* structure used for manipulating transmit data
|
||||
*/
|
||||
typedef struct TxState
|
||||
{
|
||||
struct te_state state;
|
||||
unsigned int index;
|
||||
unsigned char writebuf[MAXWRITESIZE];
|
||||
} TxState;
|
||||
|
||||
/*
|
||||
* The set of parameter options supported by the device
|
||||
*/
|
||||
static unsigned int baud_options[] =
|
||||
{
|
||||
#ifdef __hpux
|
||||
115200, 57600,
|
||||
#endif
|
||||
38400, 19200, 9600
|
||||
};
|
||||
|
||||
static ParameterList param_list[] =
|
||||
{
|
||||
{
|
||||
AP_BAUD_RATE,
|
||||
sizeof(baud_options) / sizeof(unsigned int),
|
||||
baud_options
|
||||
}
|
||||
};
|
||||
|
||||
static const ParameterOptions serpar_options =
|
||||
{
|
||||
sizeof(param_list) / sizeof(ParameterList),
|
||||
param_list
|
||||
};
|
||||
|
||||
/*
|
||||
* The default parameter config for the device
|
||||
*/
|
||||
static Parameter param_default[] =
|
||||
{
|
||||
{ AP_BAUD_RATE, 9600 }
|
||||
};
|
||||
|
||||
static const ParameterConfig serpar_defaults =
|
||||
{
|
||||
sizeof(param_default)/sizeof(Parameter),
|
||||
param_default
|
||||
};
|
||||
|
||||
/*
|
||||
* The user-modified options for the device
|
||||
*/
|
||||
static unsigned int user_baud_options[sizeof(baud_options) /
|
||||
sizeof(unsigned int)];
|
||||
|
||||
static ParameterList param_user_list[] =
|
||||
{
|
||||
{
|
||||
AP_BAUD_RATE,
|
||||
sizeof(user_baud_options) / sizeof(unsigned),
|
||||
user_baud_options
|
||||
}
|
||||
};
|
||||
|
||||
static ParameterOptions user_options =
|
||||
{
|
||||
sizeof(param_user_list) / sizeof(ParameterList),
|
||||
param_user_list
|
||||
};
|
||||
|
||||
static bool user_options_set;
|
||||
|
||||
/* forward declarations */
|
||||
static int serpar_reset(void);
|
||||
static int serpar_set_params(const ParameterConfig *config);
|
||||
static int SerparMatch(const char *name, const char *arg);
|
||||
|
||||
static void process_baud_rate(unsigned int target_baud_rate)
|
||||
{
|
||||
const ParameterList *full_list;
|
||||
ParameterList *user_list;
|
||||
|
||||
/* create subset of full options */
|
||||
full_list = Angel_FindParamList(&serpar_options, AP_BAUD_RATE);
|
||||
user_list = Angel_FindParamList(&user_options, AP_BAUD_RATE);
|
||||
|
||||
if (full_list != NULL && user_list != NULL)
|
||||
{
|
||||
unsigned int i, j;
|
||||
unsigned int def_baud = 0;
|
||||
|
||||
/* find lower or equal to */
|
||||
for (i = 0; i < full_list->num_options; ++i)
|
||||
if (target_baud_rate >= full_list->option[i])
|
||||
{
|
||||
/* copy remaining */
|
||||
for (j = 0; j < (full_list->num_options - i); ++j)
|
||||
user_list->option[j] = full_list->option[i+j];
|
||||
user_list->num_options = j;
|
||||
|
||||
/* check this is not the default */
|
||||
Angel_FindParam(AP_BAUD_RATE, &serpar_defaults, &def_baud);
|
||||
if ((j == 1) && (user_list->option[0] == def_baud))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("user selected default\n");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
user_options_set = TRUE;
|
||||
#ifdef DEBUG
|
||||
printf("user options are: ");
|
||||
for (j = 0; j < user_list->num_options; ++j)
|
||||
printf("%u ", user_list->option[j]);
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
break; /* out of i loop */
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (i >= full_list->num_options)
|
||||
printf("couldn't match baud rate %u\n", target_baud_rate);
|
||||
#endif
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else
|
||||
printf("failed to find lists\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static int SerparOpen(const char *name, const char *arg)
|
||||
{
|
||||
char *sername = NULL;
|
||||
char *parname = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("SerparOpen: name %s arg %s\n", name, arg ? arg : "<NULL>");
|
||||
#endif
|
||||
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
if (IsOpenSerial() || IsOpenParallel()) return -1;
|
||||
#else
|
||||
if (Unix_IsSerialInUse() || Unix_IsParallelInUse()) return -1;
|
||||
#endif
|
||||
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
if (SerparMatch(name, arg) == -1)
|
||||
return -1;
|
||||
#else
|
||||
Unix_IsValidParallelDevice(name,&sername,&parname);
|
||||
# ifdef DEBUG
|
||||
printf("translated %s to serial %s and parallel %s\n",
|
||||
name==0 ? "NULL" : name,
|
||||
sername==0 ? "NULL" : sername,
|
||||
parname==0 ? "NULL" : parname);
|
||||
# endif
|
||||
if (sername==NULL || parname==NULL) return -1;
|
||||
#endif
|
||||
|
||||
user_options_set = FALSE;
|
||||
|
||||
/* interpret and store the arguments */
|
||||
if (arg != NULL)
|
||||
{
|
||||
unsigned int target_baud_rate;
|
||||
|
||||
target_baud_rate = (unsigned int)strtoul(arg, NULL, 10);
|
||||
|
||||
if (target_baud_rate > 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("user selected baud rate %u\n", target_baud_rate);
|
||||
#endif
|
||||
process_baud_rate(target_baud_rate);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else
|
||||
printf("could not understand baud rate %s\n", arg);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
{
|
||||
/*
|
||||
* The serial port number is in name[0] followed by
|
||||
* the parallel port number in name[1]
|
||||
*/
|
||||
|
||||
int sport = name[0] - '0';
|
||||
int pport = name[1] - '0';
|
||||
|
||||
if (OpenParallel(pport) != COM_OK)
|
||||
return -1;
|
||||
|
||||
if (OpenSerial(sport, FALSE) != COM_OK)
|
||||
{
|
||||
CloseParallel();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
Unix_OpenParallel(parname);
|
||||
Unix_OpenSerial(sername);
|
||||
#endif
|
||||
|
||||
serpar_reset();
|
||||
|
||||
#if defined(__unix) || defined(__CYGWIN32__)
|
||||
Unix_ioctlNonBlocking();
|
||||
#endif
|
||||
|
||||
Angel_RxEngineInit(&config, &rxstate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
static int SerparMatch(const char *name, const char *arg)
|
||||
{
|
||||
char sername[2];
|
||||
char parname[2];
|
||||
|
||||
UNUSED(arg);
|
||||
|
||||
sername[0] = name[0];
|
||||
parname[0] = name[1];
|
||||
sername[1] = parname[1] = 0;
|
||||
|
||||
if (IsValidDevice(sername) == COM_DEVICENOTVALID ||
|
||||
IsValidDevice(parname) == COM_DEVICENOTVALID)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int SerparMatch(const char *portstring, const char *arg)
|
||||
{
|
||||
char *sername=NULL, *parname=NULL;
|
||||
UNUSED(arg);
|
||||
|
||||
Unix_IsValidParallelDevice(portstring,&sername,&parname);
|
||||
|
||||
/* Match failed if either sername or parname are still NULL */
|
||||
if (sername==NULL || parname==NULL) return -1;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void SerparClose(void)
|
||||
{
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
CloseParallel();
|
||||
CloseSerial();
|
||||
#else
|
||||
Unix_CloseParallel();
|
||||
Unix_CloseSerial();
|
||||
#endif
|
||||
}
|
||||
|
||||
static int SerparRead(DriverCall *dc, bool block)
|
||||
{
|
||||
static unsigned char readbuf[MAXREADSIZE];
|
||||
static int rbindex = 0;
|
||||
|
||||
int nread;
|
||||
int read_errno;
|
||||
int c = 0;
|
||||
re_status restatus;
|
||||
int ret_code = -1; /* assume bad packet or error */
|
||||
|
||||
/*
|
||||
* we must not overflow buffer, and must start after
|
||||
* the existing data
|
||||
*/
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
{
|
||||
BOOL dummy = FALSE;
|
||||
nread = BytesInRXBufferSerial();
|
||||
|
||||
if (nread > MAXREADSIZE - rbindex)
|
||||
nread = MAXREADSIZE - rbindex;
|
||||
read_errno = ReadSerial(readbuf+rbindex, nread, &dummy);
|
||||
if (pfnProgressCallback != NULL && read_errno == COM_OK)
|
||||
{
|
||||
progressInfo.nRead += nread;
|
||||
(*pfnProgressCallback)(&progressInfo);
|
||||
}
|
||||
}
|
||||
#else
|
||||
nread = Unix_ReadSerial(readbuf+rbindex, MAXREADSIZE-rbindex, block);
|
||||
read_errno = errno;
|
||||
#endif
|
||||
|
||||
if ((nread > 0) || (rbindex > 0))
|
||||
{
|
||||
#ifdef DO_TRACE
|
||||
printf("[%d@%d] ", nread, rbindex);
|
||||
#endif
|
||||
|
||||
if (nread > 0)
|
||||
rbindex = rbindex + nread;
|
||||
|
||||
do
|
||||
{
|
||||
restatus = Angel_RxEngine(readbuf[c], &(dc->dc_packet), &rxstate);
|
||||
|
||||
#ifdef DO_TRACE
|
||||
printf("<%02X ",readbuf[c]);
|
||||
#endif
|
||||
c++;
|
||||
} while (c < rbindex &&
|
||||
((restatus == RS_IN_PKT) || (restatus == RS_WAIT_PKT)));
|
||||
|
||||
#ifdef DO_TRACE
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
switch(restatus)
|
||||
{
|
||||
case RS_GOOD_PKT:
|
||||
ret_code = 1;
|
||||
/* fall through to: */
|
||||
|
||||
case RS_BAD_PKT:
|
||||
/*
|
||||
* We now need to shuffle any left over data down to the
|
||||
* beginning of our private buffer ready to be used
|
||||
*for the next packet
|
||||
*/
|
||||
#ifdef DO_TRACE
|
||||
printf("SerparRead() processed %d, moving down %d\n",
|
||||
c, rbindex - c);
|
||||
#endif
|
||||
|
||||
if (c != rbindex)
|
||||
memmove((char *) readbuf, (char *) (readbuf + c), rbindex - c);
|
||||
|
||||
rbindex -= c;
|
||||
|
||||
break;
|
||||
|
||||
case RS_IN_PKT:
|
||||
case RS_WAIT_PKT:
|
||||
rbindex = 0; /* will have processed all we had */
|
||||
ret_code = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
printf("Bad re_status in SerparRead()\n");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (nread == 0)
|
||||
/* nothing to read */
|
||||
ret_code = 0;
|
||||
else if (read_errno == ERRNO_FOR_BLOCKED_IO) /* nread < 0 */
|
||||
ret_code = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
if ((nread < 0) && (read_errno != ERRNO_FOR_BLOCKED_IO))
|
||||
perror("read() error in SerparRead()");
|
||||
#endif
|
||||
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function: send_packet
|
||||
* Purpose: Send a stream of bytes to Angel through the parallel port
|
||||
*
|
||||
* Algorithm: We need to present the data in a form that all boards can
|
||||
* swallow. With the PID board, this is a problem: for reasons
|
||||
* described in the driver (angel/pid/st16c552.c), data are
|
||||
* sent a nybble at a time on D0-D2 and D4; D3 is wired to ACK,
|
||||
* which generates an interrupt when it goes low. This routine
|
||||
* fills in an array of nybbles, with ACK clear in all but the
|
||||
* last one. If, for whatever reason, the write fails, then
|
||||
* ACK is forced high (thereby enabling the next write a chance
|
||||
* to be noticed when the falling edge of ACK generates an
|
||||
* interrupt (hopefully).
|
||||
*
|
||||
* Params:
|
||||
* Input: txstate Contains the packet to be sent
|
||||
*
|
||||
* Returns: Number of *complete* bytes written
|
||||
*/
|
||||
|
||||
static int SerparWrite(DriverCall *dc)
|
||||
{
|
||||
te_status status;
|
||||
int nwritten = 0;
|
||||
static TxState txstate;
|
||||
|
||||
/*
|
||||
* is this a new packet?
|
||||
*/
|
||||
if (dc->dc_context == NULL)
|
||||
{
|
||||
/*
|
||||
* yes - initialise TxEngine
|
||||
*/
|
||||
Angel_TxEngineInit(&config, &dc->dc_packet, &txstate.state);
|
||||
|
||||
txstate.index = 0;
|
||||
dc->dc_context = &txstate;
|
||||
}
|
||||
|
||||
/*
|
||||
* fill the buffer using the Tx Engine
|
||||
*/
|
||||
do
|
||||
{
|
||||
status = Angel_TxEngine(&dc->dc_packet, &txstate.state,
|
||||
&txstate.writebuf[txstate.index]);
|
||||
if (status != TS_IDLE) txstate.index++;
|
||||
|
||||
} while (status == TS_IN_PKT && txstate.index < MAXWRITESIZE);
|
||||
|
||||
#ifdef DO_TRACE
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
while (i < txstate.index)
|
||||
{
|
||||
printf(">%02X ", txstate.writebuf[i]);
|
||||
|
||||
if (!(++i % 16))
|
||||
putc('\n', stdout);
|
||||
}
|
||||
|
||||
if (i % 16)
|
||||
putc('\n', stdout);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* the data are ready, all we need now is to send them out
|
||||
* in a form that Angel can swallow.
|
||||
*/
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
if (WriteParallel(txstate.writebuf, txstate.index) == COM_OK)
|
||||
{
|
||||
nwritten = txstate.index;
|
||||
if (pfnProgressCallback != NULL)
|
||||
{
|
||||
progressInfo.nWritten += nwritten;
|
||||
(*pfnProgressCallback)(&progressInfo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox(GetFocus(), "Write error\n", "Angel", MB_OK | MB_ICONSTOP);
|
||||
return -1; /* SJ - This really needs to return a value, which is picked up in */
|
||||
/* DevSW_Read as meaning stop debugger but don't kill. */
|
||||
}
|
||||
#else
|
||||
nwritten = Unix_WriteParallel(txstate.writebuf, txstate.index);
|
||||
#endif
|
||||
|
||||
if (nwritten < 0) nwritten = 0;
|
||||
|
||||
#ifdef DO_TRACE
|
||||
printf("SerparWrite: wrote %d out of %d bytes\n",
|
||||
nwritten, txstate.index);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* has the whole packet gone?
|
||||
*/
|
||||
if (nwritten == (int)txstate.index &&
|
||||
(status == TS_DONE_PKT || status == TS_IDLE))
|
||||
/*
|
||||
* yes it has
|
||||
*/
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
/*
|
||||
* if some data are left, shuffle them
|
||||
* to the start of the buffer
|
||||
*/
|
||||
if (nwritten != (int)txstate.index && nwritten != 0)
|
||||
{
|
||||
txstate.index -= nwritten;
|
||||
(void)memmove((char *) txstate.writebuf,
|
||||
(char *) (txstate.writebuf + nwritten),
|
||||
txstate.index);
|
||||
}
|
||||
else if (nwritten == (int)txstate.index)
|
||||
txstate.index = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int serpar_reset(void)
|
||||
{
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
FlushParallel();
|
||||
FlushSerial();
|
||||
#else
|
||||
Unix_ResetParallel();
|
||||
Unix_ResetSerial();
|
||||
#endif
|
||||
|
||||
return serpar_set_params(&serpar_defaults);
|
||||
}
|
||||
|
||||
static int find_baud_rate(unsigned int *speed)
|
||||
{
|
||||
static struct
|
||||
{
|
||||
unsigned int baud;
|
||||
int termiosValue;
|
||||
} possibleBaudRates[] =
|
||||
{
|
||||
#if defined(__hpux)
|
||||
{115200, _B115200}, {57600, _B57600},
|
||||
#endif
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
{38400, CBR_38400}, {19200, CBR_19200}, {9600, CBR_9600}, {0, 0}
|
||||
#else
|
||||
{38400, B38400}, {19200, B19200}, {9600, B9600}, {0, 0}
|
||||
#endif
|
||||
};
|
||||
unsigned int i;
|
||||
|
||||
/* look for lower or matching -- will always terminate at 0 end marker */
|
||||
for (i = 0; possibleBaudRates[i].baud > *speed; ++i)
|
||||
/* do nothing */
|
||||
;
|
||||
|
||||
if (possibleBaudRates[i].baud > 0)
|
||||
*speed = possibleBaudRates[i].baud;
|
||||
|
||||
return possibleBaudRates[i].termiosValue;
|
||||
}
|
||||
|
||||
static int serpar_set_params(const ParameterConfig *config)
|
||||
{
|
||||
unsigned int speed;
|
||||
int termios_value;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("serpar_set_params\n");
|
||||
#endif
|
||||
|
||||
if (!Angel_FindParam(AP_BAUD_RATE, config, &speed))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("speed not found in config\n");
|
||||
#endif
|
||||
return DE_OKAY;
|
||||
}
|
||||
|
||||
termios_value = find_baud_rate(&speed);
|
||||
if (termios_value == 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("speed not valid: %u\n", speed);
|
||||
#endif
|
||||
return DE_OKAY;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("setting speed to %u\n", speed);
|
||||
#endif
|
||||
|
||||
#ifdef COMPILING_ON_WINDOWS
|
||||
SetBaudRate((WORD)termios_value);
|
||||
#else
|
||||
Unix_SetSerialBaudRate(termios_value);
|
||||
#endif
|
||||
|
||||
return DE_OKAY;
|
||||
}
|
||||
|
||||
|
||||
static int serpar_get_user_params(ParameterOptions **p_options)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("serpar_get_user_params\n");
|
||||
#endif
|
||||
|
||||
if (user_options_set)
|
||||
{
|
||||
*p_options = &user_options;
|
||||
}
|
||||
else
|
||||
{
|
||||
*p_options = NULL;
|
||||
}
|
||||
|
||||
return DE_OKAY;
|
||||
}
|
||||
|
||||
|
||||
static int serial_get_default_params( const ParameterConfig **p_config )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf( "serial_get_default_params\n" );
|
||||
#endif
|
||||
|
||||
*p_config = &serpar_defaults;
|
||||
return DE_OKAY;
|
||||
}
|
||||
|
||||
|
||||
static int SerparIoctl(const int opcode, void *args)
|
||||
{
|
||||
int ret_code;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("SerparIoctl: op %d arg %p\n", opcode, args ? args : "<NULL>");
|
||||
#endif
|
||||
|
||||
switch (opcode)
|
||||
{
|
||||
case DC_RESET:
|
||||
ret_code = serpar_reset();
|
||||
break;
|
||||
|
||||
case DC_SET_PARAMS:
|
||||
ret_code = serpar_set_params((const ParameterConfig *)args);
|
||||
break;
|
||||
|
||||
case DC_GET_USER_PARAMS:
|
||||
ret_code = serpar_get_user_params((ParameterOptions **)args);
|
||||
break;
|
||||
|
||||
case DC_GET_DEFAULT_PARAMS:
|
||||
ret_code =
|
||||
serial_get_default_params((const ParameterConfig **)args);
|
||||
break;
|
||||
|
||||
default:
|
||||
ret_code = DE_BAD_OP;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
DeviceDescr angel_SerparDevice =
|
||||
{
|
||||
"SERPAR",
|
||||
SerparOpen,
|
||||
SerparMatch,
|
||||
SerparClose,
|
||||
SerparRead,
|
||||
SerparWrite,
|
||||
SerparIoctl
|
||||
};
|
||||
|
||||
/* EOF serpardr.c */
|
|
@ -1,317 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* sys.h
|
||||
***********************************************************************
|
||||
* Angel C Libary support channel protocol definitions
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* MESSAGE FORMAT
|
||||
* --------------
|
||||
* Format of the "data" section of C Lib Support Channel Messages.
|
||||
* You will notice that the format is much the same as the format
|
||||
* of ADP messages - this is so that multi-threaded C Libraries can
|
||||
* be supported.
|
||||
*
|
||||
* unsigned32 reason - Main C Library reason code.
|
||||
* unsigned32 debugID - Info. describing host debug world;
|
||||
* private to host and used in any target
|
||||
* initiated messages.
|
||||
* unsigned32 OSinfo1 \ Target OS information to identify process/thread
|
||||
* unsigned32 OSinfo2 / world, etc. These two fields are target defined.
|
||||
* byte args[n] - Data for message "reason" code.
|
||||
*
|
||||
* The "debugID" is defined by the host-end of the protocol, and is used
|
||||
* by the host to ensure that messages are routed to the correct handler
|
||||
* program/veneer (eg. imagine several threads having opened stdout and
|
||||
* each writing to a different window in a windowed debugger).
|
||||
*
|
||||
* NOTE: The reason that there is no "size" information, is that the
|
||||
* message IDs themselves encode the format of any arguments.
|
||||
*
|
||||
* For further discussion of the format see adp.h
|
||||
*
|
||||
* N.B. All streams are little endian.
|
||||
*
|
||||
* CLIB REASON CODE
|
||||
* ----------------
|
||||
* The message reason codes contain some information that ties them to
|
||||
* the channel and direction that the message will be used with. This
|
||||
* will ensure that even if the message "#define name" is not
|
||||
* completely descriptive, the message reason code is.
|
||||
*
|
||||
* b31 = direction. 0=Host-to-Target; 1=Target-to-Host;
|
||||
* b30-16 = reserved. should be zero
|
||||
* b15-0 = message reason code.
|
||||
*
|
||||
* Note that typically a request will be initiated by the target side, and
|
||||
* that the host will then respond with either an acknowledgement or some
|
||||
* data. In either case the same reason code will be used, but the direction
|
||||
* bit will be reveresed.
|
||||
*/
|
||||
|
||||
#ifndef __sys_h
|
||||
#define __sys_h
|
||||
|
||||
#ifndef HtoT
|
||||
#define HtoT ((unsigned)0 << 31) /* Host-to-Target message */
|
||||
#define TtoH ((unsigned)1 << 31) /* Target-to-Host message */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The following are error codes used in the status field returned on
|
||||
* sending a message. 0 represents no error having occurred, non-zero
|
||||
* represents a general error. More codes should be added as required.
|
||||
*/
|
||||
|
||||
#ifndef ErrCode
|
||||
#define NoError 0x0
|
||||
#endif
|
||||
|
||||
/*************************************************************************/
|
||||
/* The following are direct conversions of the DeMon SWI's */
|
||||
/* NB: nbytes is the number of bytes INCLUDING THE NULL character where */
|
||||
/* applicable. */
|
||||
|
||||
/* This message is used as a response to a packet whose message
|
||||
* was not understood. The return parameter, code is the reason
|
||||
* code which was not understood. Although intended for use as a
|
||||
* default case on a received message switch it can also be used
|
||||
* as a proper message*/
|
||||
#define CL_Unrecognised 0x00
|
||||
/* Unrecognised()
|
||||
* return(word code)
|
||||
*/
|
||||
|
||||
/* Write a character to the terminal.
|
||||
*/
|
||||
#define CL_WriteC 0x01
|
||||
/* WriteC(byte data)
|
||||
* return(word status)
|
||||
*/
|
||||
|
||||
/* Write a NULL terminated string of characters to the terminal. The length
|
||||
* of the string excluding the NULL terminating character is passed in
|
||||
* 'nbytes'.
|
||||
*/
|
||||
#define CL_Write0 0x02
|
||||
/* Write0(word nbytes, bytes data)
|
||||
* return(word status)
|
||||
*/
|
||||
|
||||
/* Read a character from the terminal - probably the keyboard.
|
||||
*/
|
||||
#define CL_ReadC 0x04
|
||||
/* ReadC(void)
|
||||
* return(word status, byte data)
|
||||
*/
|
||||
|
||||
/* Perform system call, pass NULL terminated string to host's command
|
||||
* line interpreter(NOT AVAILABLE IN PC/DOS RELEASE). The data byte
|
||||
* returned holds the return code from the system call.
|
||||
*/
|
||||
#define CL_System 0x05
|
||||
/* CLI(word nbytes, bytes data)
|
||||
* return(word status, word data)
|
||||
*/
|
||||
|
||||
/* It returns the address of the null terminated command line string used to
|
||||
* invoke the program. status will be set to NoError if the command line
|
||||
* can be returned. Other status values will be treated as error conditions.
|
||||
*/
|
||||
#define CL_GetCmdLine 0x10
|
||||
/* GetCmdLine(void)
|
||||
* return(word status, word nbytes, bytes argline)
|
||||
*/
|
||||
|
||||
/* Return the number of centi-seconds since the support code began
|
||||
* execution. Only the difference between successive calls can be
|
||||
* meaningful.
|
||||
*/
|
||||
#define CL_Clock 0x61
|
||||
/* Clock(void)
|
||||
* return(word status, word clks)
|
||||
*/
|
||||
|
||||
/* Return the number of seconds since the beginning of 1970.
|
||||
*/
|
||||
#define CL_Time 0x63
|
||||
/* Time(void)
|
||||
* return(word status, word time)
|
||||
*/
|
||||
|
||||
/* Delete(remove, un-link, wipe, destroy) the file named by the
|
||||
* NULL-terminated string 'name'.
|
||||
*/
|
||||
#define CL_Remove 0x64
|
||||
/* Remove(word nbytes, bytes name)
|
||||
* return(word status)
|
||||
*/
|
||||
|
||||
/* Rename the file specified by the NULL-terminated string 'oname'
|
||||
* to 'nname'.
|
||||
*/
|
||||
#define CL_Rename 0x65
|
||||
/* Rename(word nbytes, bytes oname, word nbytes, bytes nname)
|
||||
* return(word status)
|
||||
*/
|
||||
|
||||
/* 'name' specifies a NULL-terminated string containing a file name or a
|
||||
* device name. Opens the file/device and returns a non-zero handle on
|
||||
* success that can be quoted to CL_Close, CL_Read, CL_Write, CL_Seek,
|
||||
* CL_Flen or CL_IsTTY. The mode is an integer in the range 0-11:-
|
||||
*
|
||||
* Mode: 0 1 2 3 4 5 6 7 8 9 10 11
|
||||
* ANSI C fopen mode: r rb r+ r+b w wb w+ w+b a ab a+ a+b
|
||||
*
|
||||
* Values 12-15 are illegal. If 'name' is ":tt" the stdin/stdout is
|
||||
* opened depending on whether 'mode' is read or write.
|
||||
*/
|
||||
#define CL_Open 0x66
|
||||
/* Open(word nbytes, bytes name, word mode)
|
||||
* return(word handle)
|
||||
*/
|
||||
|
||||
/* 'handle' is a file handle previously returned by CL_Open. CL_Close
|
||||
* closes the file.
|
||||
*/
|
||||
#define CL_Close 0x68
|
||||
/* Close(word handle)
|
||||
* return(word status)
|
||||
*/
|
||||
|
||||
/* Writes data of length nbytes to the file/device specified by
|
||||
* handle. nbtotal represents the total number of bytes to be
|
||||
* written, whereas nbytes is the number of bytes in this packet
|
||||
*
|
||||
* If nbtotal is <= DATASIZE - CL_Write message header size in the
|
||||
* packet then nbytes = nbtotal and the number of bytes not written
|
||||
* is returned. If nbtotal is > the packet size then the CL_Write
|
||||
* must be followed by a number of CL_WriteX's to complete the write,
|
||||
* the nbytes returned by CL_Write can be ignored
|
||||
* If the status word returned is non zero, an error has occurred and
|
||||
* the write request has been aborted.
|
||||
*
|
||||
*/
|
||||
#define CL_Write 0x69
|
||||
/* Write(word handle, word nbtotal, word nbytes, bytes data)
|
||||
* return(word status, word nbytes)
|
||||
*/
|
||||
|
||||
/* Write Extension is a reads a continuation of data from a CL_Write
|
||||
* which was too big to fit in a single packet.
|
||||
* nbytes is the number of bytes of data in this packet, the
|
||||
* returned value of nbytes can be ignored except if it is the
|
||||
* last packet, in which case it is the number of bytes that were NOT
|
||||
* written
|
||||
*/
|
||||
#define CL_WriteX 0x6A
|
||||
/* WriteX(word nbytes, bytes data)
|
||||
* return(word status, word nbytes)
|
||||
*/
|
||||
|
||||
/* Reads 'nbytes' from the file/device specified by 'handle'.
|
||||
*
|
||||
* If nbytes <= DATASIZE then the read will occur in a single packet
|
||||
* and the returned value of nbytes will be the number of bytes actually
|
||||
* read and nbmore will be 0. If nbytes> DATASIZE then multiple packets
|
||||
* will have to be used ie CL_Read followed by 1 or more CL_ReadX
|
||||
* packets. In this case CL_Read will return nbytes read in the current
|
||||
* packet and nbmore representing how many more bytes are expected to be
|
||||
* read
|
||||
* If the status word is non zero then the request has completed with an
|
||||
* error. If the status word is 0xFFFFFFFF (-1) then an EOF condition
|
||||
* has been reached.
|
||||
*/
|
||||
#define CL_Read 0x6B
|
||||
/* Read(word handle, word nbytes)
|
||||
* return(word status, word nbytes, word nbmore, bytes data)
|
||||
*/
|
||||
|
||||
/* Read eXtension returns a continuation of the data that was opened for
|
||||
* read in the earlier CL_Read. The return value nbytes is the number of
|
||||
* data bytes in the packet, nbmore is the number of bytes more that are
|
||||
* expected to be read in subsequent packets.
|
||||
*/
|
||||
#define CL_ReadX 0x6C
|
||||
/* ReadX()
|
||||
* return(word status, word nbytes, word nbmore, bytes data)
|
||||
*/
|
||||
|
||||
/* Seeks to byte position 'posn' in the file/device specified by 'handle'.
|
||||
*/
|
||||
#define CL_Seek 0x6D
|
||||
/* Seek(word handle, word posn)
|
||||
* return(word status)
|
||||
*/
|
||||
|
||||
/* Returns the current length of the file specified by 'handle' in 'len'.
|
||||
* If an error occurs 'len' is set to -1.
|
||||
*/
|
||||
#define CL_Flen 0x6E
|
||||
/* Flen(word handle)
|
||||
* return(word len)
|
||||
*/
|
||||
|
||||
/* Returns NoError if 'handle' specifies an interactive device, otherwise
|
||||
* returns GenError
|
||||
*/
|
||||
#define CL_IsTTY 0x6F
|
||||
/* IsTTY(word handle)
|
||||
* return(word status)
|
||||
*/
|
||||
|
||||
/* Returns a temporary host file name. The maximum length of a file name
|
||||
* is passed to the host. The TargetID is some identifier from the target
|
||||
* for this particular temporary filename. This value is could be used
|
||||
* directly in the generation of the filename.
|
||||
*
|
||||
* If the host cannot create a suitable name or the generated name is too
|
||||
* long then status is non zero. status will be NoError if the host can create
|
||||
* a name.
|
||||
*/
|
||||
#define CL_TmpNam 0x70
|
||||
/* TmpNam(word maxlength, word TargetID)
|
||||
* return(word status, word nbytes, bytes fname)
|
||||
*/
|
||||
|
||||
/* Note there is no message for Exit, EnterOS, InstallHandler or
|
||||
* GenerateError as these will be supported entirely at the host end,
|
||||
* or by the underlying Operating system.
|
||||
*/
|
||||
|
||||
#define CL_UnknownReason (-1)
|
||||
|
||||
extern unsigned int GetRaiseHandler( void );
|
||||
extern unsigned int SysLibraryHandler(unsigned int sysCode, unsigned int *args);
|
||||
extern void angel_SysLibraryInit(void);
|
||||
|
||||
/*
|
||||
* Function: Angel_IsSysHandlerRunning
|
||||
* Purpose: return whether or not SysLibraryHandler is running
|
||||
*
|
||||
* No paramaters
|
||||
*
|
||||
* Returns 1 if SysLibraryHandler is running
|
||||
* 0 otherwise
|
||||
*/
|
||||
extern int Angel_IsSysHandlerRunning(void);
|
||||
|
||||
#ifdef ICEMAN2
|
||||
/* This function exists in an ICEman2 system only, and can be called by
|
||||
* debug support code when the debugger tells it how much memory the
|
||||
* target has. This will then be used to deal with the HEAPINFO SWI
|
||||
*/
|
||||
extern void angel_SetTopMem(unsigned addr);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -1,174 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/*-*-C-*-
|
||||
*
|
||||
*
|
||||
* Project: ANGEL
|
||||
*
|
||||
* Title: Character based packet transmission engine
|
||||
*/
|
||||
|
||||
#include <stdarg.h> /* ANSI varargs support */
|
||||
#include "angel.h" /* Angel system definitions */
|
||||
#include "endian.h" /* Endian independant memory access macros */
|
||||
#include "crc.h" /* crc generation definitions and headers */
|
||||
#include "rxtx.h"
|
||||
#include "channels.h"
|
||||
#include "buffers.h"
|
||||
#include "logging.h"
|
||||
|
||||
/* definitions to describe the engines state */
|
||||
#define N_STX 0x0 /* first 2 bits for N_ */
|
||||
#define N_BODY 0x1
|
||||
#define N_ETX 0x2
|
||||
#define N_IDLE 0x3
|
||||
#define N_MASK 0x3 /* mask for the Encapsulator state */
|
||||
|
||||
#define E_PLAIN (0x0 << 2) /* 3rd bit for E_ */
|
||||
#define E_ESC (0x1 << 2) /* 3rd bit for E_ */
|
||||
#define E_MASK (0x1 << 2) /* mask for the Escaper state */
|
||||
|
||||
#define F_HEAD (0x0 << 3) /* 4th and 5th bits for F_ */
|
||||
#define F_DATA (0x1 << 3)
|
||||
#define F_CRC (0x1 << 4)
|
||||
#define F_MASK (0x3 << 3) /* mask for the Escaper state */
|
||||
|
||||
static unsigned char escape(unsigned char ch_in, struct te_state *txstate);
|
||||
|
||||
void Angel_TxEngineInit(const struct re_config *txconfig,
|
||||
const struct data_packet *packet,
|
||||
struct te_state *txstate){
|
||||
IGNORE(packet);
|
||||
txstate->tx_state = N_STX | E_PLAIN | F_HEAD;
|
||||
txstate->field_c = 0;
|
||||
txstate->encoded = 0;
|
||||
txstate->config = txconfig;
|
||||
txstate->crc = 0;
|
||||
}
|
||||
|
||||
te_status Angel_TxEngine(const struct data_packet *packet,
|
||||
struct te_state *txstate,
|
||||
unsigned char *tx_ch){
|
||||
/* TODO: gaurd on long/bad packets */
|
||||
/*
|
||||
* encapsulate the packet, framing has been moved from a seperate
|
||||
* function into the encapsulation routine as it needed too much
|
||||
* inherited state for it to be sensibly located elsewhere
|
||||
*/
|
||||
switch ((txstate->tx_state) & N_MASK){
|
||||
case N_STX:
|
||||
#ifdef DO_TRACE
|
||||
__rt_trace("txe-stx ");
|
||||
#endif
|
||||
txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_BODY;
|
||||
*tx_ch = txstate->config->stx;
|
||||
txstate->field_c = 3; /* set up for the header */
|
||||
txstate->crc = startCRC32; /* set up basic crc */
|
||||
return TS_IN_PKT;
|
||||
case N_BODY:{
|
||||
switch (txstate->tx_state & F_MASK) {
|
||||
case F_HEAD:
|
||||
#ifdef DO_TRACE
|
||||
__rt_trace("txe-head ");
|
||||
#endif
|
||||
if (txstate->field_c == 3) {
|
||||
/* send type */
|
||||
*tx_ch = escape(packet->type, txstate);
|
||||
return TS_IN_PKT;
|
||||
}
|
||||
else {
|
||||
*tx_ch = escape((packet->len >> (txstate->field_c - 1) * 8) & 0xff,
|
||||
txstate);
|
||||
if (txstate->field_c == 0) {
|
||||
/* move on to the next state */
|
||||
txstate->tx_state = (txstate->tx_state & ~F_MASK) | F_DATA;
|
||||
txstate->field_c = packet->len;
|
||||
}
|
||||
return TS_IN_PKT;
|
||||
}
|
||||
case F_DATA:
|
||||
#ifdef DO_TRACE
|
||||
__rt_trace("txe-data ");
|
||||
#endif
|
||||
*tx_ch = escape(packet->data[packet->len - txstate->field_c], txstate);
|
||||
if (txstate->field_c == 0) {
|
||||
/* move on to the next state */
|
||||
txstate->tx_state = (txstate->tx_state & ~F_MASK) | F_CRC;
|
||||
txstate->field_c = 4;
|
||||
}
|
||||
return TS_IN_PKT;
|
||||
case F_CRC:
|
||||
#ifdef DO_TRACE
|
||||
__rt_trace("txe-crc ");
|
||||
#endif
|
||||
*tx_ch = escape((txstate->crc >> ((txstate->field_c - 1) * 8)) & 0xff,
|
||||
txstate);
|
||||
|
||||
if (txstate->field_c == 0) {
|
||||
#ifdef DO_TRACE
|
||||
__rt_trace("txe crc = 0x%x\n", txstate->crc);
|
||||
#endif
|
||||
/* move on to the next state */
|
||||
txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_ETX;
|
||||
}
|
||||
return TS_IN_PKT;
|
||||
}
|
||||
}
|
||||
case N_ETX:
|
||||
#ifdef DO_TRACE
|
||||
__rt_trace("txe-etx\n");
|
||||
#endif
|
||||
txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_IDLE;
|
||||
*tx_ch = txstate->config->etx;
|
||||
return TS_DONE_PKT;
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
__rt_info("tx default\n");
|
||||
#endif
|
||||
txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_IDLE;
|
||||
return TS_IDLE;
|
||||
}
|
||||
/* stop a silly -Wall warning */
|
||||
return (te_status)-1;
|
||||
}
|
||||
|
||||
/*
|
||||
* crc generation occurs in the escape function because it is the only
|
||||
* place where we know that we're putting a real char into the buffer
|
||||
* rather than an escaped one.
|
||||
* We must be careful here not to update the crc when we're sending it
|
||||
*/
|
||||
static unsigned char escape(unsigned char ch_in, struct te_state *txstate) {
|
||||
if (((txstate->tx_state) & E_MASK) == E_ESC) {
|
||||
/* char has been escaped so send the real char */
|
||||
#ifdef DO_TRACE
|
||||
__rt_trace("txe-echar ");
|
||||
#endif
|
||||
txstate->tx_state = (txstate->tx_state & ~E_MASK) | E_PLAIN;
|
||||
txstate->field_c--;
|
||||
if ((txstate->tx_state & F_MASK) != F_CRC)
|
||||
txstate->crc = crc32( &ch_in, 1, txstate->crc);
|
||||
return ch_in | serial_ESCAPE;
|
||||
}
|
||||
if ((ch_in < 32) && ((txstate->config->esc_set & (1 << ch_in)) != 0)) {
|
||||
/* char needs escaping */
|
||||
#ifdef DO_TRACE
|
||||
__rt_trace("txe-esc ");
|
||||
#endif
|
||||
txstate->tx_state = (txstate->tx_state & ~E_MASK) | E_ESC;
|
||||
return txstate->config->esc;
|
||||
}
|
||||
/* must be a char that can be sent plain */
|
||||
txstate->field_c--;
|
||||
if ((txstate->tx_state & F_MASK) != F_CRC)
|
||||
txstate->crc = crc32(&ch_in, 1, txstate->crc);
|
||||
return ch_in;
|
||||
}
|
||||
|
||||
/* EOF tx.c */
|
|
@ -1,533 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __hpux
|
||||
# define _POSIX_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef __hpux
|
||||
# define _TERMIOS_INCLUDED
|
||||
# include <sys/termio.h>
|
||||
# undef _TERMIOS_INCLUDED
|
||||
#else
|
||||
# include <termios.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifdef sun
|
||||
# include <sys/ioccom.h>
|
||||
# ifdef __svr4__
|
||||
# include <sys/bpp_io.h>
|
||||
# else
|
||||
# include <sbusdev/bpp_io.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef BSD
|
||||
# ifdef sun
|
||||
# include <sys/ttydev.h>
|
||||
# endif
|
||||
# ifdef __alpha
|
||||
# include <sys/ioctl.h>
|
||||
# else
|
||||
# include <sys/filio.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __hpux
|
||||
# define _INCLUDE_HPUX_SOURCE
|
||||
# include <sys/ioctl.h>
|
||||
# undef _INCLUDE_HPUX_SOURCE
|
||||
#endif
|
||||
|
||||
#include "host.h"
|
||||
#include "unixcomm.h"
|
||||
|
||||
#define PP_TIMEOUT 1 /* seconds */
|
||||
|
||||
#ifdef sun
|
||||
#define SERPORT1 "/dev/ttya"
|
||||
#define SERPORT2 "/dev/ttyb"
|
||||
#define PARPORT1 "/dev/bpp0"
|
||||
#define PARPORT2 "/dev/bpp1"
|
||||
#endif
|
||||
|
||||
#ifdef __hpux
|
||||
#define SERPORT1 "/dev/tty00"
|
||||
#define SERPORT2 "/dev/tty01"
|
||||
#define PARPORT1 "/dev/ptr_parallel"
|
||||
#define PARPORT2 "/dev/ptr_parallel"
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
#define SERPORT1 "/dev/cua0"
|
||||
#define SERPORT2 "/dev/cua1"
|
||||
#define PARPORT1 "/dev/par0"
|
||||
#define PARPORT2 "/dev/par1"
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define SERPORT1 "com1"
|
||||
#define SERPORT2 "com2"
|
||||
#define PARPORT1 "lpt1"
|
||||
#define PARPORT2 "lpt2"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Parallel port output pins, used for signalling to target
|
||||
*/
|
||||
|
||||
#ifdef sun
|
||||
struct bpp_pins bp;
|
||||
#endif
|
||||
|
||||
static int serpfd = -1;
|
||||
static int parpfd = -1;
|
||||
|
||||
extern const char *Unix_MatchValidSerialDevice(const char *name)
|
||||
{
|
||||
int i=0;
|
||||
char *sername=NULL;
|
||||
|
||||
/* Accept no name as the default serial port */
|
||||
if (name == NULL) {
|
||||
return SERPORT1;
|
||||
}
|
||||
|
||||
/* Look for the simple cases - 1,2,s,S,/dev/... first, and
|
||||
* afterwards look for S=... clauses, which need parsing properly.
|
||||
*/
|
||||
|
||||
/* Accept /dev/tty* where * is limited */
|
||||
if (strlen(name) == strlen(SERPORT1) && strncmp(name, "/dev/tty", 8) == 0) return name;
|
||||
|
||||
/* Accept "1" or "2" or "S" - S is equivalent to "1" */
|
||||
if (strcmp(name, "1") == 0 ||
|
||||
strcmp(name, "S") == 0 || strcmp(name, "s") == 0) {
|
||||
return SERPORT1;
|
||||
}
|
||||
if (strcmp(name, "2") == 0) return SERPORT2;
|
||||
|
||||
/* It wasn't one of the simple cases, so now we have to parse it
|
||||
* properly
|
||||
*/
|
||||
|
||||
do {
|
||||
switch (name[i]) {
|
||||
case ',':
|
||||
/* Skip over commas */
|
||||
i++;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
/* Unexpected character => error - not matched */
|
||||
|
||||
case 0:
|
||||
/* End of string means return whatever we have matched */
|
||||
return sername;
|
||||
|
||||
case 's':
|
||||
case 'S':
|
||||
case 'h':
|
||||
case 'H': {
|
||||
char ch = tolower(name[i]);
|
||||
int j, continue_from, len;
|
||||
|
||||
/* If the next character is a comma or a NULL then this is
|
||||
* a request for the default Serial port
|
||||
*/
|
||||
if (name[++i] == 0 || name[i] == ',') {
|
||||
if (ch=='s')
|
||||
sername=SERPORT1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Next character must be an = */
|
||||
if (name[i] != '=') return 0;
|
||||
/* Search for the end of the port spec. (ends in NULL or ,) */
|
||||
for (j= ++i; name[j] != 0 && name[j] != ','; j++)
|
||||
; /* Do nothing */
|
||||
/* Notice whether this is the last thing to parse or not
|
||||
* and also calaculate the length of the string
|
||||
*/
|
||||
if (name[j] == '0') continue_from = -1;
|
||||
else continue_from = j;
|
||||
len=(j-i);
|
||||
|
||||
/* And now try to match the serial / parallel port */
|
||||
switch (ch) {
|
||||
case 's': {
|
||||
/* Match serial port */
|
||||
if (len==1) {
|
||||
if (name[i]=='1')
|
||||
sername=SERPORT1;
|
||||
else if (name[i]=='2')
|
||||
sername=SERPORT2;
|
||||
} else if (len==strlen(SERPORT1)) {
|
||||
if (strncmp(name+i,SERPORT1,strlen(SERPORT1)) == 0)
|
||||
sername=SERPORT1;
|
||||
else if (strncmp(name+i,SERPORT2,strlen(SERPORT2)) == 0)
|
||||
sername=SERPORT2;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'h':
|
||||
/* We don't actually deal with the H case here, we just
|
||||
* match it and allow it through.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
if (continue_from == -1) return sername;
|
||||
i = continue_from;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
extern int Unix_IsSerialInUse(void)
|
||||
{
|
||||
if (serpfd >= 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern int Unix_OpenSerial(const char *name)
|
||||
{
|
||||
#if defined(BSD)
|
||||
serpfd = open(name, O_RDWR);
|
||||
#else
|
||||
serpfd = open(name, O_RDWR | O_NONBLOCK);
|
||||
#endif
|
||||
|
||||
if (serpfd < 0) {
|
||||
perror("open");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern void Unix_CloseSerial(void)
|
||||
{
|
||||
if (serpfd >= 0)
|
||||
{
|
||||
(void)close(serpfd);
|
||||
serpfd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
extern int Unix_ReadSerial(unsigned char *buf, int n, bool block)
|
||||
{
|
||||
fd_set fdset;
|
||||
struct timeval tv;
|
||||
int err;
|
||||
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(serpfd, &fdset);
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = (block ? 10000 : 0);
|
||||
|
||||
err = select(serpfd + 1, &fdset, NULL, NULL, &tv);
|
||||
|
||||
if (err < 0 && errno != EINTR)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
perror("select");
|
||||
#endif
|
||||
panic("select failure");
|
||||
return -1;
|
||||
}
|
||||
else if (err > 0 && FD_ISSET(serpfd, &fdset))
|
||||
return read(serpfd, buf, n);
|
||||
else /* err == 0 || FD_CLR(serpfd, &fdset) */
|
||||
{
|
||||
errno = ERRNO_FOR_BLOCKED_IO;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
extern int Unix_WriteSerial(unsigned char *buf, int n)
|
||||
{
|
||||
return write(serpfd, buf, n);
|
||||
}
|
||||
|
||||
extern void Unix_ResetSerial(void)
|
||||
{
|
||||
struct termios terminfo;
|
||||
|
||||
tcgetattr(serpfd, &terminfo);
|
||||
#ifdef __CYGWIN32__
|
||||
/* Expedient, but it works. */
|
||||
terminfo.c_iflag = 0;
|
||||
terminfo.c_oflag = 0;
|
||||
terminfo.c_cflag = 48;
|
||||
terminfo.c_lflag = 0;
|
||||
terminfo.c_cc[VMIN] = 0;
|
||||
terminfo.c_cc[VTIME] = 1;
|
||||
#else
|
||||
terminfo.c_lflag &= ~(ICANON | ISIG | ECHO | IEXTEN);
|
||||
terminfo.c_iflag &= ~(IGNCR | INPCK | ISTRIP | ICRNL | BRKINT);
|
||||
terminfo.c_iflag |= (IXON | IXOFF | IGNBRK);
|
||||
terminfo.c_cflag = (terminfo.c_cflag & ~CSIZE) | CS8 | CREAD;
|
||||
terminfo.c_cflag &= ~PARENB;
|
||||
terminfo.c_cc[VMIN] = 1;
|
||||
terminfo.c_cc[VTIME] = 0;
|
||||
terminfo.c_oflag &= ~OPOST;
|
||||
#endif
|
||||
tcsetattr(serpfd, TCSAFLUSH, &terminfo);
|
||||
}
|
||||
|
||||
extern void Unix_SetSerialBaudRate(int baudrate)
|
||||
{
|
||||
struct termios terminfo;
|
||||
|
||||
tcgetattr(serpfd, &terminfo);
|
||||
cfsetospeed(&terminfo, baudrate);
|
||||
cfsetispeed(&terminfo, baudrate);
|
||||
tcsetattr(serpfd, TCSAFLUSH, &terminfo);
|
||||
}
|
||||
|
||||
extern void Unix_ioctlNonBlocking(void)
|
||||
{
|
||||
#if defined(BSD)
|
||||
int nonblockingIO = 1;
|
||||
(void)ioctl(serpfd, FIONBIO, &nonblockingIO);
|
||||
|
||||
if (parpfd != -1)
|
||||
(void)ioctl(parpfd, FIONBIO, &nonblockingIO);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern void Unix_IsValidParallelDevice(
|
||||
const char *portstring, char **sername, char **parname)
|
||||
{
|
||||
int i=0;
|
||||
*sername=NULL;
|
||||
*parname=NULL;
|
||||
|
||||
/* Do not recognise a NULL portstring */
|
||||
if (portstring==NULL) return;
|
||||
|
||||
do {
|
||||
switch (portstring[i]) {
|
||||
case ',':
|
||||
/* Skip over commas */
|
||||
i++;
|
||||
break;
|
||||
|
||||
default:
|
||||
case 0:
|
||||
/* End of string or bad characcter means we have finished */
|
||||
return;
|
||||
|
||||
case 's':
|
||||
case 'S':
|
||||
case 'p':
|
||||
case 'P':
|
||||
case 'h':
|
||||
case 'H': {
|
||||
char ch = tolower(portstring[i]);
|
||||
int j, continue_from, len;
|
||||
|
||||
/* If the next character is a comma or a NULL then this is
|
||||
* a request for the default Serial or Parallel port
|
||||
*/
|
||||
if (portstring[++i] == 0 || portstring[i] == ',') {
|
||||
if (ch=='s') *sername=SERPORT1;
|
||||
else if (ch=='p') *parname=PARPORT1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Next character must be an = */
|
||||
if (portstring[i] != '=') return;
|
||||
/* Search for the end of the port spec. (ends in NULL or ,) */
|
||||
for (j= ++i; portstring[j] != 0 && portstring[j] != ','; j++)
|
||||
; /* Do nothing */
|
||||
/* Notice whether this is the last thing to parse or not
|
||||
* and also calaculate the length of the string
|
||||
*/
|
||||
if (portstring[j] == '0') continue_from = -1;
|
||||
else continue_from = j;
|
||||
len=(j-i);
|
||||
|
||||
/* And now try to match the serial / parallel port */
|
||||
switch (ch) {
|
||||
case 's': {
|
||||
/* Match serial port */
|
||||
if (len==1) {
|
||||
if (portstring[i]=='1') *sername=SERPORT1;
|
||||
else if (portstring[i]=='2') *sername=SERPORT2;
|
||||
} else if (len==strlen(SERPORT1)) {
|
||||
if (strncmp(portstring+i,SERPORT1,strlen(SERPORT1)) == 0)
|
||||
*sername=SERPORT1;
|
||||
else if (strncmp(portstring+i,SERPORT2,strlen(SERPORT2)) == 0)
|
||||
*sername=SERPORT2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'p': {
|
||||
/* Match parallel port */
|
||||
if (len==1) {
|
||||
if (portstring[i]=='1') *parname=PARPORT1;
|
||||
else if (portstring[i]=='2') *parname=PARPORT2;
|
||||
} else if (len==strlen(PARPORT1)) {
|
||||
if (strncmp(portstring+i,PARPORT1,strlen(PARPORT1)) == 0)
|
||||
*parname=PARPORT1;
|
||||
else if (strncmp(portstring+i,PARPORT2,strlen(PARPORT2)) == 0)
|
||||
*parname=PARPORT2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'h':
|
||||
/* We don't actually deal with the H case here, we just
|
||||
* match it and allow it through.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
if (continue_from == -1) return;
|
||||
i = continue_from;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (1);
|
||||
return; /* Will never get here */
|
||||
}
|
||||
|
||||
extern int Unix_IsParallelInUse(void)
|
||||
{
|
||||
if (parpfd >= 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern int Unix_OpenParallel(const char *name)
|
||||
{
|
||||
#if defined(BSD)
|
||||
parpfd = open(name, O_RDWR);
|
||||
#else
|
||||
parpfd = open(name, O_RDWR | O_NONBLOCK);
|
||||
#endif
|
||||
|
||||
if (parpfd < 0)
|
||||
{
|
||||
char errbuf[256];
|
||||
|
||||
sprintf(errbuf, "open %s", name);
|
||||
perror(errbuf);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern void Unix_CloseParallel(void)
|
||||
{
|
||||
if (parpfd >= 0)
|
||||
{
|
||||
(void)close(parpfd);
|
||||
parpfd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern unsigned int Unix_WriteParallel(unsigned char *buf, int n)
|
||||
{
|
||||
int ngone;
|
||||
|
||||
if ((ngone = write(parpfd, buf, n)) < 0)
|
||||
{
|
||||
/*
|
||||
* we ignore errors (except for debug purposes)
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
char errbuf[256];
|
||||
|
||||
sprintf(errbuf, "send_packet: write");
|
||||
perror(errbuf);
|
||||
#endif
|
||||
ngone = 0;
|
||||
}
|
||||
|
||||
/* finished */
|
||||
return (unsigned int)ngone;
|
||||
}
|
||||
|
||||
|
||||
#ifdef sun
|
||||
extern void Unix_ResetParallel(void)
|
||||
{
|
||||
struct bpp_transfer_parms tp;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("serpar_reset\n");
|
||||
#endif
|
||||
|
||||
/*
|
||||
* we need to set the parallel port up for BUSY handshaking,
|
||||
* and select the timeout
|
||||
*/
|
||||
if (ioctl(parpfd, BPPIOC_GETPARMS, &tp) < 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
perror("ioctl(BPPIOCGETPARMS)");
|
||||
#endif
|
||||
panic("serpar_reset: cannot get BPP parameters");
|
||||
}
|
||||
|
||||
tp.write_handshake = BPP_BUSY_HS;
|
||||
tp.write_timeout = PP_TIMEOUT;
|
||||
|
||||
if (ioctl(parpfd, BPPIOC_SETPARMS, &tp) < 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
perror("ioctl(BPPIOC_SETPARMS)");
|
||||
#endif
|
||||
panic("serpar_reset: cannot set BPP parameters");
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* Parallel not supported on HP */
|
||||
|
||||
extern void Unix_ResetParallel(void)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,210 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
|
||||
*
|
||||
* This software may be freely used, copied, modified, and distributed
|
||||
* provided that the above copyright notice is preserved in all copies of the
|
||||
* software.
|
||||
*/
|
||||
|
||||
/* -*-C-*-
|
||||
*
|
||||
*
|
||||
*/
|
||||
#ifndef angsd_unixcomm_h
|
||||
#define angsd_unixcomm_h
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(BSD)
|
||||
# define ERRNO_FOR_BLOCKED_IO EWOULDBLOCK
|
||||
#else
|
||||
# define ERRNO_FOR_BLOCKED_IO EAGAIN
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Function: Unix_MatchValidSerialDevice
|
||||
* Purpose: check that the serial driver/port name is valid
|
||||
* and return the actual device name if it is.
|
||||
*
|
||||
* Params:
|
||||
* Input: name Name of device going to be used
|
||||
*
|
||||
* Returns:
|
||||
* OK: Pointer to name of the device matched
|
||||
* Error or unrecognised deivce: 0
|
||||
*/
|
||||
extern const char *Unix_MatchValidSerialDevice(const char *name);
|
||||
|
||||
/*
|
||||
* Function: Unix_IsSerialInUse
|
||||
* Purpose: check whether the serial port is in use
|
||||
*
|
||||
* Params:
|
||||
* Input: Nothing
|
||||
*
|
||||
* Returns:
|
||||
* OK: 0 Serial device not in use
|
||||
* Error: -1 Serial device in use
|
||||
*/
|
||||
extern int Unix_IsSerialInUse(void);
|
||||
|
||||
/*
|
||||
* Function: Unix_OpenSerial
|
||||
* Purpose: open the serial port
|
||||
*
|
||||
* Params:
|
||||
* Input: name Name of device to open
|
||||
*
|
||||
* Returns: Unix 'open' returns
|
||||
*/
|
||||
extern int Unix_OpenSerial(const char *name);
|
||||
|
||||
/*
|
||||
* Function: Unix_CloseSerial
|
||||
* Purpose: close the serial port
|
||||
*
|
||||
* Params:
|
||||
* Input: Nothing
|
||||
*
|
||||
* Returns: Nothing
|
||||
*/
|
||||
extern void Unix_CloseSerial(void);
|
||||
|
||||
/*
|
||||
* Function: Unix_ReadSerial
|
||||
* Purpose: reads a specified number of bytes (or less) from the serial port
|
||||
*
|
||||
* Params:
|
||||
* Input: buf Buffer to store read bytes
|
||||
* n Maximum number of bytes to read
|
||||
*
|
||||
* Returns: Unix 'read' returns
|
||||
*/
|
||||
extern int Unix_ReadSerial(unsigned char *buf, int n, bool block);
|
||||
|
||||
/*
|
||||
* Function: Unix_WriteSerial
|
||||
* Purpose: writes a specified number of bytes (or less) to the serial port
|
||||
*
|
||||
* Params:
|
||||
* Input: buf Buffer to write bytes from
|
||||
* n Maximum number of bytes to write
|
||||
*
|
||||
* Returns: Unix 'write' returns
|
||||
*/
|
||||
extern int Unix_WriteSerial(unsigned char *buf, int n);
|
||||
|
||||
/*
|
||||
* Function: Unix_ResetSerial
|
||||
* Purpose: resets the serial port for another operation
|
||||
*
|
||||
* Params:
|
||||
* Input: Nothing
|
||||
*
|
||||
* Returns: Nothing
|
||||
*/
|
||||
extern void Unix_ResetSerial(void);
|
||||
|
||||
/*
|
||||
* Function: Unix_SetSerialBaudRate
|
||||
* Purpose: check that the serial driver/port name is valid
|
||||
*
|
||||
* Params:
|
||||
* Input: baudrate termios value for baud rate
|
||||
*
|
||||
* Returns: Nothing
|
||||
*/
|
||||
extern void Unix_SetSerialBaudRate(int baudrate);
|
||||
|
||||
/*
|
||||
* Function: Unix_ioctlNonBlocking
|
||||
* Purpose: sets the serial port to non-blocking IO
|
||||
*
|
||||
* Params:
|
||||
* Input: Nothing
|
||||
*
|
||||
* Returns: Nothing
|
||||
*/
|
||||
extern void Unix_ioctlNonBlocking(void);
|
||||
|
||||
/*
|
||||
* Function: Unix_IsValidParallelDevice
|
||||
* Purpose: check whether the combined serial and parallel device specification
|
||||
* is ok, and return the ports selected
|
||||
*
|
||||
* Params:
|
||||
* Input: portstring - is a string which specifies which serial
|
||||
* and parallel ports are to be used. Can
|
||||
* include s=<val> and p=<val> separated by a
|
||||
* comma.
|
||||
*
|
||||
* Returns:
|
||||
* Output: *sername - returns the device name of the chosen serial port
|
||||
* *parname - returns the device name of the chosen parallel port
|
||||
* If either of these is NULL on return then the match failed.
|
||||
*/
|
||||
extern void Unix_IsValidParallelDevice(
|
||||
const char *portstring, char **sername, char **parname
|
||||
);
|
||||
|
||||
/*
|
||||
* Function: Unix_IsParallelInUse
|
||||
* Purpose: check whether the parallel port is in use
|
||||
*
|
||||
* Params:
|
||||
* Input: Nothing
|
||||
*
|
||||
* Returns:
|
||||
* OK: 0 Parallel device not in use
|
||||
* Error: -1 Parallel device in use
|
||||
*/
|
||||
extern int Unix_IsParallelInUse(void);
|
||||
|
||||
/*
|
||||
* Function: Unix_OpenParallel
|
||||
* Purpose: open the parallel port
|
||||
*
|
||||
* Params:
|
||||
* Input: name Name of device to open
|
||||
*
|
||||
* Returns: Unix 'open' returns
|
||||
*/
|
||||
extern int Unix_OpenParallel(const char *name);
|
||||
|
||||
/*
|
||||
* Function: Unix_CloseParallel
|
||||
* Purpose: close the parallel port
|
||||
*
|
||||
* Params:
|
||||
* Input: Nothing
|
||||
*
|
||||
* Returns: Nothing
|
||||
*/
|
||||
extern void Unix_CloseParallel(void);
|
||||
|
||||
/*
|
||||
* Function: Unix_WriteParallel
|
||||
* Purpose: writes a specified number of bytes (or less) to the parallel port
|
||||
*
|
||||
* Params:
|
||||
* Input: buf Buffer to write bytes from
|
||||
* n Maximum number of bytes to write
|
||||
*
|
||||
* Returns: Unix 'write' returns
|
||||
*/
|
||||
extern unsigned int Unix_WriteParallel(unsigned char *buf, int n);
|
||||
|
||||
/*
|
||||
* Function: Unix_ResetParallel
|
||||
* Purpose: resets the parallel port for another operation
|
||||
*
|
||||
* Params:
|
||||
* Input: Nothing
|
||||
*
|
||||
* Returns: Nothing
|
||||
*/
|
||||
extern void Unix_ResetParallel(void);
|
||||
|
||||
#endif /* ndef angsd_unixcomm_h */
|
||||
|
||||
/* EOF unixcomm.h */
|
|
@ -1,159 +0,0 @@
|
|||
@ignore
|
||||
This file is completely identical to hsuser.texinfo, except that it has the
|
||||
reference to the programming manual removed. There are definately better ways
|
||||
to do this!
|
||||
|
||||
This file documents the user interface to the GNU History library.
|
||||
|
||||
Copyright (C) 1988, 1991 Free Software Foundation, Inc.
|
||||
Authored by Brian Fox.
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of this manual
|
||||
provided the copyright notice and this permission notice are preserved on
|
||||
all copies.
|
||||
|
||||
Permission is granted to process this file through Tex and print the
|
||||
results, provided the printed document carries copying permission notice
|
||||
identical to this one except for the removal of this paragraph (this
|
||||
paragraph not being relevant to the printed manual).
|
||||
|
||||
Permission is granted to copy and distribute modified versions of this
|
||||
manual under the conditions for verbatim copying, provided also that the
|
||||
GNU Copyright statement is available to the distributee, and provided that
|
||||
the entire resulting derived work is distributed under the terms of a
|
||||
permission notice identical to this one.
|
||||
|
||||
Permission is granted to copy and distribute translations of this manual
|
||||
into another language, under the above conditions for modified versions.
|
||||
@end ignore
|
||||
|
||||
@node Using History Interactively
|
||||
@appendix Using History Interactively
|
||||
|
||||
This chapter describes how to use the GNU History Library interactively,
|
||||
from a user's standpoint.
|
||||
|
||||
@menu
|
||||
* History Interaction:: What it feels like using History as a user.
|
||||
@end menu
|
||||
|
||||
@node History Interaction
|
||||
@section History Interaction
|
||||
@cindex expansion
|
||||
|
||||
The History library provides a history expansion feature similar
|
||||
to the history expansion in @code{csh}. The following text describes the
|
||||
syntax you use to manipulate history information.
|
||||
|
||||
History expansion takes two parts. In the first part, determine
|
||||
which line from the previous history will be used for substitution.
|
||||
This line is called the @dfn{event}.
|
||||
In the second part, select portions of that line for inclusion into the
|
||||
current line. These portions are called @dfn{words}.
|
||||
@value{GDBN} breaks the line into words in the same
|
||||
way that the Bash shell does, so that several English (or Unix) words
|
||||
surrounded by quotes are considered one word.
|
||||
|
||||
@menu
|
||||
* Event Designators:: How to specify which history line to use.
|
||||
* Word Designators:: Specifying which words are of interest.
|
||||
* Modifiers:: Modifying the results of susbstitution.
|
||||
@end menu
|
||||
|
||||
@node Event Designators
|
||||
@subsection Event Designators
|
||||
@cindex event designators
|
||||
|
||||
An @dfn{event designator} is a reference to a command line entry in the
|
||||
history list.
|
||||
|
||||
@table @asis
|
||||
|
||||
@item @code{!}
|
||||
Start a history subsititution, except when followed by a space, tab, or
|
||||
the end of the line... @key{=} or @key{(}.
|
||||
|
||||
@item @code{!!}
|
||||
Refer to the previous command. This is a synonym for @code{!-1}.
|
||||
|
||||
@item @code{!n}
|
||||
Refer to command line @var{n}.
|
||||
|
||||
@item @code{!-n}
|
||||
Refer to the command line @var{n} lines back.
|
||||
|
||||
@item @code{!string}
|
||||
Refer to the most recent command starting with @var{string}.
|
||||
|
||||
@item @code{!?string}[@code{?}]
|
||||
Refer to the most recent command containing @var{string}.
|
||||
|
||||
@end table
|
||||
|
||||
@node Word Designators
|
||||
@subsection Word Designators
|
||||
|
||||
A @key{:} separates the event designator from the @dfn{word designator}.
|
||||
It can be omitted if the word designator begins with a @key{^}, @key{$},
|
||||
@key{*} or @key{%}. Words are numbered from the beginning of the line,
|
||||
with the first word being denoted by a 0 (zero).
|
||||
|
||||
@table @code
|
||||
|
||||
@item 0 (zero)
|
||||
The zero'th word. For many applications, this is the command word.
|
||||
|
||||
@item n
|
||||
The @var{n}'th word.
|
||||
|
||||
@item ^
|
||||
The first argument. that is, word 1.
|
||||
|
||||
@item $
|
||||
The last argument.
|
||||
|
||||
@item %
|
||||
The word matched by the most recent @code{?string?} search.
|
||||
|
||||
@item x-y
|
||||
A range of words; @code{-@var{y}} Abbreviates @code{0-@var{y}}.
|
||||
|
||||
@item *
|
||||
All of the words, excepting the zero'th. This is a synonym for @code{1-$}.
|
||||
It is not an error to use @key{*} if there is just one word in the event.
|
||||
The empty string is returned in that case.
|
||||
|
||||
@end table
|
||||
|
||||
@node Modifiers
|
||||
@subsection Modifiers
|
||||
|
||||
After the optional word designator, you can add a sequence of one or more
|
||||
of the following @dfn{modifiers}, each preceded by a @key{:}.
|
||||
|
||||
@table @code
|
||||
|
||||
@item #
|
||||
The entire command line typed so far. This means the current command,
|
||||
not the previous command.
|
||||
@c
|
||||
@c FIXME: If it doesn't belong here, let's put it where it does.
|
||||
@c
|
||||
@c so it technically isn't a word designator and doesn't belong in
|
||||
@c this section.
|
||||
|
||||
@item h
|
||||
Remove a trailing pathname component, leaving only the head.
|
||||
|
||||
@item r
|
||||
Remove a trailing suffix of the form @samp{.}@var{suffix}, leaving the basename.
|
||||
|
||||
@item e
|
||||
Remove all but the suffix.
|
||||
|
||||
@item t
|
||||
Remove all leading pathname components, leaving the tail.
|
||||
|
||||
@item p
|
||||
Print the new command but do not execute it.
|
||||
@end table
|
|
@ -1,566 +0,0 @@
|
|||
@ignore
|
||||
This file documents the end user interface to the GNU command line
|
||||
editing feautres. It is to be an appendix to manuals for programs which
|
||||
use these features. There is a document entitled "readline.texinfo"
|
||||
which contains both end-user and programmer documentation for the GNU
|
||||
Readline Library.
|
||||
|
||||
Copyright (C) 1988 Free Software Foundation, Inc.
|
||||
|
||||
Authored by Brian Fox.
|
||||
|
||||
Permission is granted to process this file through Tex and print the
|
||||
results, provided the printed document carries copying permission notice
|
||||
identical to this one except for the removal of this paragraph (this
|
||||
paragraph not being relevant to the printed manual).
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of this manual
|
||||
provided the copyright notice and this permission notice are preserved on
|
||||
all copies.
|
||||
|
||||
Permission is granted to copy and distribute modified versions of this
|
||||
manual under the conditions for verbatim copying, provided also that the
|
||||
GNU Copyright statement is available to the distributee, and provided that
|
||||
the entire resulting derived work is distributed under the terms of a
|
||||
permission notice identical to this one.
|
||||
|
||||
Permission is granted to copy and distribute translations of this manual
|
||||
into another language, under the above conditions for modified versions.
|
||||
@end ignore
|
||||
|
||||
@node Command Line Editing
|
||||
@appendix Command Line Editing
|
||||
|
||||
This text describes GNU's command line editing interface.
|
||||
|
||||
@menu
|
||||
* Introduction and Notation:: Notation used in this text.
|
||||
* Readline Interaction:: The minimum set of commands for editing a line.
|
||||
* Readline Init File:: Customizing Readline from a user's view.
|
||||
@end menu
|
||||
|
||||
@node Introduction and Notation
|
||||
@section Introduction to Line Editing
|
||||
|
||||
The following paragraphs describe the notation we use to represent
|
||||
keystrokes.
|
||||
|
||||
The text @key{C-k} is read as `Control-K' and describes the character
|
||||
produced when the Control key is depressed and the @key{k} key is struck.
|
||||
|
||||
The text @key{M-k} is read as `Meta-K' and describes the character
|
||||
produced when the meta key (if you have one) is depressed, and the @key{k}
|
||||
key is struck. If you do not have a meta key, the identical keystroke
|
||||
can be generated by typing @key{ESC} @i{first}, and then typing @key{k}.
|
||||
Either process is known as @dfn{metafying} the @key{k} key.
|
||||
|
||||
The text @key{M-C-k} is read as `Meta-Control-k' and describes the
|
||||
character produced by @dfn{metafying} @key{C-k}.
|
||||
|
||||
In addition, several keys have their own names. Specifically,
|
||||
@key{DEL}, @key{ESC}, @key{LFD}, @key{SPC}, @key{RET}, and @key{TAB} all
|
||||
stand for themselves when seen in this text, or in an init file
|
||||
(@pxref{Readline Init File}, for more info).
|
||||
|
||||
@node Readline Interaction
|
||||
@section Readline Interaction
|
||||
@cindex interaction, readline
|
||||
|
||||
Often during an interactive session you type in a long line of text,
|
||||
only to notice that the first word on the line is misspelled. The
|
||||
Readline library gives you a set of commands for manipulating the text
|
||||
as you type it in, allowing you to just fix your typo, and not forcing
|
||||
you to retype the majority of the line. Using these editing commands,
|
||||
you move the cursor to the place that needs correction, and delete or
|
||||
insert the text of the corrections. Then, when you are satisfied with
|
||||
the line, you simply press @key{RET}. You do not have to be at the
|
||||
end of the line to press @key{RET}; the entire line is accepted
|
||||
regardless of the location of the cursor within the line.
|
||||
|
||||
@menu
|
||||
* Readline Bare Essentials:: The least you need to know about Readline.
|
||||
* Readline Movement Commands:: Moving about the input line.
|
||||
* Readline Killing Commands:: How to delete text, and how to get it back!
|
||||
* Readline Arguments:: Giving numeric arguments to commands.
|
||||
@end menu
|
||||
|
||||
@node Readline Bare Essentials
|
||||
@subsection Readline Bare Essentials
|
||||
|
||||
In order to enter characters into the line, simply type them. The typed
|
||||
character appears where the cursor was, and then the cursor moves one
|
||||
space to the right. If you mistype a character, you can use @key{DEL} to
|
||||
back up, and delete the mistyped character.
|
||||
|
||||
Sometimes you may miss typing a character that you wanted to type, and
|
||||
not notice your error until you have typed several other characters. In
|
||||
that case, you can type @key{C-b} to move the cursor to the left, and then
|
||||
correct your mistake. Aftwerwards, you can move the cursor to the right
|
||||
with @key{C-f}.
|
||||
|
||||
When you add text in the middle of a line, you will notice that characters
|
||||
to the right of the cursor get `pushed over' to make room for the text
|
||||
that you have inserted. Likewise, when you delete text behind the cursor,
|
||||
characters to the right of the cursor get `pulled back' to fill in the
|
||||
blank space created by the removal of the text. A list of the basic bare
|
||||
essentials for editing the text of an input line follows.
|
||||
|
||||
@table @asis
|
||||
@item @key{C-b}
|
||||
Move back one character.
|
||||
@item @key{C-f}
|
||||
Move forward one character.
|
||||
@item @key{DEL}
|
||||
Delete the character to the left of the cursor.
|
||||
@item @key{C-d}
|
||||
Delete the character underneath the cursor.
|
||||
@item @w{Printing characters}
|
||||
Insert itself into the line at the cursor.
|
||||
@item @key{C-_}
|
||||
Undo the last thing that you did. You can undo all the way back to an
|
||||
empty line.
|
||||
@end table
|
||||
|
||||
@node Readline Movement Commands
|
||||
@subsection Readline Movement Commands
|
||||
|
||||
The above table describes the most basic possible keystrokes that you need
|
||||
in order to do editing of the input line. For your convenience, many
|
||||
other commands have been added in addition to @key{C-b}, @key{C-f},
|
||||
@key{C-d}, and @key{DEL}. Here are some commands for moving more rapidly
|
||||
about the line.
|
||||
|
||||
@table @key
|
||||
@item C-a
|
||||
Move to the start of the line.
|
||||
@item C-e
|
||||
Move to the end of the line.
|
||||
@item M-f
|
||||
Move forward a word.
|
||||
@item M-b
|
||||
Move backward a word.
|
||||
@item C-l
|
||||
Clear the screen, reprinting the current line at the top.
|
||||
@end table
|
||||
|
||||
Notice how @key{C-f} moves forward a character, while @key{M-f} moves
|
||||
forward a word. It is a loose convention that control keystrokes
|
||||
operate on characters while meta keystrokes operate on words.
|
||||
|
||||
@node Readline Killing Commands
|
||||
@subsection Readline Killing Commands
|
||||
|
||||
@dfn{Killing} text means to delete the text from the line, but to save
|
||||
it away for later use, usually by @dfn{yanking} it back into the line.
|
||||
If the description for a command says that it `kills' text, then you can
|
||||
be sure that you can get the text back in a different (or the same)
|
||||
place later.
|
||||
|
||||
Here is the list of commands for killing text.
|
||||
|
||||
@table @key
|
||||
@item C-k
|
||||
Kill the text from the current cursor position to the end of the line.
|
||||
|
||||
@item M-d
|
||||
Kill from the cursor to the end of the current word, or if between
|
||||
words, to the end of the next word.
|
||||
|
||||
@item M-DEL
|
||||
Kill from the cursor to the start of the previous word, or if between
|
||||
words, to the start of the previous word.
|
||||
|
||||
@item C-w
|
||||
Kill from the cursor to the previous whitespace. This is different than
|
||||
@key{M-DEL} because the word boundaries differ.
|
||||
|
||||
@end table
|
||||
|
||||
And, here is how to @dfn{yank} the text back into the line.
|
||||
|
||||
@table @key
|
||||
@item C-y
|
||||
Yank the most recently killed text back into the buffer at the cursor.
|
||||
|
||||
@item M-y
|
||||
Rotate the kill-ring, and yank the new top. You can only do this if
|
||||
the prior command is @key{C-y} or @key{M-y}.
|
||||
@end table
|
||||
|
||||
When you use a kill command, the text is saved in a @dfn{kill-ring}.
|
||||
Any number of consecutive kills save all of the killed text together, so
|
||||
that when you yank it back, you get it in one clean sweep. The kill
|
||||
ring is not line specific; the text that you killed on a previously
|
||||
typed line is available to be yanked back later, when you are typing
|
||||
another line.
|
||||
|
||||
@node Readline Arguments
|
||||
@subsection Readline Arguments
|
||||
|
||||
You can pass numeric arguments to Readline commands. Sometimes the
|
||||
argument acts as a repeat count, other times it is the @i{sign} of the
|
||||
argument that is significant. If you pass a negative argument to a
|
||||
command which normally acts in a forward direction, that command will
|
||||
act in a backward direction. For example, to kill text back to the
|
||||
start of the line, you might type @key{M--} @key{C-k}.
|
||||
|
||||
The general way to pass numeric arguments to a command is to type meta
|
||||
digits before the command. If the first `digit' you type is a minus
|
||||
sign (@key{-}), then the sign of the argument will be negative. Once
|
||||
you have typed one meta digit to get the argument started, you can type
|
||||
the remainder of the digits, and then the command. For example, to give
|
||||
the @key{C-d} command an argument of 10, you could type @key{M-1 0 C-d}.
|
||||
|
||||
|
||||
@node Readline Init File
|
||||
@section Readline Init File
|
||||
|
||||
Although the Readline library comes with a set of @sc{gnu} Emacs-like
|
||||
keybindings, it is possible that you would like to use a different set
|
||||
of keybindings. You can customize programs that use Readline by putting
|
||||
commands in an @dfn{init} file in your home directory. The name of this
|
||||
file is @file{~/.inputrc}.
|
||||
|
||||
When a program which uses the Readline library starts up, the
|
||||
@file{~/.inputrc} file is read, and the keybindings are set.
|
||||
|
||||
In addition, the @key{C-x C-r} command re-reads this init file, thus
|
||||
incorporating any changes that you might have made to it.
|
||||
|
||||
@menu
|
||||
* Readline Init Syntax:: Syntax for the commands in @file{~/.inputrc}.
|
||||
* Readline vi Mode:: Switching to @code{vi} mode in Readline.
|
||||
@end menu
|
||||
|
||||
@node Readline Init Syntax
|
||||
@subsection Readline Init Syntax
|
||||
|
||||
There are only four constructs allowed in the @file{~/.inputrc}
|
||||
file:
|
||||
|
||||
@table @asis
|
||||
@item Variable Settings
|
||||
You can change the state of a few variables in Readline. You do this by
|
||||
using the @code{set} command within the init file. Here is how you
|
||||
would specify that you wish to use @code{vi} line editing commands:
|
||||
|
||||
@example
|
||||
set editing-mode vi
|
||||
@end example
|
||||
|
||||
Right now, there are only a few variables which can be set; so few in
|
||||
fact, that we just iterate them here:
|
||||
|
||||
@table @code
|
||||
|
||||
@item editing-mode
|
||||
@vindex editing-mode
|
||||
The @code{editing-mode} variable controls which editing mode you are
|
||||
using. By default, @sc{gnu} Readline starts up in Emacs editing mode, where
|
||||
the keystrokes are most similar to Emacs. This variable can either be
|
||||
set to @code{emacs} or @code{vi}.
|
||||
|
||||
@item horizontal-scroll-mode
|
||||
@vindex horizontal-scroll-mode
|
||||
This variable can either be set to @code{On} or @code{Off}. Setting it
|
||||
to @code{On} means that the text of the lines that you edit will scroll
|
||||
horizontally on a single screen line when they are larger than the width
|
||||
of the screen, instead of wrapping onto a new screen line. By default,
|
||||
this variable is set to @code{Off}.
|
||||
|
||||
@item mark-modified-lines
|
||||
@vindex mark-modified-lines
|
||||
This variable when set to @code{On}, says to display an asterisk
|
||||
(@samp{*}) at the starts of history lines which have been modified.
|
||||
This variable is off by default.
|
||||
|
||||
@item prefer-visible-bell
|
||||
@vindex prefer-visible-bell
|
||||
If this variable is set to @code{On} it means to use a visible bell if
|
||||
one is available, rather than simply ringing the terminal bell. By
|
||||
default, the value is @code{Off}.
|
||||
@end table
|
||||
|
||||
@item Key Bindings
|
||||
The syntax for controlling keybindings in the @file{~/.inputrc} file is
|
||||
simple. First you have to know the @i{name} of the command that you
|
||||
want to change. The following pages contain tables of the command name,
|
||||
the default keybinding, and a short description of what the command
|
||||
does.
|
||||
|
||||
Once you know the name of the command, simply place the name of the key
|
||||
you wish to bind the command to, a colon, and then the name of the
|
||||
command on a line in the @file{~/.inputrc} file. The name of the key
|
||||
can be expressed in different ways, depending on which is most
|
||||
comfortable for you.
|
||||
|
||||
@table @asis
|
||||
@item @w{@var{keyname}: @var{function-name} or @var{macro}}
|
||||
@var{keyname} is the name of a key spelled out in English. For example:
|
||||
@example
|
||||
Control-u: universal-argument
|
||||
Meta-Rubout: backward-kill-word
|
||||
Control-o: ">&output"
|
||||
@end example
|
||||
|
||||
In the above example, @key{C-u} is bound to the function
|
||||
@code{universal-argument}, and @key{C-o} is bound to run the macro
|
||||
expressed on the right hand side (that is, to insert the text
|
||||
@samp{>&output} into the line).
|
||||
|
||||
@item @w{"@var{keyseq}": @var{function-name} or @var{macro}}
|
||||
@var{keyseq} differs from @var{keyname} above in that strings denoting
|
||||
an entire key sequence can be specified. Simply place the key sequence
|
||||
in double quotes. @sc{gnu} Emacs style key escapes can be used, as in the
|
||||
following example:
|
||||
|
||||
@example
|
||||
"\C-u": universal-argument
|
||||
"\C-x\C-r": re-read-init-file
|
||||
"\e[11~": "Function Key 1"
|
||||
@end example
|
||||
|
||||
In the above example, @key{C-u} is bound to the function
|
||||
@code{universal-argument} (just as it was in the first example),
|
||||
@key{C-x C-r} is bound to the function @code{re-read-init-file}, and
|
||||
@key{ESC [ 1 1 ~} is bound to insert the text @samp{Function Key 1}.
|
||||
|
||||
@end table
|
||||
@end table
|
||||
|
||||
@menu
|
||||
* Commands For Moving:: Moving about the line.
|
||||
* Commands For History:: Getting at previous lines.
|
||||
* Commands For Text:: Commands for changing text.
|
||||
* Commands For Killing:: Commands for killing and yanking.
|
||||
* Numeric Arguments:: Specifying numeric arguments, repeat counts.
|
||||
* Commands For Completion:: Getting Readline to do the typing for you.
|
||||
* Miscellaneous Commands:: Other miscillaneous commands.
|
||||
@end menu
|
||||
|
||||
@need 2000
|
||||
@node Commands For Moving
|
||||
@subsubsection Commands For Moving
|
||||
|
||||
@ftable @code
|
||||
@item beginning-of-line (@key{C-a})
|
||||
Move to the start of the current line.
|
||||
|
||||
@item end-of-line (@key{C-e})
|
||||
Move to the end of the line.
|
||||
|
||||
@item forward-char (@key{C-f})
|
||||
Move forward a character.
|
||||
|
||||
@item backward-char (@key{C-b})
|
||||
Move back a character.
|
||||
|
||||
@item forward-word (@key{M-f})
|
||||
Move forward to the end of the next word.
|
||||
|
||||
@item backward-word (@key{M-b})
|
||||
Move back to the start of this, or the previous, word.
|
||||
|
||||
@item clear-screen (@key{C-l})
|
||||
Clear the screen leaving the current line at the top of the screen.
|
||||
|
||||
@end ftable
|
||||
|
||||
@need 2000
|
||||
@node Commands For History
|
||||
@subsubsection Commands For Manipulating The History
|
||||
|
||||
@ftable @code
|
||||
@item accept-line (Newline, Return)
|
||||
Accept the line regardless of where the cursor is. If this line is
|
||||
non-empty, add it to the history list. If this line was a history
|
||||
line, then restore the history line to its original state.
|
||||
|
||||
@item previous-history (@key{C-p})
|
||||
Move `up' through the history list.
|
||||
|
||||
@item next-history (@key{C-n})
|
||||
Move `down' through the history list.
|
||||
|
||||
@item beginning-of-history (@key{M-<})
|
||||
Move to the first line in the history.
|
||||
|
||||
@item end-of-history (@key{M->})
|
||||
Move to the end of the input history, i.e., the line you are entering.
|
||||
|
||||
@item reverse-search-history (@key{C-r})
|
||||
Search backward starting at the current line and moving `up' through
|
||||
the history as necessary. This is an incremental search.
|
||||
|
||||
@item forward-search-history (@key{C-s})
|
||||
Search forward starting at the current line and moving `down' through
|
||||
the the history as necessary.
|
||||
|
||||
@end ftable
|
||||
|
||||
@need 2000
|
||||
@node Commands For Text
|
||||
@subsubsection Commands For Changing Text
|
||||
|
||||
@ftable @code
|
||||
@item delete-char (@key{C-d})
|
||||
Delete the character under the cursor. If the cursor is at the
|
||||
beginning of the line, and there are no characters in the line, and
|
||||
the last character typed was not @key{C-d}, then return EOF.
|
||||
|
||||
@item backward-delete-char (Rubout)
|
||||
Delete the character behind the cursor. A numeric argument says to kill
|
||||
the characters instead of deleting them.
|
||||
|
||||
@item quoted-insert (@key{C-q}, @key{C-v})
|
||||
Add the next character that you type to the line verbatim. This is
|
||||
how to insert things like @key{C-q} for example.
|
||||
|
||||
@item tab-insert (@key{M-TAB})
|
||||
Insert a tab character.
|
||||
|
||||
@item self-insert (a, b, A, 1, !, ...)
|
||||
Insert yourself.
|
||||
|
||||
@item transpose-chars (@key{C-t})
|
||||
Drag the character before point forward over the character at point.
|
||||
Point moves forward as well. If point is at the end of the line, then
|
||||
transpose the two characters before point. Negative arguments don't work.
|
||||
|
||||
@item transpose-words (@key{M-t})
|
||||
Drag the word behind the cursor past the word in front of the cursor
|
||||
moving the cursor over that word as well.
|
||||
|
||||
@item upcase-word (@key{M-u})
|
||||
Uppercase all letters in the current (or following) word. With a
|
||||
negative argument, do the previous word, but do not move point.
|
||||
|
||||
@item downcase-word (@key{M-l})
|
||||
Lowercase all letters in the current (or following) word. With a
|
||||
negative argument, do the previous word, but do not move point.
|
||||
|
||||
@item capitalize-word (@key{M-c})
|
||||
Uppercase the first letter in the current (or following) word. With a
|
||||
negative argument, do the previous word, but do not move point.
|
||||
|
||||
@end ftable
|
||||
|
||||
@need 2000
|
||||
@node Commands For Killing
|
||||
@subsubsection Killing And Yanking
|
||||
|
||||
@ftable @code
|
||||
@item kill-line (@key{C-k})
|
||||
Kill the text from the current cursor position to the end of the line.
|
||||
|
||||
@item backward-kill-line ()
|
||||
Kill backward to the beginning of the line. This is normally unbound.
|
||||
|
||||
@item kill-word (@key{M-d})
|
||||
Kill from the cursor to the end of the current word, or if between
|
||||
words, to the end of the next word.
|
||||
|
||||
@item backward-kill-word (@key{M-DEL})
|
||||
Kill the word behind the cursor.
|
||||
|
||||
@item unix-line-discard (@key{C-u})
|
||||
Kill the whole line the way @key{C-u} used to in Unix line input.
|
||||
The killed text is saved on the kill-ring.
|
||||
|
||||
@item unix-word-rubout (@key{C-w})
|
||||
Kill the word the way @key{C-w} used to in Unix line input.
|
||||
The killed text is saved on the kill-ring. This is different than
|
||||
backward-kill-word because the word boundaries differ.
|
||||
|
||||
@item yank (@key{C-y})
|
||||
Yank the top of the kill ring into the buffer at point.
|
||||
|
||||
@item yank-pop (@key{M-y})
|
||||
Rotate the kill-ring, and yank the new top. You can only do this if
|
||||
the prior command is yank or yank-pop.
|
||||
@end ftable
|
||||
|
||||
@need 2000
|
||||
@node Numeric Arguments
|
||||
@subsubsection Specifying Numeric Arguments
|
||||
|
||||
@ftable @code
|
||||
|
||||
@item digit-argument (@key{M-0}, @key{M-1}, ... @key{M--})
|
||||
Add this digit to the argument already accumulating, or start a new
|
||||
argument. @key{M--} starts a negative argument.
|
||||
|
||||
@item universal-argument ()
|
||||
Do what @key{C-u} does in @sc{gnu} Emacs. By default, this is not bound.
|
||||
@end ftable
|
||||
|
||||
|
||||
@need 2000
|
||||
@node Commands For Completion
|
||||
@subsubsection Letting Readline Type For You
|
||||
|
||||
@ftable @code
|
||||
@item complete (TAB)
|
||||
Attempt to do completion on the text before point. This is
|
||||
implementation defined. Generally, if you are typing a filename
|
||||
argument, you can do filename completion; if you are typing a command,
|
||||
you can do command completion, if you are typing in a symbol to GDB, you
|
||||
can do symbol name completion, if you are typing in a variable to Bash,
|
||||
you can do variable name completion.
|
||||
|
||||
@item possible-completions (M-?)
|
||||
List the possible completions of the text before point.
|
||||
@end ftable
|
||||
|
||||
@need 2000
|
||||
@node Miscellaneous Commands
|
||||
@subsubsection Some Miscellaneous Commands
|
||||
|
||||
@ftable @code
|
||||
|
||||
@item re-read-init-file (@key{C-x} @key{C-r})
|
||||
Read in the contents of your @file{~/.inputrc} file, and incorporate
|
||||
any bindings found there.
|
||||
|
||||
@item abort (@key{C-g})
|
||||
Stop running the current editing command.
|
||||
|
||||
@ignore
|
||||
@c I have no idea what this means, and can't figure it out by
|
||||
@c experiment, and can't find it in the readline source.
|
||||
@c doc@cygnus.com, 20may1993.
|
||||
@item do-uppercase-version (@key{M-a}, @key{M-b}, ...)
|
||||
Run the command that is bound to your uppercase brother.
|
||||
@end ignore
|
||||
|
||||
@item prefix-meta (ESC)
|
||||
Make the next character that you type be metafied. This is for people
|
||||
without a meta key. Typing @key{ESC f} is equivalent to typing
|
||||
@key{M-f}.
|
||||
|
||||
@item undo (@key{C-_})
|
||||
Incremental undo, separately remembered for each line.
|
||||
|
||||
@item revert-line (@key{M-r})
|
||||
Undo all changes made to this line. This is like typing the `undo'
|
||||
command enough times to get back to the beginning.
|
||||
@end ftable
|
||||
|
||||
@need 2000
|
||||
@node Readline vi Mode
|
||||
@subsection Readline @code{vi} Mode
|
||||
|
||||
@cindex @code{vi} style command editing
|
||||
@kindex toggle-editing-mode
|
||||
While the Readline library does not have a full set of @code{vi} editing
|
||||
functions, it does contain enough to allow simple editing of the line.
|
||||
|
||||
In order to switch interactively between @sc{gnu} Emacs and @code{vi}
|
||||
editing modes, use the command @key{M-C-j} (toggle-editing-mode).
|
||||
|
||||
When you enter a line in @code{vi} mode, you are already placed in `insertion'
|
||||
mode, as if you had typed an `i'. Pressing @key{ESC} switches you into
|
||||
`edit' mode, where you can edit the text of the line with the standard
|
||||
@code{vi} movement keys, move to previous history lines with `k', and following
|
||||
lines with `j', and so forth.
|
||||
|
Loading…
Reference in New Issue