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

📄 drv.c

📁 是一个手机功能的模拟程序
💻 C
📖 第 1 页 / 共 3 页
字号:
            (uint32) ffsdrv_ram_intel_sb_init - (uint32) src;
        offset_of_erase =
            (uint32) ffsdrv_ram_intel_erase - (uint32) src;
        offset_of_write_halfword =
            (uint32) ffsdrv_ram_intel_sb_write_halfword - (uint32) src;
        
        break;
    default:
        ttw(ttr(TTrDrvOther, "}" NL));
        return 0;
    }

    // Make sure we are handling a half-word aligned address (Thumb mode
    // function pointers have lsb set!)
    src = (uint16 *) (~1 & (int) src);

    // If we detect that the linker allocated the driver to RUN in RAM, the
    // user has obviously NOT removed those linker lines and we bail out!
    if (offset_of_erase > FFSDRV_CODE_SIZE)
        return EFFS_DRIVER;

    dst = (uint16 *) &ffsdrv_code;

    // Code size in halfwords
    size = FFSDRV_CODE_SIZE / 2;

    // Rebind the two changed driver functions
    if (type == FFS_DRIVER_AMD_SB || type == FFS_DRIVER_INTEL_SB) {
        ffsdrv.erase =
            (void (*)(uint8))
            (offset_of_erase + (uint32) dst);
        ffsdrv.write_halfword =
            (void (*)(volatile uint16 *, uint16))
            (offset_of_write_halfword + (uint32) dst);
    }
    if (type == FFS_DRIVER_INTEL_SB) {
        ffsdrv.init =
            (int (*)(void))
            (offset_of_init + (uint32) dst);
    }

    ttw(ttr(TTrDrvOther, "ffsdrv_code, init, write, erase = 0x%07x, 0x%07x, 0x%07x, 0x%07x" NL,
            dst, (uint32) ffsdrv.init,
            (uint32) ffsdrv.write_halfword, (uint32) ffsdrv.erase));

    ttw(ttr(TTrDrvOther, "amd_begin,   init, write, erase = 0x%07x, 0x%07x, 0x%07x, 0x%07x" NL,
            ffsdrv_ram_amd_begin, ffsdrv_null_init,
            ffsdrv_ram_amd_sb_write_halfword, ffsdrv_ram_amd_sb_erase));

    ttw(ttr(TTrDrvOther, "intel_begin, init, write, erase = 0x%07x, 0x%07x, 0x%07x, 0x%07x" NL,
            ffsdrv_ram_intel_begin, ffsdrv_ram_intel_sb_init,
            ffsdrv_ram_intel_sb_write_halfword, ffsdrv_ram_intel_sb_erase));
    
    // Copy the code to RAM
    while (size--)
        *dst++ = *src++;

    ttw(ttr(TTrDrvOther, "}" NL));

    return 0;
}

#else // (TARGET == 0)

void ffsdrv_device_id_read(uint16 *manufact, uint16 *device) {}
int  ffsdrv_driver_copy_to_ram(int type) { return 0; }

#endif // (TARGET == 1)


#if (BOARD == 34)
/******************************************************************************
 * RAM Family Functions
 ******************************************************************************/

