func: pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
  
                                  BlockDriverState *bs, uint32_t sector_len,
  
                                  int nb_blocs, int nb_mappings, int width,
  
                                  uint16_t id0, uint16_t id1,
  
                                  uint16_t id2, uint16_t id3,
  
                                  uint16_t unlock_addr0, uint16_t unlock_addr1)
  
  {
  
      pflash_t *pfl;
  
      int32_t chip_len;
  
  
  
      chip_len = sector_len * nb_blocs;
  
      /* XXX: to be fixed */
  
  #if 0
  
      if (total_len != (8 * 1024 * 1024) && total_len != (16 * 1024 * 1024) &&
  
          total_len != (32 * 1024 * 1024) && total_len != (64 * 1024 * 1024))
  
          return NULL;
  
  #endif
  
      pfl = qemu_mallocz(sizeof(pflash_t));
  
      /* FIXME: Allocate ram ourselves.  */
  
      pfl->storage = qemu_get_ram_ptr(off);
  
      pfl->fl_mem = cpu_register_io_memory(pflash_read_ops, pflash_write_ops,
  
                                           pfl);
  
      pfl->off = off;
  
      pfl->base = base;
  
      pfl->chip_len = chip_len;
  
      pfl->mappings = nb_mappings;
  
      pflash_register_memory(pfl, 1);
  
      pfl->bs = bs;
  
      if (pfl->bs) {
  
          /* read the initial flash content */
  
          bdrv_read(pfl->bs, 0, pfl->storage, chip_len >> 9);
  
      }
  
  #if 0 /* XXX: there should be a bit to set up read-only,
  
         *      the same way the hardware does (with WP pin).
  
         */
  
      pfl->ro = 1;
  
  #else
  
      pfl->ro = 0;
  
  #endif
  
      pfl->timer = qemu_new_timer(vm_clock, pflash_timer, pfl);
  
      pfl->sector_len = sector_len;
  
      pfl->width = width;
  
      pfl->wcycle = 0;
  
      pfl->cmd = 0;
  
      pfl->status = 0;
  
      pfl->ident[0] = id0;
  
      pfl->ident[1] = id1;
  
      pfl->ident[2] = id2;
  
      pfl->ident[3] = id3;
  
      pfl->unlock_addr[0] = unlock_addr0;
  
      pfl->unlock_addr[1] = unlock_addr1;
  
      /* Hardcoded CFI table (mostly from SG29 Spansion flash) */
  
      pfl->cfi_len = 0x52;
  
      /* Standard "QRY" string */
  
      pfl->cfi_table[0x10] = 'Q';
  
      pfl->cfi_table[0x11] = 'R';
  
      pfl->cfi_table[0x12] = 'Y';
  
      /* Command set (AMD/Fujitsu) */
  
      pfl->cfi_table[0x13] = 0x02;
  
      pfl->cfi_table[0x14] = 0x00;
  
      /* Primary extended table address */
  
      pfl->cfi_table[0x15] = 0x31;
  
      pfl->cfi_table[0x16] = 0x00;
  
      /* Alternate command set (none) */
  
      pfl->cfi_table[0x17] = 0x00;
  
      pfl->cfi_table[0x18] = 0x00;
  
      /* Alternate extended table (none) */
  
      pfl->cfi_table[0x19] = 0x00;
  
      pfl->cfi_table[0x1A] = 0x00;
  
      /* Vcc min */
  
      pfl->cfi_table[0x1B] = 0x27;
  
      /* Vcc max */
  
      pfl->cfi_table[0x1C] = 0x36;
  
      /* Vpp min (no Vpp pin) */
  
      pfl->cfi_table[0x1D] = 0x00;
  
      /* Vpp max (no Vpp pin) */
  
      pfl->cfi_table[0x1E] = 0x00;
  
      /* Reserved */
  
      pfl->cfi_table[0x1F] = 0x07;
  
      /* Timeout for min size buffer write (NA) */
  
      pfl->cfi_table[0x20] = 0x00;
  
      /* Typical timeout for block erase (512 ms) */
  
      pfl->cfi_table[0x21] = 0x09;
  
      /* Typical timeout for full chip erase (4096 ms) */
  
      pfl->cfi_table[0x22] = 0x0C;
  
      /* Reserved */
  
      pfl->cfi_table[0x23] = 0x01;
  
      /* Max timeout for buffer write (NA) */
  
      pfl->cfi_table[0x24] = 0x00;
  
      /* Max timeout for block erase */
  
      pfl->cfi_table[0x25] = 0x0A;
  
      /* Max timeout for chip erase */
  
      pfl->cfi_table[0x26] = 0x0D;
  
      /* Device size */
  
      pfl->cfi_table[0x27] = ctz32(chip_len);
  
      /* Flash device interface (8 & 16 bits) */
  
      pfl->cfi_table[0x28] = 0x02;
  
      pfl->cfi_table[0x29] = 0x00;
  
      /* Max number of bytes in multi-bytes write */
  
      /* XXX: disable buffered write as it's not supported */
  
      //    pfl->cfi_table[0x2A] = 0x05;
  
      pfl->cfi_table[0x2A] = 0x00;
  
      pfl->cfi_table[0x2B] = 0x00;
  
      /* Number of erase block regions (uniform) */
  
      pfl->cfi_table[0x2C] = 0x01;
  
      /* Erase block region 1 */
  
      pfl->cfi_table[0x2D] = nb_blocs - 1;
  
      pfl->cfi_table[0x2E] = (nb_blocs - 1) >> 8;
  
      pfl->cfi_table[0x2F] = sector_len >> 8;
  
      pfl->cfi_table[0x30] = sector_len >> 16;
  
  
  
      /* Extended */
  
      pfl->cfi_table[0x31] = 'P';
  
      pfl->cfi_table[0x32] = 'R';
  
      pfl->cfi_table[0x33] = 'I';
  
  
  
      pfl->cfi_table[0x34] = '1';
  
      pfl->cfi_table[0x35] = '0';
  
  
  
      pfl->cfi_table[0x36] = 0x00;
  
      pfl->cfi_table[0x37] = 0x00;
  
      pfl->cfi_table[0x38] = 0x00;
  
      pfl->cfi_table[0x39] = 0x00;
  
  
  
      pfl->cfi_table[0x3a] = 0x00;
  
  
  
      pfl->cfi_table[0x3b] = 0x00;
  
      pfl->cfi_table[0x3c] = 0x00;
  
  
  
      return pfl;
  
  }
  