⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 drv.c

📁 是一个手机功能的模拟程序
💻 C
📖 第 1 页 / 共 3 页
字号:
void ffsdrv_ram_intel_erase(uint8 block);

#else // (TARGET == 0)

// On PC these functions are empty
void ffsdrv_ram_intel_sb_write_halfword(volatile uint16 *addr, uint16 value) {}
void ffsdrv_ram_intel_sb_erase(uint8 block) {}
void ffsdrv_ram_intel_erase(uint8 block) {}

#endif // (TARGET == 1)


/******************************************************************************
 * Intel Dual/Multi Bank Driver Functions
 ******************************************************************************/

void ffsdrv_intel_write_end(void);
void ffsdrv_intel_erase_end(void);


// ffsdrv_intel_write_halfword and ffsdrv_intel_write_end is not used
// because of the bug in the intel flash device. Instead is the functions
// ffsdrv_ram_intel_sb_write_halfword and ffsdrv_ram_intel_erase used.
void ffsdrv_intel_write_halfword(volatile uint16 *addr, uint16 value)
{
    uint32 cpsr;

    tlw(led_on(LED_WRITE));
    ttw(ttr(TTrDrvWrite, "wh(%x,%x)" NL, addr, value));

    dev.addr = addr;

    if (~*addr & value) {
        ttw(ttr(TTrFatal, "wh(%x,%x->%x) fatal" NL, addr, *addr, value));
        return;
    }

    cpsr = int_disable();
    dev.state = DEV_WRITE;

#if 1
    *addr = 0x60; // Intel Config setup
    *addr = 0xD0; // Intel Unlock block
    *addr = 0x50; // Intel Clear Status Register
#endif

    *addr = 0x40; // Intel program byte/word
    *addr = value;

    int_enable(cpsr);

    ffsdrv_intel_write_end();
}

void ffsdrv_intel_write(void *dst, const void *src, uint16 size)
{
    uint8 *mydst = dst;
    const uint8 *mysrc = src;

    if (size > 0)
    {
        if ((unsigned int) mydst & 1) {
            ffsdrv_write_byte(mydst++, *mysrc++);
            size--;
        }
        while (size >= 2) {
            ffsdrv_intel_write_halfword((uint16 *) mydst,
                                        mysrc[0] | (mysrc[1] << 8));
            size -= 2;
            mysrc += 2;
            mydst += 2;
        }
        if (size == 1)
            ffsdrv_write_byte(mydst++, *mysrc++);
    }
}

void ffsdrv_intel_write_end(void)
{
	// We can be interrupted and reentered thus the state can have been changed.
    while ((*dev.addr & 0x80) == 0 && dev.state == DEV_WRITE)
        ;

    *dev.addr = 0xFF; // Intel read array

    dev.state = DEV_READ;
    tlw(led_off(LED_WRITE));
}


void ffsdrv_intel_erase(uint8 block) 
{
    uint32 cpsr;

    ttw(ttr(TTrDrvErase, "e(%d)" NL, block));
    tlw(led_on(LED_ERASE));

    dev.addr = (uint16 *) block2addr(block);

    cpsr = int_disable();
    dev.state = DEV_ERASE;

#if 1
    *dev.addr = 0x60; // Intel Config setup
    *dev.addr = 0xD0; // Intel Unlock block
#endif

    *dev.addr = 0x50; // Intel clear status register (not really necessary)
    *dev.addr = 0x20; // Intel erase setup
    *dev.addr = 0xD0; // Intel erase confirm

    int_enable(cpsr);

    ffsdrv_intel_erase_end();
}

void ffsdrv_intel_erase_end(void)
{
    while ((*dev.addr & 0x80) == 0)
        ;

    *dev.addr = 0xFF; // Intel read array

    dev.state = DEV_READ;
    tlw(led_off(LED_ERASE));
}

