Spartan programming C example

From Ssdlpedia
Jump to: navigation, search

Initial code:

#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 to switch
  • variable 'status' initialization is added
  • return statement parenthesis are deleted
  • all cases with no performed action moved to the beginning of switch
  • SAL_PCI_CONFIG_READ and SAL_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 different 'in2' is defined
  • new structure for input to the function is defined
  • two new functions for cases treatment are defined
  • variables r10, r11 are deleted

Simplified code:

#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};
 }
Personal tools