void ffsdrv_ram_write_halfword(volatile uint16 *dst, uint16 value)
{
  *dst = value;
}

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

  if (size == 0)
  return;
  else if (size == 1)
  ffsdrv_write_byte(mydst, *mysrc);
  else {
  if ((int) mydst & 1) {
      ffsdrv_write_byte(mydst++, *mysrc++);
      size--;
  }
  while (size >= 2) {
      ffsdrv_ram_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_ram_erase(uint8 block) 
{
  int i;
  char *addr;

  addr = block2addr(block);


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

void ffsdrv_void_write_end(void)
{
}

void ffsdrv_void_erase_suspend(void)
{
}

void ffsdrv_void_erase_resume(void)
{
}

#endif // BOARD = 34

/******************************************************************************
 * Initialization
 ******************************************************************************/

const struct ffsdrv_s ffsdrv_amd = {
    ffsdrv_null_init,
    ffsdrv_amd_erase,
    ffsdrv_amd_write_halfword,
    ffsdrv_amd_write,
    ffsdrv_amd_write_end,
    ffsdrv_amd_erase_suspend,
    ffsdrv_amd_erase_resume
};

const struct ffsdrv_s ffsdrv_amd_sb = {
    ffsdrv_null_init,
    ffsdrv_ram_amd_sb_erase,
    ffsdrv_ram_amd_sb_write_halfword,
    ffsdrv_generic_write,
    ffsdrv_null_write_end,
    ffsdrv_null_erase_suspend,
    ffsdrv_null_erase_resume
};

const struct ffsdrv_s ffsdrv_sst = {
    ffsdrv_null_init,
    ffsdrv_sst_erase,
    ffsdrv_amd_write_halfword, // Use AMD driver function
    ffsdrv_sst_write,
    ffsdrv_amd_write_end,      // Use AMD driver function
    ffsdrv_sst_erase_suspend,
    ffsdrv_null_erase_resume
};

const struct ffsdrv_s ffsdrv_sst_sb = {
    ffsdrv_null_init,
    ffsdrv_null_erase,
    ffsdrv_null_write_halfword,
    ffsdrv_null_write,
    ffsdrv_null_write_end,
    ffsdrv_null_erase_suspend,
    ffsdrv_null_erase_resume
};

// We use the functions ffsdrv_ram_intel_sb_write_halfword and
// ffsdrv_ram_intel_erase due to the bug in the intel wireless flash
// device. See 28F640W30.pdf specification Errata 5.
const struct ffsdrv_s ffsdrv_intel = {
    ffsdrv_null_init,
	ffsdrv_intel_erase,
    ffsdrv_intel_write_halfword,
    ffsdrv_generic_write,
    ffsdrv_intel_write_end,
    ffsdrv_intel_erase_suspend,
    ffsdrv_intel_erase_resume
};

const struct ffsdrv_s ffsdrv_intel_sb = {
    ffsdrv_null_init,
    ffsdrv_ram_intel_sb_erase,
    ffsdrv_ram_intel_sb_write_halfword,
    ffsdrv_generic_write,
    ffsdrv_null_write_end,
    ffsdrv_null_erase_suspend,
    ffsdrv_null_erase_resume
};

const struct ffsdrv_s ffsdrv_null = {
    ffsdrv_null_init,
    ffsdrv_null_erase,
    ffsdrv_null_write_halfword,
    ffsdrv_null_write,
    ffsdrv_null_write_end,
    ffsdrv_null_erase_suspend,
    ffsdrv_null_erase_resume
};

const struct ffsdrv_s ffsdrv_amd_pseudo_sb = {
    ffsdrv_null_init,
    ffsdrv_amd_pseudo_sb_erase,
    ffsdrv_amd_pseudo_sb_write_halfword,
    ffsdrv_generic_write,
    ffsdrv_null_write_end,
    ffsdrv_null_erase_suspend,
    ffsdrv_null_erase_resume
};

#if (TARGET == 0)
const struct ffsdrv_s ffsdrv_test = {
    ffsdrv_null_init,
    ffsdrv_test_erase,
    ffsdrv_test_write_halfword,
    ffsdrv_test_write,
    ffsdrv_null_write_end,
    ffsdrv_null_erase_suspend,
    ffsdrv_null_erase_resume
};
#endif

#if (BOARD == 34)
const struct ffsdrv_s ffsdrv_test = {
    ffsdrv_null_init,
    ffsdrv_ram_erase,
    ffsdrv_ram_write_halfword,
    ffsdrv_ram_write,
    ffsdrv_void_write_end,
    ffsdrv_void_erase_suspend,
    ffsdrv_void_erase_resume
};
#endif

// Note: This function is designed for little-endian memory addressing!
void ffsdrv_write_byte(void *dst, uint8 value)
{
    uint16 halfword;

    tw(tr(TR_FUNC, TrDrvWrite, "ffsdrv_write_byte(0x%05x, 0x%x)\n",
       (int) (addr2offset(dst)), value));
    ttw(str(TTrDrvWrite, "wb" NL));

    if ((int) dst & 1)
        halfword =                (value << 8) | *((uint8 *) dst - 1);
    else
        halfword = (*((uint8 *) dst + 1) << 8) | (value);

    ffsdrv.write_halfword((uint16 *) ((int) dst & ~1), halfword);
}


extern uint16 ffs_flash_manufact;
extern uint16 ffs_flash_device;

effs_t ffsdrv_init(void)
{
    const struct ffsdrv_s *p;
    const struct flash_info_s *flash = &flash_info[0];
    int error;

#if (BOARD == 34)

    // Initialize dummy flash with default values
    dev.state     = DEV_READ;
    dev.binfo     = (struct block_info_s *) flash->binfo;
    dev.base      = (char *) flash->base;
    dev.manufact  = flash->manufact;
    dev.device    = flash->device;
    dev.numblocks = flash->numblocks;
    dev.atomlog2 = FFS_ATOM_LOG2;
    dev.atomsize = 1 << dev.atomlog2;
    dev.atomnotmask = dev.atomsize - 1;
    dev.driver      = flash->driver;

    // We assume that ALL blocks are of equal size
    dev.blocksize_ld = dev.binfo[0].size_ld;
    dev.blocksize    = (1 << dev.blocksize_ld);

    // Supply structure pointer for ffs write/read functions
    p = &ffsdrv_test;

    // Bind the driver functions
    ffsdrv.init           = p->init;
    ffsdrv.erase          = p->erase;
    ffsdrv.write_halfword = p->write_halfword;
    ffsdrv.write          = p->write;
    ffsdrv.write_end      = p->write_end;
    ffsdrv.erase_suspend  = p->erase_suspend;
    ffsdrv.erase_resume   = p->erase_resume;
     
    return EFFS_OK;
    
#else

    tw(tr(TR_BEGIN, TrDrvInit, "drv_init() {\n"));
    ttw(str(TTrDrvOther, "ffsdrv_init() {" NL));

    dev.state = DEV_READ;
    dev.binfo = 0;
    dev.base = 0;
    dev.numblocks = 0;

    // If ffs_flash_device is zero, detect device automatically by copying
    // the detect function into RAM and execute it from there...
    if (ffs_flash_manufact == 0 && ffs_flash_device == 0)
    {
#if (TARGET == 1)
        char detect_code[80];
        typedef (*pf_t)(uint16 *, uint16 *);
        pf_t myfp;

        ffsdrv_device_id_read_copy_to_ram((uint16 *) detect_code, 
                                          sizeof(detect_code));
        // Combine bit 0 of the thumb mode function pointer with the address
        // of the code in RAM. Then call the detect function in RAM.
        myfp = (pf_t) (((int) &ffsdrv_device_id_read & 1) | (int) detect_code);
        (*myfp)(&dev.manufact, &dev.device);
        // This code does not work but it is unknown as to why not.
        // ((pf_t)detect_code)(&dev.manufact, &dev.device);
#endif
    }
    else {
        dev.manufact = ffs_flash_manufact;
        dev.device   = ffs_flash_device;
    }

    tw(tr(TR_FUNC, TrDrvInit, "TARGET = %d\n", TARGET));
    tw(tr(TR_FUNC, TrDrvInit, "Looking up device (0x%2x,0x%4x): ",
          dev.manufact, dev.device));
    while (flash->manufact) {
        tw(tr(TR_NULL, TrDrvInit, "(0x%02x,0x%04x) ",
              flash->manufact, flash->device));
        if (dev.manufact == flash->manufact && dev.device == flash->device) {
            tw(tr(TR_NULL, TrDrvInit, "FOUND "));
            break;
        }
        flash++;
    }
    tw(tr(TR_NULL, TrDrvInit, "\n"));

    if (flash->manufact == 0) {
        tw(tr(TR_END, TrDrvInit, "} (%d)\n", EFFS_NODEVICE));
        return EFFS_NODEVICE;
    }

    dev.binfo     = (struct block_info_s *) flash->binfo;
    dev.base      = (char *) flash->base;
    dev.numblocks = flash->numblocks;
    dev.driver    = flash->driver;

    // We assume that ALL blocks are of equal size
    dev.blocksize_ld = dev.binfo[0].size_ld;
    dev.blocksize    = (1 << dev.blocksize_ld);

    dev.atomlog2 = FFS_ATOM_LOG2;
    dev.atomsize = 1 << dev.atomlog2;
    dev.atomnotmask = dev.atomsize - 1;

#if (TARGET == 0)
    if (dev.manufact == MANUFACT_TEST)
        dev.base = ffsdrv_test_create();

    p = &ffsdrv_test;

#else // (TARGET == 1)

    // Initialize hardware independent driver functions array
    switch (dev.driver) {
    case FFS_DRIVER_AMD:           p = &ffsdrv_amd; break;
    case FFS_DRIVER_AMD_SB:        p = &ffsdrv_amd_sb; break;
    case FFS_DRIVER_SST:           p = &ffsdrv_sst; break;
    case FFS_DRIVER_SST_SB:        p = &ffsdrv_sst_sb; break;
    case FFS_DRIVER_INTEL:         p = &ffsdrv_intel; break;
    case FFS_DRIVER_INTEL_SB:      p = &ffsdrv_intel_sb; break;
    case FFS_DRIVER_AMD_PSEUDO_SB: p = &ffsdrv_amd_pseudo_sb; break;
    default:                       p = &ffsdrv_null; break;
    }

#endif // (TARGET == 0)

    // Bind the driver functions
    ffsdrv.init           = p->init;
    ffsdrv.erase          = p->erase;
    ffsdrv.write_halfword = p->write_halfword;
    ffsdrv.write          = p->write;
    ffsdrv.write_end      = p->write_end;
    ffsdrv.erase_suspend  = p->erase_suspend;
    ffsdrv.erase_resume   = p->erase_resume;

    // Copy single bank driver code to RAM (and possibly re-bind some of the
    // driver functions)
    error = ffsdrv_driver_copy_to_ram(dev.driver);

    // FIXME: ffsdrv_intel_sb_init() does NOT work. Target freezes!
    if (error >= 0)
        error = ffsdrv.init();

    tw(tr(TR_FUNC, TrDrvInit, "dev.binfo     = 0x%x\n", (unsigned int) dev.binfo));
    tw(tr(TR_FUNC, TrDrvInit, "dev.base      = 0x%x\n", (unsigned int) dev.base));
    tw(tr(TR_FUNC, TrDrvInit, "dev.numblocks = %d\n", dev.numblocks));
    tw(tr(TR_FUNC, TrDrvInit, "dev.blocksize = %d\n", dev.blocksize));
    tw(tr(TR_FUNC, TrDrvInit, "dev.atomlog2/atomsize/atomnotmask = %d/%d/%x\n",
          dev.atomlog2, dev.atomsize, dev.atomnotmask));
    tw(tr(TR_END, TrDrvInit, "} %d\n", error));
    ttw(ttr(TTrDrvOther, "} %d" NL, error));

    return error;
#endif // BOARD = 34
}


/******************************************************************************
 * Interrupt Enable/Disable
 ******************************************************************************/

// IMPORTANT NOTE! Apparently, locating this ARM assembly code at the top of
// this file will make the compiler trash the A1 register between the calls
// of arm_int_disable and arm_int_enable() thus crashing the whole system.
// If the code is placed AFTER the usage of the functions, the compiler
// saves the A1 register. Strange but true.

// IMPORTANT NOTE! Apparently, another strange thing is that if the
// functions are declared static, they don't work!

// Executing code from RAM is NOT trivial when we need to jump between ROM
// (flash) and RAM memory. The ARM only supports 26-bit relative branch
// offsets. This is the reason why we have a local copy of the
// arm_int_disable/enable() functions in this file plus each of the
// single-bank drivers.

#if (TARGET == 1)
// Note that we use our own interrupt disable/enable function because
// Nucleus allegedly should have a bug in its implementation for this.

uint32 int_disable(void)
{
    asm("        .state16");
    asm("        mov       A1, #0xC0");
    asm("        ldr       A2, tct_disable");
    asm("        bx        A2      ");

    asm("tct_disable    .field     _TCT_Control_Interrupts+0,32");
    asm("	            .global	   _TCT_Control_Interrupts");
}

void int_enable(uint32 cpsr)
{
    asm("        .state16");
    asm("        ldr       A2, tct_enable");
    asm("        bx        A2      ");

    asm("tct_enable 	.field     _TCT_Control_Interrupts+0,32");
    asm("	            .global	   _TCT_Control_Interrupts");
}

#else

uint32 int_disable(void) { return 0; }
void int_enable(uint32 tmp) {}

#endif // (TARGET == 1)


⌨️ 快捷键说明

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