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

📄 pflash_cfi01.c.svn-base

📁 我们自己开发的一个OSEK操作系统!不知道可不可以?
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
/* *  CFI parallel flash with Intel command set emulation * *  Copyright (c) 2006 Thorsten Zitterell *  Copyright (c) 2005 Jocelyn Mayer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *//* * For now, this code can emulate flashes of 1, 2 or 4 bytes width. * Supported commands/modes are: * - flash read * - flash write * - flash ID read * - sector erase * - CFI queries * * It does not support timings * It does not support flash interleaving * It does not implement software data protection as found in many real chips * It does not implement erase suspend/resume commands * It does not implement multiple sectors erase * * It does not implement much more ... */#include "hw.h"#include "flash.h"#include "block.h"#include "qemu-timer.h"#define PFLASH_BUG(fmt, args...) \do { \    printf("PFLASH: Possible BUG - " fmt, ##args); \    exit(1); \} while(0)/* #define PFLASH_DEBUG */#ifdef PFLASH_DEBUG#define DPRINTF(fmt, args...)                      \do {                                               \        printf("PFLASH: " fmt , ##args);           \} while (0)#else#define DPRINTF(fmt, args...) do { } while (0)#endifstruct pflash_t {    BlockDriverState *bs;    target_ulong base;    target_ulong sector_len;    target_ulong total_len;    int width;    int wcycle; /* if 0, the flash is read normally */    int bypass;    int ro;    uint8_t cmd;    uint8_t status;    uint16_t ident[4];    uint8_t cfi_len;    uint8_t cfi_table[0x52];    target_ulong counter;    QEMUTimer *timer;    ram_addr_t off;    int fl_mem;    void *storage;};static void pflash_timer (void *opaque){    pflash_t *pfl = opaque;    DPRINTF("%s: command %02x done\n", __func__, pfl->cmd);    /* Reset flash */    pfl->status ^= 0x80;    if (pfl->bypass) {        pfl->wcycle = 2;    } else {        cpu_register_physical_memory(pfl->base, pfl->total_len,                        pfl->off | IO_MEM_ROMD | pfl->fl_mem);        pfl->wcycle = 0;    }    pfl->cmd = 0;}static uint32_t pflash_read (pflash_t *pfl, target_ulong offset, int width){    target_ulong boff;    uint32_t ret;    uint8_t *p;    ret = -1;    offset -= pfl->base;    boff = offset & 0xFF; /* why this here ?? */    if (pfl->width == 2)        boff = boff >> 1;    else if (pfl->width == 4)        boff = boff >> 2;    DPRINTF("%s: reading offset " TARGET_FMT_lx " under cmd %02x\n",            __func__, boff, pfl->cmd);    switch (pfl->cmd) {    case 0x00:        /* Flash area read */        p = pfl->storage;        switch (width) {        case 1:            ret = p[offset];            DPRINTF("%s: data offset " TARGET_FMT_lx " %02x\n",                    __func__, offset, ret);            break;        case 2:#if defined(TARGET_WORDS_BIGENDIAN)            ret = p[offset] << 8;            ret |= p[offset + 1];#else            ret = p[offset];            ret |= p[offset + 1] << 8;#endif            DPRINTF("%s: data offset " TARGET_FMT_lx " %04x\n",                    __func__, offset, ret);            break;        case 4:#if defined(TARGET_WORDS_BIGENDIAN)            ret = p[offset] << 24;            ret |= p[offset + 1] << 16;            ret |= p[offset + 2] << 8;            ret |= p[offset + 3];#else            ret = p[offset];            ret |= p[offset + 1] << 8;            ret |= p[offset + 1] << 8;            ret |= p[offset + 2] << 16;            ret |= p[offset + 3] << 24;#endif            DPRINTF("%s: data offset " TARGET_FMT_lx " %08x\n",                    __func__, offset, ret);            break;        default:            DPRINTF("BUG in %s\n", __func__);        }        break;    case 0x20: /* Block erase */    case 0x50: /* Clear status register */    case 0x60: /* Block /un)lock */    case 0x70: /* Status Register */    case 0xe8: /* Write block */        /* Status register read */        ret = pfl->status;        DPRINTF("%s: status %x\n", __func__, ret);        break;    case 0x98: /* Query mode */        if (boff > pfl->cfi_len)            ret = 0;        else            ret = pfl->cfi_table[boff];        break;    default:        /* This should never happen : reset state & treat it as a read */        DPRINTF("%s: unknown command state: %x\n", __func__, pfl->cmd);        pfl->wcycle = 0;        pfl->cmd = 0;    }    return ret;}/* update flash content on disk */static void pflash_update(pflash_t *pfl, int offset,                          int size){    int offset_end;    if (pfl->bs) {        offset_end = offset + size;        /* round to sectors */        offset = offset >> 9;        offset_end = (offset_end + 511) >> 9;        bdrv_write(pfl->bs, offset, pfl->storage + (offset << 9),                   offset_end - offset);    }}static void pflash_write (pflash_t *pfl, target_ulong offset, uint32_t value,                          int width){    target_ulong boff;    uint8_t *p;    uint8_t cmd;    /* WARNING: when the memory area is in ROMD mode, the offset is a       ram offset, not a physical address */    cmd = value;    if (pfl->wcycle == 0)        offset -= (target_ulong)(long)pfl->storage;    else        offset -= pfl->base;    DPRINTF("%s: offset " TARGET_FMT_lx " %08x %d wcycle 0x%x\n",            __func__, offset, value, width, pfl->wcycle);    /* Set the device in I/O access mode */    cpu_register_physical_memory(pfl->base, pfl->total_len, pfl->fl_mem);    boff = offset & (pfl->sector_len - 1);    if (pfl->width == 2)        boff = boff >> 1;    else if (pfl->width == 4)        boff = boff >> 2;    switch (pfl->wcycle) {    case 0:        /* read mode */        switch (cmd) {        case 0x00: /* ??? */            goto reset_flash;        case 0x20: /* Block erase */            p = pfl->storage;            offset &= ~(pfl->sector_len - 1);            DPRINTF("%s: block erase at " TARGET_FMT_lx " bytes "                    TARGET_FMT_lx "\n",                    __func__, offset, pfl->sector_len);            memset(p + offset, 0xff, pfl->sector_len);            pflash_update(pfl, offset, pfl->sector_len);            pfl->status |= 0x80; /* Ready! */            break;        case 0x50: /* Clear status bits */            DPRINTF("%s: Clear status bits\n", __func__);            pfl->status = 0x0;            goto reset_flash;        case 0x60: /* Block (un)lock */            DPRINTF("%s: Block unlock\n", __func__);            break;        case 0x70: /* Status Register */            DPRINTF("%s: Read status register\n", __func__);            pfl->cmd = cmd;            return;        case 0x98: /* CFI query */            DPRINTF("%s: CFI query\n", __func__);            break;        case 0xe8: /* Write to buffer */            DPRINTF("%s: Write to buffer\n", __func__);            pfl->status |= 0x80; /* Ready! */            break;        case 0xff: /* Read array mode */            DPRINTF("%s: Read array mode\n", __func__);            goto reset_flash;        default:            goto error_flash;        }        pfl->wcycle++;        pfl->cmd = cmd;        return;    case 1:        switch (pfl->cmd) {        case 0x20: /* Block erase */        case 0x28:            if (cmd == 0xd0) { /* confirm */                pfl->wcycle = 1;                pfl->status |= 0x80;            } if (cmd == 0xff) { /* read array mode */                goto reset_flash;            } else                goto error_flash;            break;        case 0xe8:            DPRINTF("%s: block write of %x bytes\n", __func__, cmd);            pfl->counter = cmd;            pfl->wcycle++;            break;        case 0x60:            if (cmd == 0xd0) {                pfl->wcycle = 0;                pfl->status |= 0x80;            } else if (cmd == 0x01) {                pfl->wcycle = 0;                pfl->status |= 0x80;            } else if (cmd == 0xff) {                goto reset_flash;            } else {                DPRINTF("%s: Unknown (un)locking command\n", __func__);                goto reset_flash;            }            break;        case 0x98:            if (cmd == 0xff) {                goto reset_flash;            } else {                DPRINTF("%s: leaving query mode\n", __func__);            }            break;        default:            goto error_flash;

⌨️ 快捷键说明

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