void ffsdrv_intel_erase_suspend(void)
{
    uint32 cpsr;
    uint16 poll;

    ttw(str(TTrDrvErase, "es" NL));
    tlw(led_on(LED_ERASE_SUSPEND));

    cpsr = int_disable();
    dev.state = DEV_ERASE_SUSPEND;
    *dev.addr = 0xB0; // Intel Erase Suspend
    *dev.addr = 0x70; // Intel Read Status Register
    while (((poll = *dev.addr) & 0x80) == 0)
        ;

    if ((poll & 0x40) == 0) {
        // Block erase has completed
        tlw(led_off(LED_ERASE_SUSPEND));
        dev.state = DEV_READ;
        tlw(led_off(LED_ERASE));
    }
    *dev.addr = 0xFF; // Intel read array
    int_enable(cpsr);
}

void ffsdrv_intel_erase_resume(void)
{
    uint32 cpsr;

    ttw(str(TTrDrvErase, "er" NL));

    cpsr = int_disable();
    dev.state = DEV_ERASE;
    *dev.addr = 0xD0; // Intel erase resume

// The following "extra" Read Status command is required because Intel has
// changed the specification of the W30 flash! (See "1.8 Volt Intel?// Wireless Flash Memory with 3 Volt I/O 28F6408W30, 28F640W30, 28F320W30
// Specification Update")
	*dev.addr = 0x70; // Intel Read Status Register

    int_enable(cpsr);

    tlw(led_off(LED_ERASE_SUSPEND));
}


/******************************************************************************
 * Void Functions
 ******************************************************************************/

int ffsdrv_null_init(void)
{
    ttw(ttr(TTrDrvOther, "ffsdrv_null_init()" NL));

    return 0;
}

void ffsdrv_null_erase(uint8 block)
{
    ttw(ttr(TTrDrvErase, "ffsdrv_null_erase(%d)" NL, block));
}

void ffsdrv_null_write_halfword(volatile uint16 *addr, uint16 value)
{
    ttw(ttr(TTrDrvWrite, "ffsdrv_null_write_halfword(0x%x, 0x%x)" NL, addr, value));
}

void ffsdrv_null_write(void *dst, const void *src, uint16 size)
{
    ttw(ttr(TTrDrvWrite, "ffsdrv_null_write(0x%x, 0x%x, %d)" NL, dst, src, size));
}

void ffsdrv_null_erase_suspend(void)
{
    ttw(str(TTrDrvErase, "ffsdrv_null_erase_suspend()" NL));
}

void ffsdrv_null_erase_resume(void)
{
    ttw(str(TTrDrvErase, "ffsdrv_null_erase_resume()" NL));
}

void ffsdrv_null_write_end(void)
{
    ttw(str(TTrDrvWrite, "ffsdrv_null_write_end()" NL));
}

void ffsdrv_null_erase_end(void)
{
    ttw(str(TTrDrvErase, "ffsdrv_null_erase_end()" NL));
}


/******************************************************************************
 * Test Driver Functions
 ******************************************************************************/

#if (TARGET == 0)

static char *image_addr = 0;
static int image_size = 0;
static int image_fd = 0;

extern int   arg_removeimage;
extern char *arg_imagename;

extern void test_fatal_printf(char *format, ...);

void ffsdrv_write_check(char *addr, int size)
{
    offset_t offset, last;

    offset = addr2offset(addr);
    last = dev.binfo[dev.numblocks-1].offset
        + (1 << dev.binfo[dev.numblocks-1].size_ld);

    if (offset < 0 || (offset + size) > last) {
        fprintf(stderr, "ffsdrv_write_check() failed (addr = 0x%x, size = %d)\n",
                (int) addr, size);
        fprintf(stdout, "ffsdrv_write_check() failed (addr = 0x%x, size = %d)\n",
                (int) addr, size);
        exit (1);
    }
}


void ffsdrv_write_error(uint16 old, uint16 new)
{
    test_fatal_printf("FATAL: Attempt to rewrite 0 to 1 bit "
                      "(old:0x%x/%c new:0x%x/%c)\n",
                      old, (old < ' ' ? '?' : old),
                      new, (new < ' ' ? '?' : new));
}

