-
Notifications
You must be signed in to change notification settings - Fork 56
Spartan programming C example
Ori Roth edited this page Apr 2, 2017
·
3 revisions
#define BUILD_CMD(addr) ((0x80000000 | (addr)) & ~3)
#define REG_OFFSET(addr) (0x00000000000000FF & (addr))
#define SAL_SET_VECTORS 0x01000000
#define SAL_GET_STATE_INFO 0x01000001
#define SAL_GET_STATE_INFO_SIZE 0x01000002
#define SAL_CLEAR_STATE_INFO 0x01000003
#define SAL_MC_RENDEZ 0x01000004
#define SAL_MC_SET_PARAMS 0x01000005
#define SAL_REGISTER_PHYSICAL_ADDR 0x01000006
#define SAL_CACHE_FLUSH 0x01000008
#define SAL_CACHE_INIT 0x01000009
#define SAL_PCI_CONFIG_READ 0x01000010
#define SAL_PCI_CONFIG_WRITE 0x01000011
#define SAL_FREQ_BASE 0x01000012
#define SAL_PHYSICAL_ID_INFO 0x01000013
#define SAL_UPDATE_PAL 0x01000020
enum {
SAL_FREQ_BASE_PLATFORM = 0,
SAL_FREQ_BASE_INTERVAL_TIMER = 1,
SAL_FREQ_BASE_REALTIME_CLOCK = 2
};
static struct sal_ret_values
sal_emulator (long index, unsigned long in1, unsigned long in2,
unsigned long in3, unsigned long in4, unsigned long in5,
unsigned long in6, unsigned long in7)
{
long r9 = 0;
long r10 = 0;
long r11 = 0;
long status;
status = 0;
if (index == SAL_FREQ_BASE) {
switch (in1) {
case SAL_FREQ_BASE_PLATFORM:
r9 = 200000000;
break;
case SAL_FREQ_BASE_INTERVAL_TIMER:
/*
* Is this supposed to be the cr.itc frequency
* or something platform specific? The SAL
* doc ain't exactly clear on this...
*/
r9 = 700000000;
break;
case SAL_FREQ_BASE_REALTIME_CLOCK:
r9 = 1;
break;
default:
status = -1;
break;
}
} else if (index == SAL_SET_VECTORS) {
;
} else if (index == SAL_GET_STATE_INFO) {
;
} else if (index == SAL_GET_STATE_INFO_SIZE) {
;
} else if (index == SAL_CLEAR_STATE_INFO) {
;
} else if (index == SAL_MC_RENDEZ) {
;
} else if (index == SAL_MC_SET_PARAMS) {
;
} else if (index == SAL_CACHE_FLUSH) {
;
} else if (index == SAL_CACHE_INIT) {
;
} else if (index == SAL_PCI_CONFIG_READ) {
/*
* in1 contains the PCI configuration address and in2
* the size of the read. The value that is read is
* returned via the general register r9.
*/
outl(BUILD_CMD(in1), 0xCF8);
if (in2 == 1) /* Reading byte */
r9 = inb(0xCFC + ((REG_OFFSET(in1) & 3)));
else if (in2 == 2) /* Reading word */
r9 = inw(0xCFC + ((REG_OFFSET(in1) & 2)));
else /* Reading dword */
r9 = inl(0xCFC);
status = PCIBIOS_SUCCESSFUL;
} else if (index == SAL_PCI_CONFIG_WRITE) {
/*
* in1 contains the PCI configuration address, in2 the
* size of the write, and in3 the actual value to be
* written out.
*/
outl(BUILD_CMD(in1), 0xCF8);
if (in2 == 1) /* Writing byte */
outb(in3, 0xCFC + ((REG_OFFSET(in1) & 3)));
else if (in2 == 2) /* Writing word */
outw(in3, 0xCFC + ((REG_OFFSET(in1) & 2)));
else /* Writing dword */
outl(in3, 0xCFC);
status = PCIBIOS_SUCCESSFUL;
} else if (index == SAL_UPDATE_PAL) {
;
} else {
status = -1;
}
return ((struct sal_ret_values) {status, r9, r10, r11});
}
Changes:
- Enumeration is created
- Nested
if
turned toswitch
- Variable
status
initialization is added - Return statement parentheses are deleted
- All cases with no performed action moved to the beginning of
switch
-
SAL_PCI_CONFIG_READ
andSAL_PCI_CONFIG_WRITE
cases union - Structure for functions and parameter that called for specified
in2
is defined - Array of characteristics (
in
/out
function and paramater) for differentin2
is defined - New structure for input to the function is defined
- Two new functions for cases treatment are defined
- Variables
r10
,r11
are deleted
#define BUILD_CMD(addr) ((0x80000000 | (addr)) & ~3)
#define REG_OFFSET(addr) (0x00000000000000FF & (addr))
enum sal_cmd_event {
SAL_SET_VECTORS = 0x01000000,
SAL_GET_STATE_INFO,
SAL_GET_STATE_INFO_SIZE,
SAL_CLEAR_STATE_INFO,
SAL_MC_RENDEZ,
SAL_MC_SET_PARAMS,
SAL_REGISTER_PHYSICAL_ADDR,
SAL_CACHE_FLUSH = 0x01000008,
SAL_CACHE_INIT,
SAL_PCI_CONFIG_READ,
SAL_PCI_CONFIG_WRITE,
SAL_FREQ_BASE,
SAL_PHYSICAL_ID_INFO,
SAL_UPDATE_PAL = 0x01000020,
};
enum {
SAL_FREQ_BASE_PLATFORM = 0,
SAL_FREQ_BASE_INTERVAL_TIMER = 1,
SAL_FREQ_BASE_REALTIME_CLOCK = 2
};
typedef long (*ptInFunction)(long);
typedef void (*ptOutFunction)(unsigned long, long);
typedef struct sal_rw_params_struct {
ptInFunction inFunction;
ptOutFunction outFunction;
int andParameter;
} sal_rw_params;
typedef struct sal_rec_vals_struct {
long index;
unsigned long in1;
unsigned long in2;
unsigned long in3;
unsigned long in4;
unsigned long in5;
unsigned long in6;
unsigned long in7
} sal_rec_vals;
static long sal_freq_base_treat(unsigned long in1, long* r9)
{
switch (in1) {
case SAL_FREQ_BASE_PLATFORM:
*r9 = 200000000;
break;
case SAL_FREQ_BASE_INTERVAL_TIMER:
/*
* Is this supposed to be the cr.itc frequency
* or something platform specific? The SAL
* doc ain't exactly clear on this...
*/
*r9 = 700000000;
break;
case SAL_FREQ_BASE_REALTIME_CLOCK:
*r9 = 1;
break;
default:
return -1;
}
return 0;
}
static long sal_config_rw_treat(sal_rec_vals input, long* r9)
{
long param;
int rw_index = 0;
static sal_rw_params sal_rw[] = {{&inl, &outl, 0},
{&inb, &outb, REG_OFFSET(in1) & 3},
{&inw, &outw, REG_OFFSET(in1) & 2}};
outl(BUILD_CMD(input.in1), 0xCF8);
if ((input.in2 == 1) || (input.in2 == 2))
rw_index = input.in2;
param = 0xCFC + REG_OFFSET(input.in1) & (sal_rw[rw_index].offset);
if (input.index == SAL_PCI_CONFIG_READ)
/*
* in1 contains the PCI configuration address and in2
* the size of the read. The value that is read is
* returned via the general register r9.
*/
*r9 = (*sal_rw[rw_index].inFunction)(param);
else
/*
* in1 contains the PCI configuration address, in2 the
* size of the write, and in3 the actual value to be
* written out.
*/
(*sal_rw[rw_index].outFunction)(input.in3, param);
return PCIBIOS_SUCCESSFUL;
}
static struct sal_ret_values sal_emulator (sal_rec_vals input)
{
long r9 = 0;
long status = 0;
switch(input.index) {
case SAL_SET_VECTORS:
case SAL_GET_STATE_INFO:
case SAL_GET_STATE_INFO_SIZE:
case SAL_CLEAR_STATE_INFO:
case SAL_MC_RENDEZ:
case SAL_MC_SET_PARAMS:
case SAL_CACHE_FLUSH:
case SAL_CACHE_INIT:
case SAL_UPDATE_PAL:
break;
case SAL_FREQ_BASE:
status = sal_freq_base_treat(input.in1, &r9);
break;
case SAL_PCI_CONFIG_READ:
case SAL_PCI_CONFIG_WRITE:
status = sal_config_rw_treat(input, &r9);
break;
default:
status = -1;
break;
}
return (struct sal_ret_values) {status, r9, 0L, 0L};
}