linux/drivers/staging/ft1000/ft1000-usb/ft1000_download.c
<<
>>
Prefs
   1/*
   2* CopyRight (C) 2007 Qualcomm Inc. All Rights Reserved.
   3*
   4* This file is part of Express Card USB Driver
   5*/
   6
   7#include <linux/kernel.h>
   8#include <linux/module.h>
   9#include <linux/netdevice.h>
  10#include <linux/etherdevice.h>
  11#include <linux/usb.h>
  12#include <linux/vmalloc.h>
  13#include "ft1000_usb.h"
  14
  15
  16#define  DWNLD_HANDSHAKE_LOC     0x02
  17#define  DWNLD_TYPE_LOC          0x04
  18#define  DWNLD_SIZE_MSW_LOC      0x06
  19#define  DWNLD_SIZE_LSW_LOC      0x08
  20#define  DWNLD_PS_HDR_LOC        0x0A
  21
  22#define  MAX_DSP_WAIT_LOOPS      40
  23#define  DSP_WAIT_SLEEP_TIME     1000       /* 1 millisecond */
  24#define  DSP_WAIT_DISPATCH_LVL   50         /* 50 usec */
  25
  26#define  HANDSHAKE_TIMEOUT_VALUE 0xF1F1
  27#define  HANDSHAKE_RESET_VALUE   0xFEFE   /* When DSP requests startover */
  28#define  HANDSHAKE_RESET_VALUE_USB   0xFE7E   /* When DSP requests startover */
  29#define  HANDSHAKE_DSP_BL_READY  0xFEFE   /* At start DSP writes this when bootloader ready */
  30#define  HANDSHAKE_DSP_BL_READY_USB  0xFE7E   /* At start DSP writes this when bootloader ready */
  31#define  HANDSHAKE_DRIVER_READY  0xFFFF   /* Driver writes after receiving 0xFEFE */
  32#define  HANDSHAKE_SEND_DATA     0x0000   /* DSP writes this when ready for more data */
  33
  34#define  HANDSHAKE_REQUEST       0x0001   /* Request from DSP */
  35#define  HANDSHAKE_RESPONSE      0x0000   /* Satisfied DSP request */
  36
  37#define  REQUEST_CODE_LENGTH     0x0000
  38#define  REQUEST_RUN_ADDRESS     0x0001
  39#define  REQUEST_CODE_SEGMENT    0x0002   /* In WORD count */
  40#define  REQUEST_DONE_BL         0x0003
  41#define  REQUEST_DONE_CL         0x0004
  42#define  REQUEST_VERSION_INFO    0x0005
  43#define  REQUEST_CODE_BY_VERSION 0x0006
  44#define  REQUEST_MAILBOX_DATA    0x0007
  45#define  REQUEST_FILE_CHECKSUM   0x0008
  46
  47#define  STATE_START_DWNLD       0x01
  48#define  STATE_BOOT_DWNLD        0x02
  49#define  STATE_CODE_DWNLD        0x03
  50#define  STATE_DONE_DWNLD        0x04
  51#define  STATE_SECTION_PROV      0x05
  52#define  STATE_DONE_PROV         0x06
  53#define  STATE_DONE_FILE         0x07
  54
  55#define  MAX_LENGTH              0x7f0
  56
  57/* Temporary download mechanism for Magnemite */
  58#define  DWNLD_MAG_TYPE_LOC          0x00
  59#define  DWNLD_MAG_LEN_LOC           0x01
  60#define  DWNLD_MAG_ADDR_LOC          0x02
  61#define  DWNLD_MAG_CHKSUM_LOC        0x03
  62#define  DWNLD_MAG_VAL_LOC           0x04
  63
  64#define  HANDSHAKE_MAG_DSP_BL_READY  0xFEFE0000   /* At start DSP writes this when bootloader ready */
  65#define  HANDSHAKE_MAG_DSP_ENTRY     0x01000000   /* Dsp writes this to request for entry address */
  66#define  HANDSHAKE_MAG_DSP_DATA      0x02000000   /* Dsp writes this to request for data block */
  67#define  HANDSHAKE_MAG_DSP_DONE      0x03000000   /* Dsp writes this to indicate download done */
  68
  69#define  HANDSHAKE_MAG_DRV_READY     0xFFFF0000   /* Driver writes this to indicate ready to download */
  70#define  HANDSHAKE_MAG_DRV_DATA      0x02FECDAB   /* Driver writes this to indicate data available to DSP */
  71#define  HANDSHAKE_MAG_DRV_ENTRY     0x01FECDAB   /* Driver writes this to indicate entry point to DSP */
  72
  73#define  HANDSHAKE_MAG_TIMEOUT_VALUE 0xF1F1
  74
  75
  76/* New Magnemite downloader */
  77#define  DWNLD_MAG1_HANDSHAKE_LOC     0x00
  78#define  DWNLD_MAG1_TYPE_LOC          0x01
  79#define  DWNLD_MAG1_SIZE_LOC          0x02
  80#define  DWNLD_MAG1_PS_HDR_LOC        0x03
  81
  82struct dsp_file_hdr {
  83        long              version_id;          /* Version ID of this image format. */
  84        long              package_id;          /* Package ID of code release. */
  85        long              build_date;          /* Date/time stamp when file was built. */
  86        long              commands_offset;     /* Offset to attached commands in Pseudo Hdr format. */
  87        long              loader_offset;       /* Offset to bootloader code. */
  88        long              loader_code_address; /* Start address of bootloader. */
  89        long              loader_code_end;     /* Where bootloader code ends. */
  90        long              loader_code_size;
  91        long              version_data_offset; /* Offset were scrambled version data begins. */
  92        long              version_data_size;   /* Size, in words, of scrambled version data. */
  93        long              nDspImages;          /* Number of DSP images in file. */
  94};
  95
  96#pragma pack(1)
  97struct dsp_image_info {
  98        long              coff_date;           /* Date/time when DSP Coff image was built. */
  99        long              begin_offset;        /* Offset in file where image begins. */
 100        long              end_offset;          /* Offset in file where image begins. */
 101        long              run_address;         /* On chip Start address of DSP code. */
 102        long              image_size;          /* Size of image. */
 103        long              version;             /* Embedded version # of DSP code. */
 104        unsigned short    checksum;            /* DSP File checksum */
 105        unsigned short    pad1;
 106};
 107
 108
 109/* checks if the doorbell register is cleared */
 110static int check_usb_db(struct ft1000_usb *ft1000dev)
 111{
 112        int loopcnt;
 113        u16 temp;
 114        int status;
 115
 116        loopcnt = 0;
 117
 118        while (loopcnt < 10) {
 119                status = ft1000_read_register(ft1000dev, &temp,
 120                                               FT1000_REG_DOORBELL);
 121                DEBUG("check_usb_db: read FT1000_REG_DOORBELL value is %x\n",
 122                       temp);
 123                if (temp & 0x0080) {
 124                        DEBUG("FT1000:Got checkusb doorbell\n");
 125                        status = ft1000_write_register(ft1000dev, 0x0080,
 126                                                FT1000_REG_DOORBELL);
 127                        status = ft1000_write_register(ft1000dev, 0x0100,
 128                                                FT1000_REG_DOORBELL);
 129                        status = ft1000_write_register(ft1000dev,  0x8000,
 130                                                FT1000_REG_DOORBELL);
 131                        break;
 132                } else {
 133                        loopcnt++;
 134                        msleep(10);
 135                }
 136
 137        }
 138
 139        loopcnt = 0;
 140        while (loopcnt < 20) {
 141                status = ft1000_read_register(ft1000dev, &temp,
 142                                               FT1000_REG_DOORBELL);
 143                DEBUG("FT1000:check_usb_db:Doorbell = 0x%x\n", temp);
 144                if (temp & 0x8000) {
 145                        loopcnt++;
 146                        msleep(10);
 147                } else  {
 148                        DEBUG("check_usb_db: door bell is cleared, return 0\n");
 149                        return 0;
 150                }
 151        }
 152
 153        return -1;
 154}
 155
 156/* gets the handshake and compares it with the expected value */
 157static u16 get_handshake(struct ft1000_usb *ft1000dev, u16 expected_value)
 158{
 159        u16 handshake;
 160        int loopcnt;
 161        int status = 0;
 162
 163        loopcnt = 0;
 164
 165        while (loopcnt < 100) {
 166                /* Need to clear downloader doorbell if Hartley ASIC */
 167                status = ft1000_write_register(ft1000dev,  FT1000_DB_DNLD_RX,
 168                                                FT1000_REG_DOORBELL);
 169                if (ft1000dev->fcodeldr) {
 170                        DEBUG(" get_handshake: fcodeldr is %d\n",
 171                                ft1000dev->fcodeldr);
 172                        ft1000dev->fcodeldr = 0;
 173                        status = check_usb_db(ft1000dev);
 174                        if (status != 0) {
 175                                DEBUG("get_handshake: check_usb_db failed\n");
 176                                break;
 177                        }
 178                        status = ft1000_write_register(ft1000dev,
 179                                        FT1000_DB_DNLD_RX,
 180                                        FT1000_REG_DOORBELL);
 181                }
 182
 183                status = ft1000_read_dpram16(ft1000dev,
 184                                DWNLD_MAG1_HANDSHAKE_LOC, (u8 *)&handshake, 1);
 185                handshake = ntohs(handshake);
 186
 187                if (status)
 188                        return HANDSHAKE_TIMEOUT_VALUE;
 189
 190                if ((handshake == expected_value) ||
 191                    (handshake == HANDSHAKE_RESET_VALUE_USB)) {
 192                        return handshake;
 193                } else  {
 194                        loopcnt++;
 195                        msleep(10);
 196                }
 197        }
 198
 199        return HANDSHAKE_TIMEOUT_VALUE;
 200}
 201
 202/* write the handshake value to the handshake location */
 203static void put_handshake(struct ft1000_usb *ft1000dev, u16 handshake_value)
 204{
 205        u32 tempx;
 206        u16 tempword;
 207        int status;
 208
 209        tempx = (u32)handshake_value;
 210        tempx = ntohl(tempx);
 211
 212        tempword = (u16)(tempx & 0xffff);
 213        status = ft1000_write_dpram16(ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC,
 214                                        tempword, 0);
 215        tempword = (u16)(tempx >> 16);
 216        status = ft1000_write_dpram16(ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC,
 217                                        tempword, 1);
 218        status = ft1000_write_register(ft1000dev, FT1000_DB_DNLD_TX,
 219                                        FT1000_REG_DOORBELL);
 220}
 221
 222static u16 get_handshake_usb(struct ft1000_usb *ft1000dev, u16 expected_value)
 223{
 224        u16 handshake;
 225        int loopcnt;
 226        u16 temp;
 227        int status = 0;
 228
 229        loopcnt = 0;
 230        handshake = 0;
 231
 232        while (loopcnt < 100) {
 233                if (ft1000dev->usbboot == 2) {
 234                        status = ft1000_read_dpram32(ft1000dev, 0,
 235                                        (u8 *)&(ft1000dev->tempbuf[0]), 64);
 236                        for (temp = 0; temp < 16; temp++) {
 237                                DEBUG("tempbuf %d = 0x%x\n", temp,
 238                                        ft1000dev->tempbuf[temp]);
 239                        }
 240                        status = ft1000_read_dpram16(ft1000dev,
 241                                                DWNLD_MAG1_HANDSHAKE_LOC,
 242                                                (u8 *)&handshake, 1);
 243                        DEBUG("handshake from read_dpram16 = 0x%x\n",
 244                                handshake);
 245                        if (ft1000dev->dspalive == ft1000dev->tempbuf[6]) {
 246                                handshake = 0;
 247                        } else {
 248                                handshake = ft1000dev->tempbuf[1];
 249                                ft1000dev->dspalive =
 250                                                ft1000dev->tempbuf[6];
 251                        }
 252                } else {
 253                        status = ft1000_read_dpram16(ft1000dev,
 254                                                DWNLD_MAG1_HANDSHAKE_LOC,
 255                                                (u8 *)&handshake, 1);
 256                }
 257
 258                loopcnt++;
 259                msleep(10);
 260                handshake = ntohs(handshake);
 261                if ((handshake == expected_value) ||
 262                    (handshake == HANDSHAKE_RESET_VALUE_USB))
 263                        return handshake;
 264        }
 265
 266        return HANDSHAKE_TIMEOUT_VALUE;
 267}
 268
 269static void put_handshake_usb(struct ft1000_usb *ft1000dev, u16 handshake_value)
 270{
 271        int i;
 272
 273        for (i = 0; i < 1000; i++)
 274                ;
 275}
 276
 277static u16 get_request_type(struct ft1000_usb *ft1000dev)
 278{
 279        u16 request_type;
 280        int status;
 281        u16 tempword;
 282        u32 tempx;
 283
 284        if (ft1000dev->bootmode == 1) {
 285                status = fix_ft1000_read_dpram32(ft1000dev,
 286                                DWNLD_MAG1_TYPE_LOC, (u8 *)&tempx);
 287                tempx = ntohl(tempx);
 288        } else {
 289                tempx = 0;
 290                status = ft1000_read_dpram16(ft1000dev,
 291                                DWNLD_MAG1_TYPE_LOC, (u8 *)&tempword, 1);
 292                tempx |= (tempword << 16);
 293                tempx = ntohl(tempx);
 294        }
 295        request_type = (u16)tempx;
 296
 297        return request_type;
 298}
 299
 300static u16 get_request_type_usb(struct ft1000_usb *ft1000dev)
 301{
 302        u16 request_type;
 303        int status;
 304        u16 tempword;
 305        u32 tempx;
 306
 307        if (ft1000dev->bootmode == 1) {
 308                status = fix_ft1000_read_dpram32(ft1000dev,
 309                                DWNLD_MAG1_TYPE_LOC, (u8 *)&tempx);
 310                tempx = ntohl(tempx);
 311        } else {
 312                if (ft1000dev->usbboot == 2) {
 313                        tempx = ft1000dev->tempbuf[2];
 314                        tempword = ft1000dev->tempbuf[3];
 315                } else {
 316                        tempx = 0;
 317                        status = ft1000_read_dpram16(ft1000dev,
 318                                        DWNLD_MAG1_TYPE_LOC,
 319                                        (u8 *)&tempword, 1);
 320                }
 321                tempx |= (tempword << 16);
 322                tempx = ntohl(tempx);
 323        }
 324        request_type = (u16)tempx;
 325
 326        return request_type;
 327}
 328
 329static long get_request_value(struct ft1000_usb *ft1000dev)
 330{
 331        u32 value;
 332        u16 tempword;
 333        int status;
 334
 335        if (ft1000dev->bootmode == 1) {
 336                status = fix_ft1000_read_dpram32(ft1000dev,
 337                                DWNLD_MAG1_SIZE_LOC, (u8 *)&value);
 338                value = ntohl(value);
 339        } else  {
 340                status = ft1000_read_dpram16(ft1000dev,
 341                                DWNLD_MAG1_SIZE_LOC, (u8 *)&tempword, 0);
 342                value = tempword;
 343                status = ft1000_read_dpram16(ft1000dev,
 344                                DWNLD_MAG1_SIZE_LOC, (u8 *)&tempword, 1);
 345                value |= (tempword << 16);
 346                value = ntohl(value);
 347        }
 348
 349        return value;
 350}
 351
 352
 353/* writes a value to DWNLD_MAG1_SIZE_LOC */
 354static void put_request_value(struct ft1000_usb *ft1000dev, long lvalue)
 355{
 356        u32    tempx;
 357        int    status;
 358
 359        tempx = ntohl(lvalue);
 360        status = fix_ft1000_write_dpram32(ft1000dev, DWNLD_MAG1_SIZE_LOC,
 361                                          (u8 *)&tempx);
 362}
 363
 364
 365
 366/* returns the checksum of the pseudo header */
 367static u16 hdr_checksum(struct pseudo_hdr *pHdr)
 368{
 369        u16   *usPtr = (u16 *)pHdr;
 370        u16   chksum;
 371
 372
 373        chksum = ((((((usPtr[0] ^ usPtr[1]) ^ usPtr[2]) ^ usPtr[3]) ^
 374        usPtr[4]) ^ usPtr[5]) ^ usPtr[6]);
 375
 376        return chksum;
 377}
 378
 379static int check_buffers(u16 *buff_w, u16 *buff_r, int len, int offset)
 380{
 381        int i;
 382
 383        for (i = 0; i < len; i++) {
 384                if (buff_w[i] != buff_r[i + offset])
 385                        return -EREMOTEIO;
 386        }
 387
 388        return 0;
 389}
 390
 391static int write_dpram32_and_check(struct ft1000_usb *ft1000dev,
 392                u16 tempbuffer[], u16 dpram)
 393{
 394        int status;
 395        u16 resultbuffer[64];
 396        int i;
 397
 398        for (i = 0; i < 10; i++) {
 399                status = ft1000_write_dpram32(ft1000dev, dpram,
 400                                (u8 *)&tempbuffer[0], 64);
 401                if (status == 0) {
 402                        /* Work around for ASIC bit stuffing problem. */
 403                        if ((tempbuffer[31] & 0xfe00) == 0xfe00) {
 404                                status = ft1000_write_dpram32(ft1000dev,
 405                                                dpram+12, (u8 *)&tempbuffer[24],
 406                                                64);
 407                        }
 408                        /* Let's check the data written */
 409                        status = ft1000_read_dpram32(ft1000dev, dpram,
 410                                        (u8 *)&resultbuffer[0], 64);
 411                        if ((tempbuffer[31] & 0xfe00) == 0xfe00) {
 412                                if (check_buffers(tempbuffer, resultbuffer, 28,
 413                                                        0)) {
 414                                        DEBUG("FT1000:download:DPRAM write failed 1 during bootloading\n");
 415                                        usleep_range(9000, 11000);
 416                                        break;
 417                                }
 418                                status = ft1000_read_dpram32(ft1000dev,
 419                                                dpram+12,
 420                                                (u8 *)&resultbuffer[0], 64);
 421
 422                                if (check_buffers(tempbuffer, resultbuffer, 16,
 423                                                        24)) {
 424                                        DEBUG("FT1000:download:DPRAM write failed 2 during bootloading\n");
 425                                        usleep_range(9000, 11000);
 426                                        break;
 427                                }
 428                        } else {
 429                                if (check_buffers(tempbuffer, resultbuffer, 32,
 430                                                        0)) {
 431                                        DEBUG("FT1000:download:DPRAM write failed 3 during bootloading\n");
 432                                        usleep_range(9000, 11000);
 433                                        break;
 434                                }
 435                        }
 436                        if (status == 0)
 437                                break;
 438                }
 439        }
 440        return status;
 441}
 442
 443/* writes a block of DSP image to DPRAM
 444 * Parameters:  struct ft1000_usb  - device structure
 445 *              u16 **pUsFile - DSP image file pointer in u16
 446 *              u8  **pUcFile - DSP image file pointer in u8
 447 *              long word_length - length of the buffer to be written to DPRAM
 448 */
 449static int write_blk(struct ft1000_usb *ft1000dev, u16 **pUsFile, u8 **pUcFile,
 450                long word_length)
 451{
 452        int status = 0;
 453        u16 dpram;
 454        int loopcnt, i;
 455        u16 tempword;
 456        u16 tempbuffer[64];
 457
 458        /*DEBUG("FT1000:download:start word_length = %d\n",(int)word_length); */
 459        dpram = (u16)DWNLD_MAG1_PS_HDR_LOC;
 460        tempword = *(*pUsFile);
 461        (*pUsFile)++;
 462        status = ft1000_write_dpram16(ft1000dev, dpram, tempword, 0);
 463        tempword = *(*pUsFile);
 464        (*pUsFile)++;
 465        status = ft1000_write_dpram16(ft1000dev, dpram++, tempword, 1);
 466
 467        *pUcFile = *pUcFile + 4;
 468        word_length--;
 469        tempword = (u16)word_length;
 470        word_length = (word_length / 16) + 1;
 471        for (; word_length > 0; word_length--) { /* In words */
 472                loopcnt = 0;
 473                for (i = 0; i < 32; i++) {
 474                        if (tempword != 0) {
 475                                tempbuffer[i++] = *(*pUsFile);
 476                                (*pUsFile)++;
 477                                tempbuffer[i] = *(*pUsFile);
 478                                (*pUsFile)++;
 479                                *pUcFile = *pUcFile + 4;
 480                                loopcnt++;
 481                                tempword--;
 482                        } else {
 483                                tempbuffer[i++] = 0;
 484                                tempbuffer[i] = 0;
 485                        }
 486                }
 487
 488                /*DEBUG("write_blk: loopcnt is %d\n", loopcnt); */
 489                /*DEBUG("write_blk: bootmode = %d\n", bootmode); */
 490                /*DEBUG("write_blk: dpram = %x\n", dpram); */
 491                if (ft1000dev->bootmode == 0) {
 492                        if (dpram >= 0x3F4)
 493                                status = ft1000_write_dpram32(ft1000dev, dpram,
 494                                                (u8 *)&tempbuffer[0], 8);
 495                        else
 496                                status = ft1000_write_dpram32(ft1000dev, dpram,
 497                                                (u8 *)&tempbuffer[0], 64);
 498                } else {
 499                        status = write_dpram32_and_check(ft1000dev, tempbuffer,
 500                                        dpram);
 501                        if (status != 0) {
 502                                DEBUG("FT1000:download:Write failed tempbuffer[31] = 0x%x\n", tempbuffer[31]);
 503                                break;
 504                        }
 505                }
 506                dpram = dpram + loopcnt;
 507        }
 508        return status;
 509}
 510
 511static void usb_dnld_complete(struct urb *urb)
 512{
 513        /* DEBUG("****** usb_dnld_complete\n"); */
 514}
 515
 516/* writes a block of DSP image to DPRAM
 517 * Parameters:  struct ft1000_usb  - device structure
 518 *              u16 **pUsFile - DSP image file pointer in u16
 519 *              u8  **pUcFile - DSP image file pointer in u8
 520 *              long word_length - length of the buffer to be written to DPRAM
 521 */
 522static int write_blk_fifo(struct ft1000_usb *ft1000dev, u16 **pUsFile,
 523                          u8 **pUcFile, long word_length)
 524{
 525        int byte_length;
 526
 527        byte_length = word_length * 4;
 528
 529        if (byte_length && ((byte_length % 64) == 0))
 530                byte_length += 4;
 531
 532        if (byte_length < 64)
 533                byte_length = 68;
 534
 535        usb_init_urb(ft1000dev->tx_urb);
 536        memcpy(ft1000dev->tx_buf, *pUcFile, byte_length);
 537        usb_fill_bulk_urb(ft1000dev->tx_urb,
 538                          ft1000dev->dev,
 539                          usb_sndbulkpipe(ft1000dev->dev,
 540                                          ft1000dev->bulk_out_endpointAddr),
 541                          ft1000dev->tx_buf, byte_length, usb_dnld_complete,
 542                          (void *)ft1000dev);
 543
 544        usb_submit_urb(ft1000dev->tx_urb, GFP_ATOMIC);
 545
 546        *pUsFile = *pUsFile + (word_length << 1);
 547        *pUcFile = *pUcFile + (word_length << 2);
 548
 549        return 0;
 550}
 551
 552static int scram_start_dwnld(struct ft1000_usb *ft1000dev, u16 *hshake,
 553                u32 *state)
 554{
 555        int status = 0;
 556
 557        DEBUG("FT1000:STATE_START_DWNLD\n");
 558        if (ft1000dev->usbboot)
 559                *hshake = get_handshake_usb(ft1000dev, HANDSHAKE_DSP_BL_READY);
 560        else
 561                *hshake = get_handshake(ft1000dev, HANDSHAKE_DSP_BL_READY);
 562        if (*hshake == HANDSHAKE_DSP_BL_READY) {
 563                DEBUG("scram_dnldr: handshake is HANDSHAKE_DSP_BL_READY, call put_handshake(HANDSHAKE_DRIVER_READY)\n");
 564                put_handshake(ft1000dev, HANDSHAKE_DRIVER_READY);
 565        } else if (*hshake == HANDSHAKE_TIMEOUT_VALUE) {
 566                status = -ETIMEDOUT;
 567        } else {
 568                DEBUG("FT1000:download:Download error: Handshake failed\n");
 569                status = -ENETRESET;
 570        }
 571        *state = STATE_BOOT_DWNLD;
 572        return status;
 573}
 574
 575static int request_code_segment(struct ft1000_usb *ft1000dev, u16 **s_file,
 576                 u8 **c_file, const u8 *endpoint, bool boot_case)
 577{
 578        long word_length;
 579        int status = 0;
 580
 581        /*DEBUG("FT1000:REQUEST_CODE_SEGMENT\n");i*/
 582        word_length = get_request_value(ft1000dev);
 583        /*DEBUG("FT1000:word_length = 0x%x\n", (int)word_length); */
 584        /*NdisMSleep (100); */
 585        if (word_length > MAX_LENGTH) {
 586                DEBUG("FT1000:download:Download error: Max length exceeded\n");
 587                return -1;
 588        }
 589        if ((word_length * 2 + (long)c_file) > (long)endpoint) {
 590                /* Error, beyond boot code range.*/
 591                DEBUG("FT1000:download:Download error: Requested len=%d exceeds BOOT code boundary.\n", (int)word_length);
 592                return -1;
 593        }
 594        if (word_length & 0x1)
 595                word_length++;
 596        word_length = word_length / 2;
 597
 598        if (boot_case) {
 599                status = write_blk(ft1000dev, s_file, c_file, word_length);
 600                /*DEBUG("write_blk returned %d\n", status); */
 601        } else {
 602                status = write_blk_fifo(ft1000dev, s_file, c_file, word_length);
 603                if (ft1000dev->usbboot == 0)
 604                        ft1000dev->usbboot++;
 605                if (ft1000dev->usbboot == 1)
 606                        status |= ft1000_write_dpram16(ft1000dev,
 607                                        DWNLD_MAG1_PS_HDR_LOC, 0, 0);
 608        }
 609        return status;
 610}
 611
 612/* Scramble downloader for Harley based ASIC via USB interface */
 613int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart,
 614                u32 FileLength)
 615{
 616        int status = 0;
 617        u32 state;
 618        u16 handshake;
 619        struct pseudo_hdr *pseudo_header;
 620        u16 pseudo_header_len;
 621        long word_length;
 622        u16 request;
 623        u16 temp;
 624
 625        struct dsp_file_hdr *file_hdr;
 626        struct dsp_image_info *dsp_img_info = NULL;
 627        long requested_version;
 628        bool correct_version;
 629        struct drv_msg *mailbox_data;
 630        u16 *data = NULL;
 631        u16 *s_file = NULL;
 632        u8 *c_file = NULL;
 633        u8 *boot_end = NULL, *code_end = NULL;
 634        int image;
 635        long loader_code_address, loader_code_size = 0;
 636        long run_address = 0, run_size = 0;
 637
 638        u32 templong;
 639        u32 image_chksum = 0;
 640
 641        u16 dpram = 0;
 642        u8 *pbuffer;
 643        struct prov_record *pprov_record;
 644        struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net);
 645
 646        DEBUG("Entered   scram_dnldr...\n");
 647
 648        ft1000dev->fcodeldr = 0;
 649        ft1000dev->usbboot = 0;
 650        ft1000dev->dspalive = 0xffff;
 651
 652        /*
 653         * Get version id of file, at first 4 bytes of file, for newer files.
 654         */
 655
 656        state = STATE_START_DWNLD;
 657
 658        file_hdr = (struct dsp_file_hdr *)pFileStart;
 659
 660        ft1000_write_register(ft1000dev, 0x800, FT1000_REG_MAG_WATERMARK);
 661
 662        s_file = (u16 *) (pFileStart + file_hdr->loader_offset);
 663        c_file = (u8 *) (pFileStart + file_hdr->loader_offset);
 664
 665        boot_end = (u8 *) (pFileStart + file_hdr->loader_code_end);
 666
 667        loader_code_address = file_hdr->loader_code_address;
 668        loader_code_size = file_hdr->loader_code_size;
 669        correct_version = false;
 670
 671        while ((status == 0) && (state != STATE_DONE_FILE)) {
 672                switch (state) {
 673                case STATE_START_DWNLD:
 674                        status = scram_start_dwnld(ft1000dev, &handshake,
 675                                                   &state);
 676                        break;
 677
 678                case STATE_BOOT_DWNLD:
 679                        DEBUG("FT1000:STATE_BOOT_DWNLD\n");
 680                        ft1000dev->bootmode = 1;
 681                        handshake = get_handshake(ft1000dev, HANDSHAKE_REQUEST);
 682                        if (handshake == HANDSHAKE_REQUEST) {
 683                                /*
 684                                 * Get type associated with the request.
 685                                 */
 686                                request = get_request_type(ft1000dev);
 687                                switch (request) {
 688                                case REQUEST_RUN_ADDRESS:
 689                                        DEBUG("FT1000:REQUEST_RUN_ADDRESS\n");
 690                                        put_request_value(ft1000dev,
 691                                                          loader_code_address);
 692                                        break;
 693                                case REQUEST_CODE_LENGTH:
 694                                        DEBUG("FT1000:REQUEST_CODE_LENGTH\n");
 695                                        put_request_value(ft1000dev,
 696                                                          loader_code_size);
 697                                        break;
 698                                case REQUEST_DONE_BL:
 699                                        DEBUG("FT1000:REQUEST_DONE_BL\n");
 700                                        /* Reposition ptrs to beginning of code section */
 701                                        s_file = (u16 *) (boot_end);
 702                                        c_file = (u8 *) (boot_end);
 703                                        /* DEBUG("FT1000:download:s_file = 0x%8x\n", (int)s_file); */
 704                                        /* DEBUG("FT1000:download:c_file = 0x%8x\n", (int)c_file); */
 705                                        state = STATE_CODE_DWNLD;
 706                                        ft1000dev->fcodeldr = 1;
 707                                        break;
 708                                case REQUEST_CODE_SEGMENT:
 709                                        status = request_code_segment(ft1000dev,
 710                                                        &s_file, &c_file,
 711                                                        (const u8 *)boot_end,
 712                                                        true);
 713                                break;
 714                                default:
 715                                        DEBUG
 716                                            ("FT1000:download:Download error: Bad request type=%d in BOOT download state.\n",
 717                                             request);
 718                                        status = -1;
 719                                        break;
 720                                }
 721                                if (ft1000dev->usbboot)
 722                                        put_handshake_usb(ft1000dev,
 723                                                          HANDSHAKE_RESPONSE);
 724                                else
 725                                        put_handshake(ft1000dev,
 726                                                      HANDSHAKE_RESPONSE);
 727                        } else {
 728                                DEBUG
 729                                    ("FT1000:download:Download error: Handshake failed\n");
 730                                status = -1;
 731                        }
 732
 733                        break;
 734
 735                case STATE_CODE_DWNLD:
 736                        /* DEBUG("FT1000:STATE_CODE_DWNLD\n"); */
 737                        ft1000dev->bootmode = 0;
 738                        if (ft1000dev->usbboot)
 739                                handshake =
 740                                    get_handshake_usb(ft1000dev,
 741                                                      HANDSHAKE_REQUEST);
 742                        else
 743                                handshake =
 744                                    get_handshake(ft1000dev, HANDSHAKE_REQUEST);
 745                        if (handshake == HANDSHAKE_REQUEST) {
 746                                /*
 747                                 * Get type associated with the request.
 748                                 */
 749                                if (ft1000dev->usbboot)
 750                                        request =
 751                                            get_request_type_usb(ft1000dev);
 752                                else
 753                                        request = get_request_type(ft1000dev);
 754                                switch (request) {
 755                                case REQUEST_FILE_CHECKSUM:
 756                                        DEBUG
 757                                            ("FT1000:download:image_chksum = 0x%8x\n",
 758                                             image_chksum);
 759                                        put_request_value(ft1000dev,
 760                                                          image_chksum);
 761                                        break;
 762                                case REQUEST_RUN_ADDRESS:
 763                                        DEBUG
 764                                            ("FT1000:download:  REQUEST_RUN_ADDRESS\n");
 765                                        if (correct_version) {
 766                                                DEBUG
 767                                                    ("FT1000:download:run_address = 0x%8x\n",
 768                                                     (int)run_address);
 769                                                put_request_value(ft1000dev,
 770                                                                  run_address);
 771                                        } else {
 772                                                DEBUG
 773                                                    ("FT1000:download:Download error: Got Run address request before image offset request.\n");
 774                                                status = -1;
 775                                                break;
 776                                        }
 777                                        break;
 778                                case REQUEST_CODE_LENGTH:
 779                                        DEBUG
 780                                            ("FT1000:download:REQUEST_CODE_LENGTH\n");
 781                                        if (correct_version) {
 782                                                DEBUG
 783                                                    ("FT1000:download:run_size = 0x%8x\n",
 784                                                     (int)run_size);
 785                                                put_request_value(ft1000dev,
 786                                                                  run_size);
 787                                        } else {
 788                                                DEBUG
 789                                                    ("FT1000:download:Download error: Got Size request before image offset request.\n");
 790                                                status = -1;
 791                                                break;
 792                                        }
 793                                        break;
 794                                case REQUEST_DONE_CL:
 795                                        ft1000dev->usbboot = 3;
 796                                        /* Reposition ptrs to beginning of provisioning section */
 797                                        s_file =
 798                                            (u16 *) (pFileStart +
 799                                                     file_hdr->commands_offset);
 800                                        c_file =
 801                                            (u8 *) (pFileStart +
 802                                                    file_hdr->commands_offset);
 803                                        state = STATE_DONE_DWNLD;
 804                                        break;
 805                                case REQUEST_CODE_SEGMENT:
 806                                        /* DEBUG("FT1000:download: REQUEST_CODE_SEGMENT - CODELOADER\n"); */
 807                                        if (!correct_version) {
 808                                                DEBUG
 809                                                    ("FT1000:download:Download error: Got Code Segment request before image offset request.\n");
 810                                                status = -1;
 811                                                break;
 812                                        }
 813
 814                                        status = request_code_segment(ft1000dev,
 815                                                        &s_file, &c_file,
 816                                                        (const u8 *)code_end,
 817                                                        false);
 818
 819                                        break;
 820
 821                                case REQUEST_MAILBOX_DATA:
 822                                        DEBUG
 823                                            ("FT1000:download: REQUEST_MAILBOX_DATA\n");
 824                                        /* Convert length from byte count to word count. Make sure we round up. */
 825                                        word_length =
 826                                            (long)(pft1000info->DSPInfoBlklen +
 827                                                   1) / 2;
 828                                        put_request_value(ft1000dev,
 829                                                          word_length);
 830                                        mailbox_data =
 831                                            (struct drv_msg *)&(pft1000info->
 832                                                                DSPInfoBlk[0]);
 833                                        /*
 834                                         * Position ASIC DPRAM auto-increment pointer.
 835                                         */
 836
 837                                        data = (u16 *) &mailbox_data->data[0];
 838                                        dpram = (u16) DWNLD_MAG1_PS_HDR_LOC;
 839                                        if (word_length & 0x1)
 840                                                word_length++;
 841
 842                                        word_length = (word_length / 2);
 843
 844                                        for (; word_length > 0; word_length--) {        /* In words */
 845
 846                                                templong = *data++;
 847                                                templong |= (*data++ << 16);
 848                                                status =
 849                                                    fix_ft1000_write_dpram32
 850                                                    (ft1000dev, dpram++,
 851                                                     (u8 *) &templong);
 852
 853                                        }
 854                                        break;
 855
 856                                case REQUEST_VERSION_INFO:
 857                                        DEBUG
 858                                            ("FT1000:download:REQUEST_VERSION_INFO\n");
 859                                        word_length =
 860                                            file_hdr->version_data_size;
 861                                        put_request_value(ft1000dev,
 862                                                          word_length);
 863                                        /*
 864                                         * Position ASIC DPRAM auto-increment pointer.
 865                                         */
 866
 867                                        s_file =
 868                                            (u16 *) (pFileStart +
 869                                                     file_hdr->
 870                                                     version_data_offset);
 871
 872                                        dpram = (u16) DWNLD_MAG1_PS_HDR_LOC;
 873                                        if (word_length & 0x1)
 874                                                word_length++;
 875
 876                                        word_length = (word_length / 2);
 877
 878                                        for (; word_length > 0; word_length--) {        /* In words */
 879
 880                                                templong = ntohs(*s_file++);
 881                                                temp = ntohs(*s_file++);
 882                                                templong |= (temp << 16);
 883                                                status =
 884                                                    fix_ft1000_write_dpram32
 885                                                    (ft1000dev, dpram++,
 886                                                     (u8 *) &templong);
 887
 888                                        }
 889                                        break;
 890
 891                                case REQUEST_CODE_BY_VERSION:
 892                                        DEBUG
 893                                            ("FT1000:download:REQUEST_CODE_BY_VERSION\n");
 894                                        correct_version = false;
 895                                        requested_version =
 896                                            get_request_value(ft1000dev);
 897
 898                                        dsp_img_info =
 899                                            (struct dsp_image_info *)(pFileStart
 900                                                                      +
 901                                                                      sizeof
 902                                                                      (struct
 903                                                                       dsp_file_hdr));
 904
 905                                        for (image = 0;
 906                                             image < file_hdr->nDspImages;
 907                                             image++) {
 908
 909                                                if (dsp_img_info->version ==
 910                                                    requested_version) {
 911                                                        correct_version = true;
 912                                                        DEBUG
 913                                                            ("FT1000:download: correct_version is TRUE\n");
 914                                                        s_file =
 915                                                            (u16 *) (pFileStart
 916                                                                     +
 917                                                                     dsp_img_info->
 918                                                                     begin_offset);
 919                                                        c_file =
 920                                                            (u8 *) (pFileStart +
 921                                                                    dsp_img_info->
 922                                                                    begin_offset);
 923                                                        code_end =
 924                                                            (u8 *) (pFileStart +
 925                                                                    dsp_img_info->
 926                                                                    end_offset);
 927                                                        run_address =
 928                                                            dsp_img_info->
 929                                                            run_address;
 930                                                        run_size =
 931                                                            dsp_img_info->
 932                                                            image_size;
 933                                                        image_chksum =
 934                                                            (u32) dsp_img_info->
 935                                                            checksum;
 936                                                        break;
 937                                                }
 938                                                dsp_img_info++;
 939
 940                                        }       /* end of for */
 941
 942                                        if (!correct_version) {
 943                                                /*
 944                                                 * Error, beyond boot code range.
 945                                                 */
 946                                                DEBUG
 947                                                    ("FT1000:download:Download error: Bad Version Request = 0x%x.\n",
 948                                                     (int)requested_version);
 949                                                status = -1;
 950                                                break;
 951                                        }
 952                                        break;
 953
 954                                default:
 955                                        DEBUG
 956                                            ("FT1000:download:Download error: Bad request type=%d in CODE download state.\n",
 957                                             request);
 958                                        status = -1;
 959                                        break;
 960                                }
 961                                if (ft1000dev->usbboot)
 962                                        put_handshake_usb(ft1000dev,
 963                                                          HANDSHAKE_RESPONSE);
 964                                else
 965                                        put_handshake(ft1000dev,
 966                                                      HANDSHAKE_RESPONSE);
 967                        } else {
 968                                DEBUG
 969                                    ("FT1000:download:Download error: Handshake failed\n");
 970                                status = -1;
 971                        }
 972
 973                        break;
 974
 975                case STATE_DONE_DWNLD:
 976                        DEBUG("FT1000:download:Code loader is done...\n");
 977                        state = STATE_SECTION_PROV;
 978                        break;
 979
 980                case STATE_SECTION_PROV:
 981                        DEBUG("FT1000:download:STATE_SECTION_PROV\n");
 982                        pseudo_header = (struct pseudo_hdr *)c_file;
 983
 984                        if (pseudo_header->checksum ==
 985                            hdr_checksum(pseudo_header)) {
 986                                if (pseudo_header->portdest !=
 987                                    0x80 /* Dsp OAM */) {
 988                                        state = STATE_DONE_PROV;
 989                                        break;
 990                                }
 991                                pseudo_header_len = ntohs(pseudo_header->length);       /* Byte length for PROV records */
 992
 993                                /* Get buffer for provisioning data */
 994                                pbuffer =
 995                                    kmalloc((pseudo_header_len +
 996                                             sizeof(struct pseudo_hdr)),
 997                                            GFP_ATOMIC);
 998                                if (pbuffer) {
 999                                        memcpy(pbuffer, (void *)c_file,
1000                                               (u32) (pseudo_header_len +
1001                                                      sizeof(struct
1002                                                             pseudo_hdr)));
1003                                        /* link provisioning data */
1004                                        pprov_record =
1005                                            kmalloc(sizeof(struct prov_record),
1006                                                    GFP_ATOMIC);
1007                                        if (pprov_record) {
1008                                                pprov_record->pprov_data =
1009                                                    pbuffer;
1010                                                list_add_tail(&pprov_record->
1011                                                              list,
1012                                                              &pft1000info->
1013                                                              prov_list);
1014                                                /* Move to next entry if available */
1015                                                c_file =
1016                                                    (u8 *) ((unsigned long)
1017                                                            c_file +
1018                                                            (u32) ((pseudo_header_len + 1) & 0xFFFFFFFE) + sizeof(struct pseudo_hdr));
1019                                                if ((unsigned long)(c_file) -
1020                                                    (unsigned long)(pFileStart)
1021                                                    >=
1022                                                    (unsigned long)FileLength) {
1023                                                        state = STATE_DONE_FILE;
1024                                                }
1025                                        } else {
1026                                                kfree(pbuffer);
1027                                                status = -1;
1028                                        }
1029                                } else {
1030                                        status = -1;
1031                                }
1032                        } else {
1033                                /* Checksum did not compute */
1034                                status = -1;
1035                        }
1036                        DEBUG
1037                            ("ft1000:download: after STATE_SECTION_PROV, state = %d, status= %d\n",
1038                             state, status);
1039                        break;
1040
1041                case STATE_DONE_PROV:
1042                        DEBUG("FT1000:download:STATE_DONE_PROV\n");
1043                        state = STATE_DONE_FILE;
1044                        break;
1045
1046                default:
1047                        status = -1;
1048                        break;
1049                }               /* End Switch */
1050
1051                if (status != 0)
1052                        break;
1053
1054/****
1055      // Check if Card is present
1056      status = Harley_Read_Register(&temp, FT1000_REG_SUP_IMASK);
1057      if ( (status != NDIS_STATUS_SUCCESS) || (temp == 0x0000) ) {
1058        break;
1059      }
1060
1061      status = Harley_Read_Register(&temp, FT1000_REG_ASIC_ID);
1062      if ( (status != NDIS_STATUS_SUCCESS) || (temp == 0xffff) ) {
1063        break;
1064      }
1065****/
1066
1067        }                       /* End while */
1068
1069        DEBUG("Download exiting with status = 0x%8x\n", status);
1070        ft1000_write_register(ft1000dev, FT1000_DB_DNLD_TX,
1071                              FT1000_REG_DOORBELL);
1072
1073        return status;
1074}
1075