linux/drivers/staging/dgap/downld.c
<<
>>
Prefs
   1/*
   2 * Copyright 2003 Digi International (www.digi.com)
   3 *      Scott H Kilau <Scott_Kilau at digi dot com>
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License as published by
   7 * the Free Software Foundation; either version 2, or (at your option)
   8 * any later version.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
  12 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  13 * PURPOSE.  See the GNU General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License
  16 * along with this program; if not, write to the Free Software
  17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18 *
  19 * $Id: downld.c,v 1.6 2009/01/14 14:10:54 markh Exp $
  20 */
  21
  22/*
  23** downld.c
  24**
  25**  This is the daemon that sends the fep, bios, and concentrator images
  26**  from user space to the driver.
  27** BUGS: 
  28**  If the file changes in the middle of the download, you probably
  29**     will get what you deserve.
  30**
  31*/
  32
  33#include <stdlib.h>
  34#include <stdio.h>
  35#include <fcntl.h>
  36#include <sys/types.h>
  37#include <sys/stat.h>
  38#include <sys/errno.h>
  39
  40#include "dgap_types.h"
  41#include "digi.h"
  42#include "dgap_fep5.h"
  43
  44#include "dgap_downld.h"
  45
  46#include <string.h>
  47#include <malloc.h>
  48#include <stddef.h>
  49#include <unistd.h>
  50
  51char            *pgm;
  52void            myperror();
  53
  54/*
  55**  This structure is used to keep track of the diferent images available
  56**  to give to the driver.  It is arranged so that the things that are
  57**  constants or that have defaults are first inthe strucutre to simplify
  58**  the table of initializers.
  59*/
  60struct image_info {
  61        short   type;           /* bios, fep, conc */
  62        short   family;         /* boards this applies to */
  63        short   subtype;        /* subtype */
  64        int     len;            /* size of image */
  65        char    *image;         /* ioctl struct + image */
  66        char    *name;
  67        char    *fname;         /* filename of binary (i.e. "asfep.bin") */
  68        char    *pathname;      /* pathname to this binary ("/etc/dgap/xrfep.bin"); */
  69        time_t  mtime;          /* Last modification time */
  70};
  71
  72#define IBIOS   0
  73#define IFEP    1
  74#define ICONC   2
  75#define ICONFIG 3
  76#define IBAD    4
  77
  78#define DEFAULT_LOC "/lib/firmware/dgap/"
  79
  80struct image_info       *image_list;
  81int                     nimages, count;
  82
  83struct image_info images[] = {
  84{IBIOS, T_EPC,      SUBTYPE, 0, NULL, "EPC/X",  "fxbios.bin", DEFAULT_LOC "fxbios.bin", 0 },
  85{IFEP,  T_EPC,      SUBTYPE, 0, NULL, "EPC/X",  "fxfep.bin", DEFAULT_LOC "fxfep.bin", 0 },
  86{ICONC, T_EPC,      SUBTYPE, 0, NULL, "EPC/X",  "fxcon.bin", DEFAULT_LOC "fxcon.bin", 0 },
  87
  88{IBIOS, T_CX,       SUBTYPE, 0, NULL, "C/X",    "cxbios.bin", DEFAULT_LOC "cxbios.bin", 0 },
  89{IFEP,  T_CX,       SUBTYPE, 0, NULL, "C/X",    "cxhost.bin", DEFAULT_LOC "cxhost.bin", 0 },
  90
  91{IBIOS, T_CX,       T_PCIBUS, 0, NULL, "C/X PCI", "cxpbios.bin", DEFAULT_LOC "cxpbios.bin", 0 },
  92{IFEP,  T_CX,       T_PCIBUS, 0, NULL, "C/X PCI", "cxpfep.bin", DEFAULT_LOC "cxpfep.bin", 0 },
  93
  94{ICONC, T_CX,       SUBTYPE, 0, NULL, "C/X",    "cxcon.bin", DEFAULT_LOC "cxcon.bin", 0 },
  95{ICONC, T_CX,       SUBTYPE, 0, NULL, "C/X",    "ibmcxcon.bin", DEFAULT_LOC "ibmcxcon.bin", 0 },
  96{ICONC, T_CX,       SUBTYPE, 0, NULL, "C/X",    "ibmencon.bin", DEFAULT_LOC "ibmencon.bin", 0 },
  97
  98{IBIOS, FAMILY,   T_PCXR, 0, NULL, "PCXR",      "xrbios.bin", DEFAULT_LOC "xrbios.bin", 0 },
  99{IFEP,  FAMILY,   T_PCXR, 0,  NULL,  "PCXR",    "xrfep.bin", DEFAULT_LOC "xrfep.bin", 0  },
 100
 101{IBIOS, T_PCLITE,   SUBTYPE, 0, NULL, "X/em",   "sxbios.bin", DEFAULT_LOC "sxbios.bin", 0 },
 102{IFEP,  T_PCLITE,   SUBTYPE, 0,  NULL,  "X/em", "sxfep.bin", DEFAULT_LOC "sxfep.bin", 0  },
 103
 104{IBIOS, T_EPC,      T_PCIBUS, 0, NULL, "PCI",   "pcibios.bin", DEFAULT_LOC "pcibios.bin", 0 },
 105{IFEP,  T_EPC,      T_PCIBUS, 0, NULL, "PCI",   "pcifep.bin", DEFAULT_LOC "pcifep.bin", 0 },
 106{ICONFIG, 0,        0, 0, NULL,         NULL,   "dgap.conf",    "/etc/dgap.conf", 0 },
 107
 108/* IBAD/NULL entry indicating end-of-table */
 109
 110{IBAD,  0,     0, 0,  NULL,  NULL, NULL, NULL, 0 }
 111
 112} ;
 113
 114int     errorprint = 1;
 115int     nodldprint = 1;
 116int     debugflag;
 117int     fd;
 118
 119struct downld_t *ip;    /* Image pointer in current image  */
 120struct downld_t *dp;    /* conc. download */
 121
 122
 123/*
 124 * The same for either the FEP or the BIOS. 
 125 *  Append the downldio header, issue the ioctl, then free
 126 *  the buffer.  Not horribly CPU efficient, but quite RAM efficient.
 127 */
 128
 129void squirt(int req_type, int bdid, struct image_info *ii)
 130{
 131        struct downldio *dliop;
 132        int size_buf;
 133        int sfd;
 134        struct stat sb;
 135
 136        /*
 137         * If this binary comes from a file, stat it to see how
 138         * large it is. Yes, we intentionally do this each
 139         * time for the binary may change between loads. 
 140         */
 141
 142        if (ii->pathname) {
 143                sfd = open(ii->pathname, O_RDONLY);
 144
 145                if (sfd < 0 ) {
 146                        myperror(ii->pathname);
 147                        goto squirt_end; 
 148                }
 149
 150                if (fstat(sfd, &sb) == -1 ) {
 151                        myperror(ii->pathname);
 152                        goto squirt_end;
 153                }
 154
 155                ii->len = sb.st_size ; 
 156        }
 157
 158        size_buf = ii->len + sizeof(struct downldio);
 159
 160        /*
 161         * This buffer will be freed at the end of this function.  It is
 162         * not resilient and should be around only long enough for the d/l
 163         * to happen.
 164         */
 165        dliop = (struct downldio *) malloc(size_buf);
 166
 167        if (dliop == NULL) {
 168                fprintf(stderr,"%s: can't get %d bytes of memory; aborting\n", 
 169                        pgm, size_buf);
 170                exit (1);
 171        }
 172
 173        /* Now, stick the image in fepimage.  This can come from either
 174         *  the compiled-in image or from the filesystem.
 175         */
 176        if (ii->pathname)
 177                read(sfd, dliop->image.fi.fepimage, ii->len);
 178        else
 179                memcpy(dliop ->image.fi.fepimage, ii->image, ii->len);
 180
 181        dliop->req_type = req_type;
 182        dliop->bdid = bdid;
 183
 184        dliop->image.fi.len = ii->len;
 185
 186        if (debugflag)
 187                printf("sending %d bytes of %s %s from %s\n",
 188                        ii->len, 
 189                        (ii->type == IFEP) ? "FEP" : (ii->type == IBIOS) ? "BIOS" : "CONFIG",
 190                        ii->name ? ii->name : "",
 191                        (ii->pathname) ? ii->pathname : "internal image" );
 192
 193        if (ioctl(fd, DIGI_DLREQ_SET, (char *) dliop) == -1) {
 194                if(errorprint) {
 195                        fprintf(stderr,
 196                                "%s: warning - download ioctl failed\n",pgm);
 197                        errorprint = 0;
 198                }
 199                sleep(2);
 200        }
 201
 202squirt_end:
 203
 204        if (ii->pathname) {
 205                close(sfd);
 206        }
 207        free(dliop);
 208}
 209
 210
 211/*
 212 *  See if we need to reload the download image in core 
 213 * 
 214 */
 215void consider_file_rescan(struct image_info *ii)
 216{
 217        int sfd ; 
 218        int len ; 
 219        struct stat     sb;
 220
 221        /* This operation only makes sense when we're working from a file */
 222
 223        if (ii->pathname) {
 224
 225                sfd = open (ii->pathname, O_RDONLY) ;
 226                if (sfd < 0 ) {
 227                        myperror(ii->pathname);
 228                        exit(1) ;
 229                }
 230
 231                if( fstat(sfd,&sb) == -1 ) {
 232                        myperror(ii->pathname);
 233                        exit(1);
 234                }
 235                
 236                /* If the file hasn't changed since we last did this, 
 237                 * and we have not done a free() on the image, bail  
 238                 */
 239                if (ii->image && (sb.st_mtime == ii->mtime))
 240                        goto end_rescan;
 241
 242                ii->len = len = sb.st_size ; 
 243
 244                /* Record the timestamp of the file */
 245                ii->mtime = sb.st_mtime;
 246
 247                /* image should be NULL unless there is an image malloced
 248                 * in already.  Before we malloc again, make sure we don't
 249                 * have a memory leak.
 250                 */
 251                if ( ii->image ) {
 252                        free( ii->image ); 
 253                        /* ii->image = NULL; */ /* not necessary */
 254                }
 255
 256                /* This image will be kept only long enough for the 
 257                 * download to happen.  After sending the last block, 
 258                 * it will be freed
 259                 */
 260                ii->image = malloc(len) ;
 261
 262                if (ii->image == NULL) {
 263                        fprintf(stderr,
 264                                "%s: can't get %d bytes of memory; aborting\n",
 265                                 pgm, len);
 266                        exit (1);
 267                }
 268
 269                if (read(sfd, ii->image, len) < len) {
 270                        fprintf(stderr,"%s: read error on %s; aborting\n", 
 271                                pgm, ii->pathname);
 272                        exit (1);
 273                }
 274
 275end_rescan:
 276                close(sfd);
 277                
 278        }
 279}
 280
 281/*
 282 * Scan for images to match the driver requests
 283 */
 284
 285struct image_info * find_conc_image()
 286{
 287        int x ; 
 288        struct image_info *i = NULL ; 
 289
 290        for ( x = 0; x < nimages; x++ ) {
 291                i=&image_list[x];
 292                                
 293                if(i->type != ICONC)
 294                        continue;
 295
 296                consider_file_rescan(i) ;
 297
 298                ip = (struct downld_t *) image_list[x].image;
 299                if (ip == NULL) continue;
 300
 301                /*
 302                 * When I removed Clusterport, I kept only the code that I
 303                 * was SURE wasn't ClusterPort.  We may not need the next two
 304                 * lines of code.
 305                 */
 306                if ((dp->dl_type != 'P' ) && ( ip->dl_srev == dp->dl_srev ))
 307                        return i;
 308        } 
 309        return NULL ; 
 310}
 311
 312
 313int main(int argc, char **argv)
 314{
 315        struct downldio dlio;
 316        int             offset, bsize;
 317        int             x;
 318        char            *down, *image, *fname;
 319        struct image_info *ii;
 320
 321        pgm = argv[0];
 322        dp = &dlio.image.dl;            /* conc. download */
 323
 324        while((argc > 2) && !strcmp(argv[1],"-d")) {
 325                debugflag++ ;
 326                argc-- ;
 327                argv++ ;
 328        }
 329
 330        if(argc < 2) {
 331                fprintf(stderr,
 332                        "usage: %s download-device [image-file] ...\n",
 333                        pgm);
 334                exit(1);
 335        }
 336
 337
 338
 339        /*
 340         * Daemonize, unless debugging is turned on.
 341         */
 342        if (debugflag == 0) {
 343                switch (fork())
 344                {
 345                case 0:
 346                        break;
 347
 348                case -1:
 349                        return 1;
 350
 351                default:
 352                        return 0;
 353                }
 354
 355                setsid();
 356
 357                /*
 358                 * The child no longer needs "stdin", "stdout", or "stderr",
 359                 * and should not block processes waiting for them to close.
 360                 */
 361                fclose(stdin);
 362                fclose(stdout);
 363                fclose(stderr);
 364
 365        }
 366
 367        while (1) {
 368                if( (fd = open(argv[1], O_RDWR)) == -1 ) {
 369                        sleep(1);
 370                }
 371                else
 372                        break;
 373        }
 374
 375        /*
 376        ** create a list of images to search through when trying to match
 377        ** requests from the driver.  Put images from the command line in
 378        ** the list before built in images so that the command line images
 379        ** can override the built in ones.
 380        */
 381        
 382        /* allocate space for the list */
 383
 384        nimages = argc - 2;
 385
 386        /* count the number of default list entries */
 387
 388        for (count = 0; images[count].type != IBAD; ++count) ;
 389
 390        nimages += count;
 391
 392        /* Really should just remove the variable "image_list".... robertl */
 393        image_list = images ; 
 394           
 395        /* get the images from the command line */
 396        for(x = 2; x < argc; x++) {
 397                int xx; 
 398
 399                /*
 400                 * strip off any leading path information for 
 401                 * determining file type 
 402                 */
 403                if( (fname = strrchr(argv[x],'/')) == NULL)
 404                        fname = argv[x];
 405                else
 406                        fname++;        /* skip the slash */
 407
 408                for (xx = 0; xx < count; xx++) {
 409                        if (strcmp(fname, images[xx].fname) == 0 ) { 
 410                                images[xx].pathname = argv[x];
 411
 412                                /* image should be NULL until */
 413                                /* space is malloced */
 414                                images[xx].image = NULL ;  
 415                        }
 416                }
 417        }
 418
 419        sleep(3);
 420        
 421        /*
 422        ** Endless loop: get a request from the fep, and service that request.
 423        */
 424        for(;;) {
 425                /* get the request */
 426                if (debugflag)
 427                        printf("b4 get ioctl...");
 428        
 429                if (ioctl(fd,DIGI_DLREQ_GET, &dlio) == -1 ) {
 430                        if (errorprint) {
 431                                fprintf(stderr,
 432                                        "%s: warning - download ioctl failed\n",
 433                                        pgm);
 434                                errorprint = 0;
 435                        }
 436                        sleep(2);
 437                } else {
 438                        if (debugflag)
 439                                printf("dlio.req_type is %d bd %d\n",
 440                                        dlio.req_type,dlio.bdid);
 441        
 442                        switch(dlio.req_type) {
 443                        case DLREQ_BIOS:
 444                                /*
 445                                ** find the bios image for this type
 446                                */
 447                                for ( x = 0; x < nimages; x++ ) {
 448                                        if(image_list[x].type != IBIOS)
 449                                                continue;
 450        
 451                                        if ((dlio.image.fi.type & FAMILY) == 
 452                                                image_list[x].family) {
 453                                                
 454                                                if ( image_list[x].family == T_CX   ) { 
 455                                                        if ((dlio.image.fi.type & BUSTYPE) 
 456                                                                == T_PCIBUS ) {
 457                                                                if ( image_list[x].subtype 
 458                                                                        == T_PCIBUS )
 459                                                                        break;
 460                                                        }
 461                                                        else { 
 462                                                                break;
 463                                                        }
 464                                                }
 465                                                else if ( image_list[x].family == T_EPC ) {
 466                                                /* If subtype of image is T_PCIBUS, it is */
 467                                                /* a PCI EPC image, so the board must */
 468                                                /* have bus type T_PCIBUS to match */
 469                                                        if ((dlio.image.fi.type & BUSTYPE) 
 470                                                                == T_PCIBUS ) {
 471                                                                if ( image_list[x].subtype 
 472                                                                        == T_PCIBUS )
 473                                                                        break;
 474                                                        }
 475                                                        else { 
 476                                                        /* NON PCI EPC doesn't use PCI image */
 477                                                                if ( image_list[x].subtype 
 478                                                                        != T_PCIBUS )
 479                                                                        break;
 480                                                        }
 481                                                }
 482                                                else
 483                                                        break;
 484                                        }
 485                                        else if ((dlio.image.fi.type & SUBTYPE) == image_list[x].subtype) {
 486                                                /* PCXR board will break out of the loop here */
 487                                                if ( image_list[x].subtype == T_PCXR   ) { 
 488                                                                        break;
 489                                                }
 490                                        }
 491                                }
 492        
 493                                if ( x >= nimages) {
 494                                        /*
 495                                        ** no valid images exist
 496                                        */
 497                                        if(nodldprint) {
 498                                                fprintf(stderr,
 499                                                "%s: cannot find correct BIOS image\n",
 500                                                        pgm);
 501                                                nodldprint = 0;
 502                                        }
 503                                        dlio.image.fi.type = -1;
 504                                        if (ioctl(fd, DIGI_DLREQ_SET, &dlio) == -1) {
 505                                                if (errorprint) {
 506                                                        fprintf(stderr,
 507                                                        "%s: warning - download ioctl failed\n",
 508                                                        pgm);
 509                                                        errorprint = 0;
 510                                                }
 511                                                sleep(2);
 512                                        }
 513                                        break;
 514                                }
 515                                squirt(dlio.req_type, dlio.bdid, &image_list[x]);
 516                                break ;
 517        
 518                        case DLREQ_FEP:
 519                                /*
 520                                ** find the fep image for this type
 521                                */
 522                                for ( x = 0; x < nimages; x++ ) {
 523                                        if(image_list[x].type != IFEP)
 524                                                continue;
 525                                        if( (dlio.image.fi.type & FAMILY) == 
 526                                                image_list[x].family ) {
 527                                                if ( image_list[x].family == T_CX   ) { 
 528                                                        /* C/X PCI board */
 529                                                        if ((dlio.image.fi.type & BUSTYPE) 
 530                                                                == T_PCIBUS ) {
 531                                                                if ( image_list[x].subtype
 532                                                                        == T_PCIBUS )
 533                                                                        break;
 534                                                        }
 535                                                        else { 
 536                                                        /* Regular CX */
 537                                                                break;
 538                                                        }
 539                                                }
 540                                                else if ( image_list[x].family == T_EPC   )  {
 541                                                /* If subtype of image is T_PCIBUS, it is */
 542                                                /* a PCI EPC image, so the board must */
 543                                                /* have bus type T_PCIBUS to match */
 544                                                        if ((dlio.image.fi.type & BUSTYPE) 
 545                                                                == T_PCIBUS ) {
 546                                                                if ( image_list[x].subtype 
 547                                                                        == T_PCIBUS )
 548                                                                        break;
 549                                                        }
 550                                                        else { 
 551                                                        /* NON PCI EPC doesn't use PCI image */
 552                                                                if ( image_list[x].subtype 
 553                                                                        != T_PCIBUS )
 554                                                                        break;
 555                                                        }
 556                                                }
 557                                                else
 558                                                        break;
 559                                        }
 560                                        else if ((dlio.image.fi.type & SUBTYPE) == image_list[x].subtype) {
 561                                                /* PCXR board will break out of the loop here */
 562                                                if ( image_list[x].subtype == T_PCXR   ) { 
 563                                                                        break;
 564                                                }
 565                                        }
 566                                }
 567        
 568                                if ( x >= nimages) {
 569                                        /*
 570                                        ** no valid images exist
 571                                        */
 572                                        if(nodldprint) {
 573                                                fprintf(stderr,
 574                                                "%s: cannot find correct FEP image\n",
 575                                                        pgm);
 576                                                nodldprint = 0;
 577                                        }
 578                                        dlio.image.fi.type=-1;
 579                                        if( ioctl(fd,DIGI_DLREQ_SET,&dlio) == -1 ) {
 580                                                if(errorprint) {
 581                                                        fprintf(stderr,
 582                                                "%s: warning - download ioctl failed\n",
 583                                                                pgm);
 584                                                        errorprint=0;
 585                                                }
 586                                                sleep(2);
 587                                        }
 588                                        break;
 589                                }
 590                                squirt(dlio.req_type, dlio.bdid, &image_list[x]);
 591                                break;
 592
 593                        case DLREQ_DEVCREATE:
 594                                {
 595                                        char string[1024];
 596#if 0
 597                                        sprintf(string, "%s /proc/dgap/%d/mknod", DEFSHELL, dlio.bdid);
 598#endif
 599                                        sprintf(string, "%s /usr/sbin/dgap_updatedevs %d", DEFSHELL, dlio.bdid);
 600                                        system(string);
 601
 602                                        if (debugflag)
 603                                                printf("Created Devices.\n");
 604                                        if (ioctl(fd, DIGI_DLREQ_SET, &dlio) == -1 ) {
 605                                                if(errorprint) {
 606                                                        fprintf(stderr, "%s: warning - DEVCREATE ioctl failed\n",pgm);
 607                                                        errorprint = 0;
 608                                                }
 609                                                sleep(2);
 610                                        }
 611                                        if (debugflag)
 612                                                printf("After ioctl set - Created Device.\n");
 613                                }
 614
 615                                break;
 616        
 617                        case DLREQ_CONFIG:
 618                                for ( x = 0; x < nimages; x++ ) {
 619                                        if(image_list[x].type != ICONFIG)
 620                                                continue;
 621                                        else
 622                                                break;
 623                                }
 624
 625                                if ( x >= nimages) {
 626                                        /*
 627                                        ** no valid images exist
 628                                        */
 629                                        if(nodldprint) {
 630                                                fprintf(stderr,
 631                                                "%s: cannot find correct CONFIG image\n",
 632                                                        pgm);
 633                                                nodldprint = 0;
 634                                        }
 635                                        dlio.image.fi.type=-1;
 636                                        if (ioctl(fd, DIGI_DLREQ_SET, &dlio) == -1 ) {
 637                                                if(errorprint) {
 638                                                        fprintf(stderr,
 639                                                "%s: warning - download ioctl failed\n",
 640                                                                pgm);
 641                                                        errorprint=0;
 642                                                }
 643                                                sleep(2);
 644                                        }
 645                                        break;
 646                                }
 647
 648                                squirt(dlio.req_type, dlio.bdid, &image_list[x]);
 649                                break;
 650
 651                        case DLREQ_CONC:
 652                                /*
 653                                ** find the image needed for this download
 654                                */
 655                                if ( dp->dl_seq == 0 ) {
 656                                        /*
 657                                        ** find image for hardware rev range
 658                                        */
 659                                        for ( x = 0; x < nimages; x++ ) {
 660                                                ii=&image_list[x];
 661                
 662                                                if(image_list[x].type != ICONC)
 663                                                        continue;
 664                
 665                                                consider_file_rescan(ii) ;
 666                
 667                                                ip = (struct downld_t *) image_list[x].image;
 668                                                if (ip == NULL) continue;
 669                
 670                                                /*
 671                                                 * When I removed Clusterport, I kept only the
 672                                                 * code that I was SURE wasn't ClusterPort.
 673                                                 * We may not need the next four lines of code.
 674                                                 */
 675
 676                                                if ((dp->dl_type != 'P' ) &&
 677                                                 (ip->dl_lrev <= dp->dl_lrev ) && 
 678                                                 ( dp->dl_lrev <= ip->dl_hrev))
 679                                                        break;
 680                                        }
 681                                    
 682                                        if ( x >= nimages ) {
 683                                                /*
 684                                                ** No valid images exist
 685                                                */
 686                                                if(nodldprint) {
 687                                                        fprintf(stderr,
 688                                                "%s: cannot find correct download image %d\n",
 689                                                                pgm, dp->dl_lrev);
 690                                                        nodldprint=0;
 691                                                }
 692                                                continue;
 693                                        }
 694                                    
 695                                } else {
 696                                        /*
 697                                        ** find image version required
 698                                        */
 699                                        if ((ii = find_conc_image()) == NULL ) {
 700                                                /*
 701                                                ** No valid images exist
 702                                                */
 703                                                fprintf(stderr,
 704                                                "%s: can't find rest of download image??\n",
 705                                                        pgm);
 706                                                continue;
 707                                        }
 708                                }
 709                        
 710                                /*
 711                                ** download block of image
 712                                */
 713                        
 714                                offset = 1024 * dp->dl_seq;
 715                                
 716                                /*
 717                                ** test if block requested within image
 718                                */
 719                                if ( offset < ii->len ) { 
 720        
 721                                        /*
 722                                        ** if it is, determine block size, set segment,
 723                                        ** set size, set pointers, and copy block
 724                                        */
 725                                        if (( bsize = ii->len - offset ) > 1024 )
 726                                                bsize = 1024;
 727                                    
 728                                        /*
 729                                        ** copy image version info to download area
 730                                        */
 731                                        dp->dl_srev = ip->dl_srev;
 732                                        dp->dl_lrev = ip->dl_lrev;
 733                                        dp->dl_hrev = ip->dl_hrev;
 734                                    
 735                                        dp->dl_seg = (64 * dp->dl_seq) + ip->dl_seg;
 736                                        dp->dl_size = bsize;
 737                                    
 738                                        down = (char *)&dp->dl_data[0];
 739                                        image = (char *)((char *)ip + offset);
 740        
 741                                        memcpy(down, image, bsize);
 742                                } 
 743                                else {
 744                                        /*
 745                                        ** Image has been downloaded, set segment and
 746                                        ** size to indicate no more blocks
 747                                        */
 748                                        dp->dl_seg = ip->dl_seg;
 749                                        dp->dl_size = 0;
 750        
 751                                        /* Now, we can release the concentrator */
 752                                        /* image from memory if we're running  */
 753                                        /* from filesystem images */
 754                
 755                                        if (ii->pathname)
 756                                                if (ii->image) {
 757                                                        free(ii->image);
 758                                                        ii->image = NULL ; 
 759                                                } 
 760                                }
 761                        
 762                                if (debugflag)
 763                                                printf(
 764                                                "sending conc dl section %d to %s from %s\n",
 765                                                        dp->dl_seq, ii->name,
 766                                                ii->pathname ? ii->pathname : "Internal Image");
 767                
 768                                if (ioctl(fd, DIGI_DLREQ_SET, &dlio) == -1 ) {
 769                                        if (errorprint) {
 770                                                fprintf(stderr,
 771                                                "%s: warning - download ioctl failed\n",
 772                                                        pgm);
 773                                                errorprint=0;
 774                                        }
 775                                        sleep(2);
 776                                }
 777                                break;
 778                        } /* switch */
 779                }
 780                if (debugflag > 1) {
 781                        printf("pausing: "); fflush(stdout);
 782                        fflush(stdin);
 783                        while(getchar() != '\n');
 784                                printf("continuing\n");
 785                }
 786        }
 787}
 788
 789/*
 790** myperror()
 791**
 792**  Same as normal perror(), but places the program name at the begining
 793**  of the message.
 794*/
 795void myperror(char *s)
 796{
 797        fprintf(stderr,"%s: %s: %s.\n",pgm, s, strerror(errno));
 798}
 799