edt_bitfile.c

00001 /* #pragma ident "@(#)edt_bitfile.c     1.7 07/18/08 EDT" */
00002 
00003 #include "edt_bitfile.h"
00004 
00005 /**************************************************************************
00006  *
00007  * edt_bitfile API
00008  *
00009  *       Subroutines used to identify EDT boards and read a Xilinx
00010  *       configuration file with information about which interface
00011  *       bitfiles can be used with which PCI flash bitfiles. 
00012  *       See /opt/EDTpcd/pcdrequest.c for a sample application.
00013  *
00014  * A typical application will start with:
00015  *
00016  *      #include "edt_bitfile.h"
00017  *
00018  *      static edt_board_desc_table edt_boards ;
00019  *      static edt_bitfile_desc_table edt_bitfiles ;
00020  *      
00021  *   edt_boards is a table of installed EDT boards, their type, unit number
00022  *   and which PCI bitfile is loaded in the flash prom.
00023  *
00024  *   edt_bitfiles is a table correlating PCI bitfiles with interface bitfiles,
00025  *   and each bitfile has a descriptive comment.  It is loaded from a text
00026  *   configuration file which lists each PCI bitfile and the interface
00027  *   bitfiles (and comments) that can be used with it.
00028  *
00029  * Make the following call to initialize edt_boards:
00030  *
00031  *      edt_probe_boards(edt_boards) ;
00032  *
00033  * Next initialize edt_bitfiles with:
00034  *
00035  *      edt_read_bitfile_config("cfg_file_name", edt_bitfiles) ;
00036  *
00037  * Finally, to search the edt_bitfiles table for a particular PCI bitfile,
00038  * call:
00039  *
00040  *      edt_bitfile_desc *ptr ;
00041  *
00042  *      ptr = edt_get_bitfile_desc(flash_name, edt_bitfiles) ;
00043  *
00044  * where flash_name is taken from edt_boards[i].pci_flash_name.
00045  * ptr now contains a pointer to the following struct:
00046  *
00047  *      typedef struct {
00048  *          char *pci_bitfile_name ;
00049  *          int   intfc_bitfile_count ;
00050  *          char *intfc_bitfile_names[64] ;
00051  *          char *intfc_bitfile_comments[64] ;
00052  *      } edt_bitfile_desc ; 
00053  *
00054  * The intfc_bitfile_count variable contains the number of bitfile strings in
00055  * intfc_bitfile_names and intfc_bitfile_comments.
00056  *
00057  * See /opt/EDTpcd/pcdrequest for an example program.
00058  *
00059  *
00060  * The format of the bitfile config file is:
00061  *
00062  *      # Comments have a '#' in the leftmost column
00063  *      flash_file_name_1:
00064  *      flash_file_name_2:
00065  *            .
00066  *            .
00067  *      flash_file_name_N:
00068  *      < tab >bitfile_name_1   "Descriptive comment for bitfile_name_1"
00069  *      < tab >bitfile_name_2   "Descriptive comment for bitfile_name_1"
00070  *                   .
00071  *                   .
00072  *      < tab >bitfile_name_N   "Descriptive comment for bitfile_name_N"
00073  *
00074  *      flash_file_name_N+1:
00075  *      < tab >bitfile_name_N+1 "Descriptive comment for bitfile_name_N+1"
00076  *            .
00077  *            .
00078  *
00079  * Bitfile names must be preceeded by a tab character.  Empty lines and
00080  * lines beginning with '#' are ignored.  In the above example,
00081  * flash_file_name_1 through flash_file_name_N can use bitfile_name_1
00082  * through bit_file_name_N.  Here is an actual example for the PCD board:
00083  *
00084  *      pcd20.bit:
00085  *      pcd40.bit:
00086  *      pcd60.bit:
00087  *              pcd_src.bit     "16-bit parallel I/O synced to PCD source clock"
00088  *              pcd_looped.bit  "16-bit parallel I/O synced to external clock"
00089  *              ssd.bit         "One channel serial input"
00090  *              ssd2.bit        "Two channel serial input"
00091  *              ssd4.bit        "Four channel serial input"
00092  *              ssdio.bit       "Dual channel serial I/O"
00093  *              ssdout1.bit     "One channel serial output"
00094  *
00095  *      pcd16.bit:
00096  *              ssd16in.bit     "16 channel serial input"
00097  *              ssd16out.bit    "16 channel serial output"
00098  *
00099  **************************************************************************/
00100 
00101 int
00102 edt_probe_boards(edt_board_desc_table edt_boards)
00103 {
00104     FILE *fp ;
00105     int need_unit_no = 1 ;
00106     int need_xilinx_type = 0 ;
00107     int curr_unit_no ;
00108     int list_entries = 0 ;
00109     int ret ;
00110     static char probe_str[512] ;
00111     static char board_name[128] ;
00112     static char curr_flash_name[128] ;
00113 
00114 #ifdef _NT_
00115     if ((fp = _popen(".\\pciload -p", "r")) == NULL)
00116 #else
00117     if ((fp = popen("./pciload -p", "r")) == NULL)
00118 #endif
00119     {
00120         app_perror("./pciload -p") ;
00121         return -1 ;
00122     }
00123 
00124     memset(edt_boards, 0, sizeof(edt_board_desc_table)) ;
00125 
00126     while (fgets(probe_str, 511, fp))
00127     {
00128         /*
00129          * Three states:  
00130          *
00131          *      1. need board name and unit number
00132          *      2. need Xilinx type
00133          *      3. need flash bitfile name
00134          */
00135         if (need_unit_no)
00136         {
00137             if ((ret = sscanf(probe_str, "%s unit %d", board_name,
00138                                                       &curr_unit_no)) == 2)
00139             {
00140                 edt_boards[list_entries].unit_no = curr_unit_no ;
00141                 strncpy(edt_boards[list_entries].board_name, board_name, 127);
00142                 need_unit_no = 0 ;
00143                 need_xilinx_type = 1 ;
00144             }
00145         }
00146         else if (need_xilinx_type)
00147         {
00148             char *p = strrchr(probe_str, ' ') ;
00149 
00150             if (p)
00151                 *p = '\0' ;
00152 
00153             if ((p = strrchr(probe_str, ' ')) != NULL)
00154                 strcpy(edt_boards[list_entries].pci_xilinx_type, p + 1) ;
00155             else
00156                 strcpy(edt_boards[list_entries].pci_xilinx_type, probe_str) ;
00157 
00158             need_xilinx_type = 0 ;
00159         }
00160         else            /* need flash bitfile name */
00161         {
00162             int sector_num ;
00163 
00164             ret = sscanf(probe_str, "  Sector %d <%s", &sector_num,
00165                                                    (char*) &curr_flash_name) ;
00166             if (ret == 1 && sector_num == 3)
00167             {
00168                 char *p = strchr(probe_str, '3') ;
00169 
00170                 p += 2 ;
00171                 if (strncmp(p, "No program id", 13) == 0)
00172                 {
00173                     strcpy(edt_boards[list_entries].pci_flash_name,
00174                                                 "No program id") ;
00175                 }
00176                 else
00177                 {
00178                     strcpy(edt_boards[list_entries].pci_flash_name,
00179                                       "Unrecognized program id") ;
00180                 }
00181                 need_unit_no = 1 ;
00182                 ++ list_entries ;
00183             }
00184             else if (ret == 2)
00185             {
00186                 /* strip off .ncd or .bit extension */
00187                 char *p = strrchr(curr_flash_name, '.') ;
00188 
00189                 if (p)
00190                     *p = '\0' ;
00191 
00192                 p = strrchr(curr_flash_name, '_') ;
00193 
00194                 /* strip off _3v or _5v substring */
00195                 if (p && 
00196                       (( *(p+1) == '3' || *(p+1) == '5') && *(p+2) == 'v' ))
00197                     *p = '\0' ;
00198                         
00199                 strcpy(edt_boards[list_entries].pci_flash_name,
00200                                             curr_flash_name) ;
00201                 strcat(edt_boards[list_entries].pci_flash_name, ".bit") ;
00202                 need_unit_no = 1 ;
00203                 ++ list_entries ;
00204             }
00205         }
00206     }
00207 
00208     return 0 ;
00209 }
00210 
00211 edt_bitfile_desc *edt_get_bitfile_desc(char *flash_name, edt_bitfile_desc_table edt_bitfiles)
00212 {
00213     int i ;
00214 
00215     for (i = 0; i < EDT_MAX_BITFILES; i++)
00216     {
00217         if (edt_bitfiles[i].pci_bitfile_name)
00218         {
00219             if (strcmp(flash_name, edt_bitfiles[i].pci_bitfile_name) == 0)
00220                 return &edt_bitfiles[i] ;
00221         }
00222     }
00223     return NULL ;
00224 }
00225 
00226 int
00227 edt_read_bitfile_config(char *cfg_file_name,edt_bitfile_desc_table edt_bitfiles)
00228 {
00229     FILE *cfg_fp ;
00230     struct stat sbuf ;
00231     char *cfg_buf, *cfg_ptr, *ptr ;
00232     int i, cfg_size, curr_pci, shared_pcis, curr_intfc,
00233         need_flash_names, need_intfc_names, line_no ;
00234 
00235     if ((cfg_fp = fopen(cfg_file_name, "rb")) == NULL)
00236     {
00237         app_perror(cfg_file_name) ;
00238         return -1 ;
00239     }
00240 
00241     memset(edt_bitfiles, 0, sizeof(edt_bitfile_desc_table)) ;
00242 
00243     fstat(fileno(cfg_fp), &sbuf) ;
00244     cfg_size = sbuf.st_size ;
00245 
00246     cfg_buf = (char *) malloc(cfg_size+1) ;
00247     fread(cfg_buf, 1, cfg_size, cfg_fp) ;
00248     cfg_buf[cfg_size] = '\0' ;
00249     fclose(cfg_fp) ;
00250 
00251     cfg_ptr = cfg_buf ;
00252     curr_pci = 0 ;
00253     shared_pcis = 0 ;
00254     curr_intfc = 0 ;
00255     need_flash_names = 1 ;
00256     need_intfc_names = 0 ;
00257     line_no = 1 ;
00258     while (cfg_ptr < cfg_buf + cfg_size)
00259     {
00260         if (need_flash_names)
00261         {
00262             if (*cfg_ptr != '\n')
00263             {
00264                 if (*cfg_ptr == ' ' || *cfg_ptr == '\t')
00265                 {
00266                     if (shared_pcis == 0)
00267                     {
00268                         printf("%s:  <1>syntax error on line %d\n",
00269                                            cfg_file_name, line_no);
00270                         return -1 ;
00271                     }
00272                     need_flash_names = 0 ;
00273                     need_intfc_names = 1 ;
00274                 }
00275                 else
00276                 {
00277                     if (*cfg_ptr == '#')
00278                     {
00279                         ++ line_no ;
00280                         while (*cfg_ptr != '\n')
00281                             ++ cfg_ptr ;
00282                     }
00283                     else
00284                     {
00285                         edt_bitfiles[curr_pci + shared_pcis].pci_bitfile_name
00286                                                                         = cfg_ptr;
00287 
00288                         if ((ptr = strchr(cfg_ptr, ':')) != NULL)
00289                         {
00290                             *ptr = '\0' ;
00291                             cfg_ptr = ptr + 1 ;
00292                         }
00293                         else
00294                         {
00295                             printf("%s:  <2>syntax error on line %d\n",
00296                                                cfg_file_name, line_no);
00297                             return -1 ;
00298                         }
00299 
00300                         if ((ptr = strchr(cfg_ptr, '"')) != NULL)
00301                         {
00302                             cfg_ptr = ptr + 1 ;
00303 
00304                             edt_bitfiles[curr_pci + shared_pcis].
00305                                    pci_bitfile_comment = cfg_ptr;
00306 
00307                             if ((ptr = strchr(cfg_ptr, '"')) != NULL)
00308                             {
00309                                     *ptr = '\0' ;
00310                                     cfg_ptr = ptr + 1 ;
00311 
00312                                     while (*cfg_ptr != '\n')
00313                                     {
00314                                         ++ cfg_ptr ;
00315                                     }
00316 
00317                             }
00318                             else
00319                             {
00320                                     printf("%s:  <2.5>syntax error on line %d\n",
00321                                                        cfg_file_name, line_no);
00322                                     return -1 ;
00323                             }
00324                         }
00325 
00326                         ++ shared_pcis ;
00327                     }
00328                 }
00329             }
00330             else
00331             {
00332                 ++ line_no ;
00333                 ++ cfg_ptr ;
00334             }
00335         }
00336         else if (need_intfc_names)
00337         {
00338             if (*cfg_ptr != '\n')
00339             {
00340                 while (*cfg_ptr == ' ' || *cfg_ptr == '\t')
00341                     ++ cfg_ptr ;
00342 
00343                 for (i = 0; i < shared_pcis; i++)
00344                     edt_bitfiles[curr_pci + i].
00345                              intfc_bitfile_names[curr_intfc] = cfg_ptr;
00346 
00347                 while (*cfg_ptr != ' ' && *cfg_ptr != '\t')
00348                     ++ cfg_ptr ;
00349 
00350                 *cfg_ptr++ = '\0' ;
00351 
00352                 if ((ptr = strchr(cfg_ptr, '"')) != NULL)
00353                 {
00354                     cfg_ptr = ptr + 1 ;
00355 
00356                     for (i = 0; i < shared_pcis; i++)
00357                         edt_bitfiles[curr_pci + i].
00358                              intfc_bitfile_comments[curr_intfc] = cfg_ptr ;
00359 
00360                     if ((ptr = strchr(cfg_ptr, '"')) != NULL)
00361                     {
00362                         *ptr = '\0' ;
00363                         cfg_ptr = ptr + 1 ;
00364 
00365                         while (*cfg_ptr != '\n')
00366                             ++ cfg_ptr ;
00367                     }
00368                     else
00369                     {
00370                         printf("%s:  <3>syntax error on line %d\n",
00371                                            cfg_file_name, line_no);
00372                         return -1 ;
00373                     }
00374                 }
00375                 else
00376                 {
00377                     printf("%s:  <4>syntax error on line %d\n", cfg_file_name,
00378                                                                      line_no);
00379                     return -1 ;
00380                 }
00381 
00382                 ++ curr_intfc ;
00383             }
00384             else
00385             {
00386                 for (i = 0; i < shared_pcis; i++)
00387                     edt_bitfiles[curr_pci + i].intfc_bitfile_count = curr_intfc;
00388 
00389                 curr_intfc = 0 ;
00390                 curr_pci += shared_pcis ;
00391                 shared_pcis = 0 ;
00392                 need_intfc_names = 0 ;
00393                 need_flash_names = 1 ;
00394             }
00395         }
00396 
00397         if (*cfg_ptr == '\n')
00398         {
00399             ++ cfg_ptr ;
00400             ++ line_no ;
00401         }
00402     }
00403 
00404     if (need_intfc_names)
00405     {
00406         for (i = 0; i < shared_pcis; i++)
00407             edt_bitfiles[curr_pci + i].intfc_bitfile_count = curr_intfc;
00408     }
00409 
00410     return 0 ;
00411 }
00412 
00413 
00414 int
00415 edt_create_pcdload_script(edt_board_desc_table edt_boards)
00416 {
00417     int i, ch ;
00418     const char *homedir = edt_envvar_from_devtype((const)edt_boards[0].board_name); /* assumes there is a board 0 */
00419         FILE *fp = fopen(homedir, "wb+") ;
00420         printf("Creating %s/pcdload.bat", edt_envvar_from_devtype((const)edt_boards[0].board_name)) ;
00421 
00422         if (fp == NULL)
00423         {
00424             app_perror((char *)homedir);
00425             return -1 ;
00426         }
00427 
00428 #ifdef _NT_
00429         fputs("REM\nREM See \\edt\\pcd\\pcd_bitfiles for flash and bitfile information.\nREM\n", fp) ;
00430         fputs("REM\nREM See \\edt\\pcd\\initpcd.c comments for setting up multi-channel boards.\nREM\n", fp) ;
00431 #else
00432         fputs("#! /bin/csh -f\n\n", fp) ;
00433         fputs("#\n# See /opt/EDTpcd/pcd_bitfiles for flash and bitfile information.\n", fp) ;
00434         fputs("# See /edt/pcd/initpcd.c comments for setting up multi-channel boards.\n#\n", fp) ;
00435 #endif
00436 
00437     for (i = 0; i < EDT_MAX_BOARDS; i++)
00438     {
00439         if (strncmp(edt_boards[i].board_name, "pcd", 3) == 0)
00440         {
00441 #ifdef _NT_
00442             fprintf(fp, "REM\nREM PCD unit %d PCI flash %s:\nREM\n",
00443 #else
00444             fprintf(fp, "#\n# PCD unit %d PCI flash %s:\n#\n",
00445 #endif
00446                 edt_boards[i].unit_no,
00447                 edt_boards[i].pci_flash_name) ;
00448     
00449             if (edt_boards[i].intfc_bitfile)
00450             {
00451 #ifdef _NT_
00452                 fprintf(fp, ".\\bitload -u %d %s\n\n",
00453 #else
00454                 fprintf(fp, "./bitload -u %d %s\n\n",
00455 #endif
00456                                edt_boards[i].unit_no,
00457                         edt_boards[i].intfc_bitfile);
00458             }
00459             else
00460             {
00461 #ifdef _NT_
00462                 fputs("REM ", fp);
00463 #else
00464                 fputs("# ", fp);
00465 #endif
00466                 fputs("Use initpcd to configure this board (see initpcd.c for documentation).\n", fp);
00467 #ifdef _NT_
00468                 fputs("REM ", fp);
00469 #else
00470                 fputs("# ", fp);
00471 #endif
00472                 fprintf(fp, "For example, replace this line with \"initpcd -u %d -f cda_diffchk.cfg\"\n", 
00473                    edt_boards[i].unit_no);
00474 #ifdef _NT_
00475                 fputs("REM ", fp);
00476 #else
00477                 fputs("# ", fp);
00478 #endif
00479                 fputs("For support:  email tech@edt.com or call 503-690-1234.\n", fp);
00480                 fputs("\n", fp) ;
00481             }
00482         }
00483     }
00484 
00485     fputs("Done.\n\nPress return to view the PCD configuration script: ", stdout) ;
00486     fflush(stdout) ;
00487     getchar() ;
00488     puts("\n");
00489     puts("\n");
00490 
00491     fflush(fp);
00492     rewind(fp);
00493     while ((ch = getc(fp)) != EOF)
00494         putc(ch, stdout);
00495     puts("\n");
00496 
00497     fclose(fp) ;
00498 
00499 #ifndef _NT_
00500     system("chmod a+x /opt/EDTpcd/pcdload") ;
00501 #endif
00502 
00503     return 0 ;
00504 }
00505 
00506 void
00507 app_perror(char *str)
00508 {
00509     perror(str) ;
00510 }
00511 
00512 
00513 char *
00514 get_bitfile_list(edt_bitfile_desc_table edt_bitfiles)
00515 {
00516     int i, j ;
00517     char *str = (char *) calloc(16*1024, 1) ;
00518 
00519     sprintf(str + strlen(str), "\n%50s\n", "Configured EDT bitfiles:\n") ;
00520     for (i = 0; i < EDT_MAX_BITFILES; i++)
00521     {
00522         if (edt_bitfiles[i].pci_bitfile_name)
00523         {
00524             sprintf(str + strlen(str), "%-20s%s\n", edt_bitfiles[i].pci_bitfile_name,
00525                                         edt_bitfiles[i].pci_bitfile_comment);
00526 
00527             if ((strncmp(edt_bitfiles[i].pci_bitfile_name, "pcd20.bit", strlen("pcd20.bit")) != 0)
00528              && (strncmp(edt_bitfiles[i].pci_bitfile_name, "pcd40.bit", strlen("pcd40.bit")) != 0))
00529             {
00530                 for (j = 0; j < edt_bitfiles[i].intfc_bitfile_count; j++)
00531                     sprintf(str + strlen(str), "\t%-20s%s\n",
00532                                      edt_bitfiles[i].intfc_bitfile_names[j],
00533                                      edt_bitfiles[i].intfc_bitfile_comments[j]);
00534             }
00535             if ((strncmp(edt_bitfiles[i].pci_bitfile_name, "pcd20.bit", strlen("pcd20.bit")) != 0)
00536              && (strncmp(edt_bitfiles[i].pci_bitfile_name, "pcd40.bit", strlen("pcd40.bit")) != 0))
00537             sprintf(str + strlen(str), "\n") ;
00538         }
00539     }
00540 
00541     return str ;
00542 }

Generated on 19 Jun 2015 by  doxygen 1.4.7