qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v4 02/10] block/pflash_cfi02: Refactor, NFC inte


From: Philippe Mathieu-Daudé
Subject: Re: [Qemu-devel] [PATCH v4 02/10] block/pflash_cfi02: Refactor, NFC intended
Date: Mon, 6 May 2019 09:34:27 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.6.1

On 4/26/19 6:26 PM, Stephen Checkoway wrote:
> Simplify and refactor for upcoming commits. In particular, pull out all
> of the code to modify the status into simple helper functions. Status
> handling becomes more complex once multiple chips are interleaved to
> produce a single device.
> 
> No change in functionality is intended with this commit.

As this patch is hard to digest, I splitted it in various atomic changes
in another series:
https://lists.gnu.org/archive/html/qemu-devel/2019-05/msg00975.html

> 
> Signed-off-by: Stephen Checkoway <address@hidden>
> ---
>  hw/block/pflash_cfi02.c | 221 +++++++++++++++++-----------------------
>  1 file changed, 95 insertions(+), 126 deletions(-)
> 
> diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c
> index f2c6201f81..4b7af71806 100644
> --- a/hw/block/pflash_cfi02.c
> +++ b/hw/block/pflash_cfi02.c
> @@ -46,18 +46,19 @@
>  #include "hw/sysbus.h"
>  #include "trace.h"
>  
> -//#define PFLASH_DEBUG
> -#ifdef PFLASH_DEBUG
> +#define PFLASH_DEBUG false
>  #define DPRINTF(fmt, ...)                                  \
>  do {                                                       \
> -    fprintf(stderr, "PFLASH: " fmt , ## __VA_ARGS__);       \
> +    if (PFLASH_DEBUG) {                                    \
> +        fprintf(stderr, "PFLASH: " fmt, ## __VA_ARGS__);   \
> +    }                                                      \
>  } while (0)
> -#else
> -#define DPRINTF(fmt, ...) do { } while (0)
> -#endif
>  
>  #define PFLASH_LAZY_ROMD_THRESHOLD 42
>  
> +/* Special write cycle for CFI queries. */
> +#define WCYCLE_CFI 7
> +
>  struct PFlashCFI02 {
>      /*< private >*/
>      SysBusDevice parent_obj;
> @@ -97,6 +98,31 @@ struct PFlashCFI02 {
>      void *storage;
>  };
>  
> +/*
> + * Toggle status bit DQ7.
> + */
> +static inline void toggle_dq7(PFlashCFI02 *pfl)
> +{
> +    pfl->status ^= 0x80;
> +}
> +
> +/*
> + * Set status bit DQ7 to bit 7 of value.
> + */
> +static inline void set_dq7(PFlashCFI02 *pfl, uint8_t value)
> +{
> +    pfl->status &= 0x7F;
> +    pfl->status |= value & 0x80;
> +}
> +
> +/*
> + * Toggle status bit DQ6.
> + */
> +static inline void toggle_dq6(PFlashCFI02 *pfl)
> +{
> +    pfl->status ^= 0x40;
> +}
> +
>  /*
>   * Set up replicated mappings of the same region.
>   */
> @@ -126,7 +152,7 @@ static void pflash_timer (void *opaque)
>  
>      trace_pflash_timer_expired(pfl->cmd);
>      /* Reset flash */
> -    pfl->status ^= 0x80;
> +    toggle_dq7(pfl);
>      if (pfl->bypass) {
>          pfl->wcycle = 2;
>      } else {
> @@ -136,12 +162,34 @@ static void pflash_timer (void *opaque)
>      pfl->cmd = 0;
>  }
>  
> -static uint32_t pflash_read(PFlashCFI02 *pfl, hwaddr offset,
> -                            int width, int be)
> +/*
> + * Read data from flash.
> + */
> +static uint64_t pflash_data_read(PFlashCFI02 *pfl, hwaddr offset,
> +                                 unsigned int width)
>  {
> +    uint8_t *p = (uint8_t *)pfl->storage + offset;
> +    uint64_t ret = pfl->be ? ldn_be_p(p, width) : ldn_le_p(p, width);
> +    /* XXX: Need a trace_pflash_data_read(offset, ret, width) */
> +    switch (width) {
> +    case 1:
> +        trace_pflash_data_read8(offset, ret);
> +        break;
> +    case 2:
> +        trace_pflash_data_read16(offset, ret);
> +        break;
> +    case 4:
> +        trace_pflash_data_read32(offset, ret);
> +        break;
> +    }
> +    return ret;
> +}
> +
> +static uint64_t pflash_read(void *opaque, hwaddr offset, unsigned int width)
> +{
> +    PFlashCFI02 *pfl = opaque;
>      hwaddr boff;
> -    uint32_t ret;
> -    uint8_t *p;
> +    uint64_t ret;
>  
>      ret = -1;
>      trace_pflash_read(offset, pfl->cmd, width, pfl->wcycle);
> @@ -166,39 +214,8 @@ static uint32_t pflash_read(PFlashCFI02 *pfl, hwaddr 
> offset,
>      case 0x80:
>          /* We accept reads during second unlock sequence... */
>      case 0x00:
> -    flash_read:
>          /* Flash area read */
> -        p = pfl->storage;
> -        switch (width) {
> -        case 1:
> -            ret = p[offset];
> -            trace_pflash_data_read8(offset, ret);
> -            break;
> -        case 2:
> -            if (be) {
> -                ret = p[offset] << 8;
> -                ret |= p[offset + 1];
> -            } else {
> -                ret = p[offset];
> -                ret |= p[offset + 1] << 8;
> -            }
> -            trace_pflash_data_read16(offset, ret);
> -            break;
> -        case 4:
> -            if (be) {
> -                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 + 2] << 16;
> -                ret |= p[offset + 3] << 24;
> -            }
> -            trace_pflash_data_read32(offset, ret);
> -            break;
> -        }
> +        ret = pflash_data_read(pfl, offset, width);
>          break;
>      case 0x90:
>          /* flash ID read */
> @@ -213,23 +230,23 @@ static uint32_t pflash_read(PFlashCFI02 *pfl, hwaddr 
> offset,
>          case 0x0E:
>          case 0x0F:
>              ret = boff & 0x01 ? pfl->ident3 : pfl->ident2;
> -            if (ret == (uint8_t)-1) {
> -                goto flash_read;
> +            if (ret != (uint8_t)-1) {
> +                break;
>              }
> -            break;
> +            /* Fall through to data read. */
>          default:
> -            goto flash_read;
> +            ret = pflash_data_read(pfl, offset, width);
>          }
> -        DPRINTF("%s: ID " TARGET_FMT_plx " %x\n", __func__, boff, ret);
> +        DPRINTF("%s: ID " TARGET_FMT_plx " %" PRIx64 "\n", __func__, boff, 
> ret);
>          break;
>      case 0xA0:
>      case 0x10:
>      case 0x30:
>          /* Status register read */
>          ret = pfl->status;
> -        DPRINTF("%s: status %x\n", __func__, ret);
> +        DPRINTF("%s: status %" PRIx64 "\n", __func__, ret);
>          /* Toggle bit 6 */
> -        pfl->status ^= 0x40;
> +        toggle_dq6(pfl);
>          break;
>      case 0x98:
>          /* CFI query mode */
> @@ -245,8 +262,7 @@ static uint32_t pflash_read(PFlashCFI02 *pfl, hwaddr 
> offset,
>  }
>  
>  /* update flash content on disk */
> -static void pflash_update(PFlashCFI02 *pfl, int offset,
> -                          int size)
> +static void pflash_update(PFlashCFI02 *pfl, int offset, int size)
>  {
>      int offset_end;
>      if (pfl->blk) {
> @@ -259,9 +275,10 @@ static void pflash_update(PFlashCFI02 *pfl, int offset,
>      }
>  }
>  
> -static void pflash_write(PFlashCFI02 *pfl, hwaddr offset,
> -                         uint32_t value, int width, int be)
> +static void pflash_write(void *opaque, hwaddr offset, uint64_t value,
> +                         unsigned int width)
>  {
> +    PFlashCFI02 *pfl = opaque;
>      hwaddr boff;
>      uint8_t *p;
>      uint8_t cmd;
> @@ -277,7 +294,7 @@ static void pflash_write(PFlashCFI02 *pfl, hwaddr offset,
>      trace_pflash_write(offset, value, width, pfl->wcycle);
>      offset &= pfl->chip_len - 1;
>  
> -    DPRINTF("%s: offset " TARGET_FMT_plx " %08x %d\n", __func__,
> +    DPRINTF("%s: offset " TARGET_FMT_plx " %08" PRIx64 " %d\n", __func__,
>              offset, value, width);
>      boff = offset & (pfl->sector_len - 1);
>      if (pfl->width == 2)
> @@ -295,7 +312,7 @@ static void pflash_write(PFlashCFI02 *pfl, hwaddr offset,
>          if (boff == 0x55 && cmd == 0x98) {
>          enter_CFI_mode:
>              /* Enter CFI query mode */
> -            pfl->wcycle = 7;
> +            pfl->wcycle = WCYCLE_CFI;
>              pfl->cmd = 0x98;
>              return;
>          }
> @@ -345,40 +362,22 @@ static void pflash_write(PFlashCFI02 *pfl, hwaddr 
> offset,
>              goto check_unlock0;
>          case 0xA0:
>              trace_pflash_data_write(offset, value, width, 0);
> -            p = pfl->storage;
>              if (!pfl->ro) {
> -                switch (width) {
> -                case 1:
> -                    p[offset] &= value;
> -                    pflash_update(pfl, offset, 1);
> -                    break;
> -                case 2:
> -                    if (be) {
> -                        p[offset] &= value >> 8;
> -                        p[offset + 1] &= value;
> -                    } else {
> -                        p[offset] &= value;
> -                        p[offset + 1] &= value >> 8;
> -                    }
> -                    pflash_update(pfl, offset, 2);
> -                    break;
> -                case 4:
> -                    if (be) {
> -                        p[offset] &= value >> 24;
> -                        p[offset + 1] &= value >> 16;
> -                        p[offset + 2] &= value >> 8;
> -                        p[offset + 3] &= value;
> -                    } else {
> -                        p[offset] &= value;
> -                        p[offset + 1] &= value >> 8;
> -                        p[offset + 2] &= value >> 16;
> -                        p[offset + 3] &= value >> 24;
> -                    }
> -                    pflash_update(pfl, offset, 4);
> -                    break;
> +                p = (uint8_t *)pfl->storage + offset;
> +                if (pfl->be) {
> +                    uint64_t current = ldn_be_p(p, width);
> +                    stn_be_p(p, width, current & value);
> +                } else {
> +                    uint64_t current = ldn_le_p(p, width);
> +                    stn_le_p(p, width, current & value);
>                  }
> +                pflash_update(pfl, offset, width);
>              }
> -            pfl->status = 0x00 | ~(value & 0x80);
> +            /*
> +             * While programming, status bit DQ7 should hold the opposite
> +             * value from how it was programmed.
> +             */
> +            set_dq7(pfl, ~value);
>              /* Let's pretend write is immediate */
>              if (pfl->bypass)
>                  goto do_bypass;
> @@ -426,7 +425,7 @@ static void pflash_write(PFlashCFI02 *pfl, hwaddr offset,
>                  memset(pfl->storage, 0xFF, pfl->chip_len);
>                  pflash_update(pfl, 0, pfl->chip_len);
>              }
> -            pfl->status = 0x00;
> +            set_dq7(pfl, 0x00);
>              /* Let's wait 5 seconds before chip erase is done */
>              timer_mod(&pfl->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
>                        (NANOSECONDS_PER_SECOND * 5));
> @@ -441,7 +440,7 @@ static void pflash_write(PFlashCFI02 *pfl, hwaddr offset,
>                  memset(p + offset, 0xFF, pfl->sector_len);
>                  pflash_update(pfl, offset, pfl->sector_len);
>              }
> -            pfl->status = 0x00;
> +            set_dq7(pfl, 0x00);
>              /* Let's wait 1/2 second before sector erase is done */
>              timer_mod(&pfl->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
>                        (NANOSECONDS_PER_SECOND / 2));
> @@ -467,7 +466,7 @@ static void pflash_write(PFlashCFI02 *pfl, hwaddr offset,
>              goto reset_flash;
>          }
>          break;
> -    case 7: /* Special value for CFI queries */
> +    case WCYCLE_CFI: /* Special value for CFI queries */
>          DPRINTF("%s: invalid write in CFI query mode\n", __func__);
>          goto reset_flash;
>      default:
> @@ -492,39 +491,9 @@ static void pflash_write(PFlashCFI02 *pfl, hwaddr offset,
>      pfl->cmd = 0;
>  }
>  
> -static uint64_t pflash_be_readfn(void *opaque, hwaddr addr, unsigned size)
> -{
> -    return pflash_read(opaque, addr, size, 1);
> -}
> -
> -static void pflash_be_writefn(void *opaque, hwaddr addr,
> -                              uint64_t value, unsigned size)
> -{
> -    pflash_write(opaque, addr, value, size, 1);
> -}
> -
> -static uint64_t pflash_le_readfn(void *opaque, hwaddr addr, unsigned size)
> -{
> -    return pflash_read(opaque, addr, size, 0);
> -}
> -
> -static void pflash_le_writefn(void *opaque, hwaddr addr,
> -                              uint64_t value, unsigned size)
> -{
> -    pflash_write(opaque, addr, value, size, 0);
> -}
> -
> -static const MemoryRegionOps pflash_cfi02_ops_be = {
> -    .read = pflash_be_readfn,
> -    .write = pflash_be_writefn,
> -    .valid.min_access_size = 1,
> -    .valid.max_access_size = 4,
> -    .endianness = DEVICE_NATIVE_ENDIAN,
> -};
> -
> -static const MemoryRegionOps pflash_cfi02_ops_le = {
> -    .read = pflash_le_readfn,
> -    .write = pflash_le_writefn,
> +static const MemoryRegionOps pflash_cfi02_ops = {
> +    .read = pflash_read,
> +    .write = pflash_write,
>      .valid.min_access_size = 1,
>      .valid.max_access_size = 4,
>      .endianness = DEVICE_NATIVE_ENDIAN,
> @@ -552,9 +521,9 @@ static void pflash_cfi02_realize(DeviceState *dev, Error 
> **errp)
>  
>      chip_len = pfl->sector_len * pfl->nb_blocs;
>  
> -    memory_region_init_rom_device(&pfl->orig_mem, OBJECT(pfl), pfl->be ?
> -                                  &pflash_cfi02_ops_be : 
> &pflash_cfi02_ops_le,
> -                                  pfl, pfl->name, chip_len, &local_err);
> +    memory_region_init_rom_device(&pfl->orig_mem, OBJECT(pfl),
> +                                  &pflash_cfi02_ops, pfl, pfl->name,
> +                                  chip_len, &local_err);
>      if (local_err) {
>          error_propagate(errp, local_err);
>          return;
> 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]