void ffsdrv_test_write_halfword(volatile uint16 *addr, uint16 value)
{
    tw(tr(TR_FUNC, TrDrvWrite, "test_write_halfword(0x%05x, 0x%x)\n",
          addr2offset(addr), value));

    ffsdrv_write_check((uint8 *) addr, 2);

    if (~*addr & value)
        ffsdrv_write_error(*addr, value);

    *addr = value;
}

void ffsdrv_test_write(void *dst, const void *src, uint16 size)
{
    uint8 *mydst = dst;
    const uint8 *mysrc = src;

    tw(tr(TR_FUNC, TrDrvWrite, "test_write(0x%05x, 0x%x, %d)\n",
          addr2offset(mydst), mysrc, size));

    if (size > 0)
    {
        if ((int) mydst & 1) {
            ffsdrv_write_byte(mydst++, *mysrc++);
            size--;
        }
        while (size >= 2) {
            ffsdrv_test_write_halfword((uint16 *) mydst, mysrc[0]|(mysrc[1] << 8));
            size -= 2;
            mysrc += 2;
            mydst += 2;
        }
        if (size == 1)
            ffsdrv_write_byte(mydst++, *mysrc++);
    }
}

void ffsdrv_test_erase(uint8 block) 
{
    int i;
    uint8 *addr;

    addr = block2addr(block);

    tw(tr(TR_FUNC, TrDrvErase, "ffsdrv_test_erase(%d)\n", block));

    for (i = 0; i < 1 << dev.binfo[block].size_ld; i++) {
        *addr++ = 0xFF;
    }
}

char *ffsdrv_test_create(void)
{
    // If flash image file already exists, open the file, and mmap it.
    // Otherwise, create file, fill file with 1's, then mmap it.
    
    int i;
    struct stat statbuf;

    image_size = (int) dev.binfo[dev.numblocks - 1].offset +
        (1 << dev.binfo[dev.numblocks - 1].size_ld);

    tw(tr(TR_BEGIN, TrDrvInit, "ffsdrv_test_create() {\n"));
    tw(tr(TR_FUNC, TrDrvInit, "%s image: '%s', size = %d\n",
          arg_removeimage ? "new" : "current", arg_imagename, image_size));

    // create file if it does not exist
    if (arg_removeimage || lstat(arg_imagename, &statbuf) == -1)
    {
        char data[64];

        // only the first run should remove the flash image file
        arg_removeimage = 0;

        tw(tr(TR_FUNC, TrDrvInit, "creating new flash image file '%s'\n",
              arg_imagename));
        image_fd = open(arg_imagename , O_RDWR|O_CREAT,
                        (S_IRWXU & ~S_IXUSR) |
                        ( S_IRWXG & ~S_IXGRP) | (S_IRWXO & ~S_IXOTH));
        if (image_fd == -1) {
            perror("Failed to create flash image");
            exit(1);
        }
        
        // write 1's to the file.
        for (i = 0; i < 64; i++)
            data[i] = 0xff;
        
        for (i = 0; i < image_size/64; i++) {
            write(image_fd, data, 64);
        }
        close(image_fd);
        image_fd = 0;
        tw(tr(TR_FUNC, TrDrvInit, "flash image file created\n"));
    }

    // only open image file if this is the first initialization.
    if (image_fd > 0) {
        tw(tr(TR_FUNC, TrDrvInit, "re-opening '%s' file of size %d\n",
              arg_imagename, image_size));
    }
    else {
        tw(tr(TR_FUNC, TrDrvInit, "opening '%s' file of size %d\n",
              arg_imagename, image_size));

        image_fd = open(arg_imagename, O_RDWR, S_IRWXU|S_IRWXG|S_IRWXO);
        if (image_fd == -1) {
            perror("Failed to open flash image");
            exit(1);
        }

        // memory map the file and update block addresses of binfo array
        image_addr = mmap(0, image_size, PROT_READ|PROT_WRITE,
                          MAP_FILE|MAP_SHARED, image_fd, 0);
    }

    tw(tr(TR_END, TrDrvInit, "}\n"));

    return image_addr;
}

