/ src / hal / utils / pci_write.c
pci_write.c
  1  /***************************************************************************
  2   *            pci_write.c
  3   *
  4   *  Sun Sep  9 15:25:18 2007
  5   *  Copyright  2007  Stephen Wille Padnos
  6   *  swpadnos @ users.sourceforge.net
  7   *  loosely based on a work by John Kasunich: bfload.c
  8   *
  9   ****************************************************************************/
 10  
 11  /*
 12   *  This program is free software; you can redistribute it and/or modify
 13   *  it under the terms of the GNU General Public License version 2 as published 
 14   *  by the Free Software Foundation.
 15   *
 16   *  This program is distributed in the hope that it will be useful,
 17   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 18   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 19   *  GNU General Public License for more details.
 20   *
 21   *  You should have received a copy of the GNU General Public License
 22   *  along with this program; if not, write to the Free Software
 23   *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 24   */
 25  
 26  #include <errno.h>
 27  #include <stdlib.h>
 28  #include <stdio.h>
 29  #include <stdarg.h>
 30  #include <string.h>
 31  #include <sys/types.h>
 32  #include <unistd.h>
 33  #include <linux/types.h>
 34  #include "upci.h"
 35  #include "bitfile.h"
 36  
 37  /* define DEBUG_PRINTS to print info about command line parameters,
 38     the detected board, etc. */
 39  #undef DEBUG_PRINTS
 40  
 41  #define array_size(x) (sizeof(x)/sizeof(x[0]))
 42  
 43  struct board_info {
 44      char *board_type;
 45      char *chip_type;
 46      unsigned short vendor_id;
 47      unsigned short device_id;
 48      unsigned short ss_vendor_id;
 49      unsigned short ss_device_id;
 50      int fpga_pci_region;
 51      int upci_devnum;
 52  };
 53  
 54  
 55  struct board_info board_info_table[] =
 56      {
 57  	{ "5i20", "2s200pq208", 0x10B5, 0x9030, 0x10B5, 0x3131, 5, 0},
 58  	{ "5i22-1M", "3s1000fg320", 0x10B5, 0x9054, 0x10B5, 0x3132, 3, 0},
 59  	{ "5i22-1.5M", "3s1500fg320", 0x10B5, 0x9054, 0x10B5, 0x3131, 3, 0}
 60      };
 61  
 62  static void errmsg(const char *funct, const char *fmt, ...);
 63  static int parse_cmdline(unsigned argc, char *argv[]);
 64  
 65  /* globals to pass data from command line parser to main */
 66  struct write_var {
 67  	__u32 *val;		/* value */
 68  	__u32 minval, maxval;	/* allowable range, set them equal for no limit */
 69  	char *shortname;		/* name of var */
 70  	char *longname;			/* more descriptive var name for error messages */
 71  };
 72  
 73  /* these could have been stored in the struct above, but it's easier to access
 74     them this way */
 75  static __u32 cardnum, cardtype, pci_region, pci_offset, value;
 76  
 77  static struct write_var params[] =
 78  	{
 79  	{&cardnum, 0, 15, "cardnum", "Card Number"},
 80  	{&cardtype, 0, array_size(board_info_table), "cardtype", "Card Type"},
 81  	{&pci_region, 0, 3, "region", "PCI Region"},
 82  	{&pci_offset, 0, 65532, "offset", "Region Offset"},
 83  	{&value, 0, 0, "value", "Write Value"}
 84  	};
 85  
 86  
 87  /* Exit codes */
 88  #define EC_OK    0   /* Exit OK. */
 89  #define EC_BADCL 100 /* Bad command line. */
 90  #define EC_HDW   101 /* Some sort of hardware failure on the 5I20. */
 91  #define EC_FILE  102 /* File error of some sort. */
 92  #define EC_SYS   103 /* Beyond our scope. */
 93  
 94  
 95  /***********************************************************************/
 96  
 97  int main(int argc, char *argv[])
 98  {
 99  	int data_region, retval;
100  #ifdef DEBUG_PRINTS
101  	int dbg;
102  #endif
103  	struct upci_dev_info info;
104      struct board_info board;
105  
106      /* if we are setuid, drop privs until needed */
107      retval = seteuid(getuid());
108      if (retval != 0) {
109          fprintf(stderr, "failed to set euid to uid %d: %s\n", getuid(), strerror(errno));
110          return EC_SYS;
111      }
112  
113      if ( parse_cmdline(argc, argv) != EC_OK ) {
114  		return EC_BADCL;
115      }
116  
117  #ifdef DEBUG_PRINTS
118  	for (dbg=0;dbg<array_size(params);dbg++) {
119  		printf("Parameter %s = %u\n", params[dbg].longname, *(params[dbg].val));
120  	}
121  #endif
122      /* set up local pointer to the correct board info table entry */
123      board = board_info_table[cardtype];
124  #ifdef DEBUG_PRINTS
125      printf ( "Board type:      %s\n", board.board_type );
126  #endif
127      /* now deal with the hardware */
128      retval = upci_scan_bus();
129      if ( retval < 0 ) {
130  		errmsg(__func__,"PCI bus data missing" );
131  		return EC_SYS;
132      }
133      info.vendor_id = board.vendor_id;
134      info.device_id = board.device_id;
135      info.ss_vendor_id = board.ss_vendor_id;
136      info.ss_device_id = board.ss_device_id;
137      info.instance = cardnum;
138      /* find the matching device */
139      board.upci_devnum = upci_find_device(&info);
140      if ( board.upci_devnum < 0 ) {
141  		errmsg(__func__, "%s board #%d not found",
142  	    	board.board_type, info.instance );
143  		return EC_HDW;
144      }
145  #ifdef DEBUG_PRINTS
146      upci_print_device_info(board.upci_devnum);
147  #else
148      data_region = upci_open_region(board.upci_devnum, pci_region);
149      upci_write_u32(data_region, pci_offset, value);
150  #endif
151      return EC_OK;
152  }
153  
154  /************************************************************************/
155  
156  static void errmsg(const char *funct, const char *fmt, ...)
157  {
158      va_list vp;
159  
160      va_start(vp, fmt);
161      fprintf(stderr, "ERROR in %s(): ", funct);
162      vfprintf(stderr, fmt, vp);
163      fprintf(stderr, "\n");
164      va_end(vp);
165  }
166  
167  void usage(void) {
168  	int i;
169  	printf("\npci_write <card> <cardtype> <region> <offset> <value>\n\n");
170  	printf("All parameters are required.\n");
171  	printf("    <card>      - card number (0-15)\n\n");
172  	printf("    <cardtype>  - card type.  valid types are:\n");
173  	for (i=0;i<array_size(board_info_table);i++) {
174  		printf("                  %d - %s\n", i, board_info_table[i].board_type);
175  	}
176  	printf("\n    <region>    - which PCI region to write into\n\n");
177  	printf("    <offset>    - offset into the region\n\n");
178  	printf("    <value>     - value to write\n\n");
179  }
180  
181  static int parse_cmdline(unsigned argc, char *argv[])
182  {
183  	int i;
184  	__u32 temp;
185  	char *eptr;
186  
187      if (argc != array_size(params)+1) {
188  		usage();
189  		return EC_BADCL;
190      }
191  
192  	/* loop through the command line parameters and the list of vars */
193  	for (i=0;i<array_size(params);i++)
194  	{
195  		temp = strtoul(argv[i+1], &eptr, 0);
196  		if (*eptr!='\0')
197  		{
198  			errmsg(__func__,"invalid %s: %s", params[i].longname, argv[i+1]);
199  			return EC_BADCL;
200  		}
201  		if (params[i].minval != params[i].maxval) {
202  				if ((temp < params[i].minval) || (temp > params[i].maxval)) {
203  					errmsg(__func__,"Parameter %s out of range: %u",
204  						params[i].longname, temp);
205  					return EC_BADCL;
206  				}
207  		}
208  		*(params[i].val)=temp;
209  	}
210      return EC_OK;
211  }