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 }