#endif // (TARGET == 0)


/******************************************************************************
 * Device Detection and Copying of Driver to RAM
 ******************************************************************************/

#if (TARGET == 1)

// Note that this function reads device code of any of the three known flash
// families; Intel, AMD and SST. This works because Intel and AMD use
// the same command data for entering READ_IDENTIFIER mode (0x90).
// The function should be copied and executed from RAM!
void ffsdrv_device_id_read(uint16 *manufact, uint16 *device)
{
    int addr, i;

    // This silly looking code has one purpose; to set addr = 0xAAAA. It is
    // necessary in order to force the compiler NOT to produce code that
    // uses LDR opcode(s) with PC-relative addressing. The assember code
    // produced from this C code is completely relocatable!
    for (i = 0, addr = 0; i < 2; i++)
        addr |= addr << 8 | 0xAA;

    FLASH_WRITE_HALFWORD (addr,      0xAA);
    FLASH_WRITE_HALFWORD (addr >> 1, 0x55);
    FLASH_WRITE_HALFWORD (addr,      0x90); // Intel/AMD read id command

    *manufact = FLASH_READ_HALFWORD (0); // flash a0 = 0
    *device   = FLASH_READ_HALFWORD (2); // flash a0 = 1

    FLASH_WRITE_HALFWORD (0, 0xFF); // Intel read-array command

    // AMD devices do not need the two unlock cycles but SST devices do,
    // even though the SST datasheets states otherwise ;-)
    FLASH_WRITE_HALFWORD (addr,      0xAA);
    FLASH_WRITE_HALFWORD (addr >> 1, 0x55);
    FLASH_WRITE_HALFWORD (addr,      0xF0); // AMD read-array/reset command
}

// Copy ffsdrv_device_id_read() function code to RAM. The only known way to
// determine the size of the code is to look either in the linker-generated
// map file or in the assember output file.
void ffsdrv_device_id_read_copy_to_ram(uint16 *dst, int size)
{
    uint16 *src = (uint16 *) &ffsdrv_device_id_read;

    // The ARM7TDMI compiler sets bit 0 for thumb mode function pointers, so
    // we need to clear this in order to copy *all* bytes. Otherwise we
    // exclude first byte and the resulting copy becomes garbage
    src = (uint16 *) (~1 & (int) src);
    size /= 2;

    while (size--)
        *dst++ = *src++;
}

// Copy ffsdrv_xxx_sb_erase() and ffsdrv_xxx_sb_write_halfword() functions
// to RAM. The only known way to determine the size of the code is to look
// either in the linker-generated map file or in the assember output file.
int ffsdrv_driver_copy_to_ram(int type)
{
    int size;
    uint16 *src, *dst;
    extern uint16 ffsdrv_ram_amd_begin[];
    extern uint16 ffsdrv_ram_intel_begin[];
    uint32 offset_of_init;
    uint32 offset_of_erase;
    uint32 offset_of_write_halfword;
    
    ttw(ttr(TTrDrvOther, "ffsdrv_driver_copy_to_ram() {" NL));

    switch (type) {
    case FFS_DRIVER_AMD:
    case FFS_DRIVER_AMD_SB:
        src = ffsdrv_ram_amd_begin;
        offset_of_erase =
            (uint32) ffsdrv_ram_amd_sb_erase - (uint32) src;
        offset_of_write_halfword =
            (uint32) ffsdrv_ram_amd_sb_write_halfword - (uint32) src;
        break;
    case FFS_DRIVER_INTEL_SB:
        src = ffsdrv_ram_intel_begin;
        offset_of_init =
            (uint32) ffsdrv_ram_intel_sb_init - (uint32) src;
        offset_of_erase =
            (uint32) ffsdrv_ram_intel_sb_erase - (uint32) src;
        offset_of_write_halfword =
            (uint32) ffsdrv_ram_intel_sb_write_halfword - (uint32) src;
    case FFS_DRIVER_INTEL:
        src = ffsdrv_ram_intel_begin;
        offset_of_init =

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -