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

📄 flash.patch

📁 linux交叉编译环境个软件和内核的补丁。
💻 PATCH
📖 第 1 页 / 共 3 页
字号:
+    kfree(flash);+    return;+  }++  fdi->num_regions = cfi_read_char(ptr, CFI_NUM_ERASE_BLOCKS_OFFSET,+                                     0, bit_width);+  DEBUG("Num regions: %d\n", fdi->num_regions);++  fdi->region = kmalloc(sizeof(flash_region_info_t)*fdi->num_regions, GFP_KERNEL);+  if (!fdi->region) {+    kfree(flash);+    kfree(fdi);+    return;+  }++  flash->ptr = ptr;+  flash->size = size;+  flash->bit_width = bit_width;+  flash->chip_cfg = chip_cfg;+  flash->mutex = MUTEX;++  fdi->ops = &amd_ops;+  fdi->next = NULL;+  fdi->handle = flash;+  fdi->dev = 0;++  offset = 0;+  for (i=0;i<fdi->num_regions;i++) {+    reg_info = cfi_read_int(ptr, CFI_ERASE_REGION_INFO_OFFSET+4*i,+                            0, bit_width, chip_cfg);+    fdi->region[i].offset = offset;+    sector_size = (reg_info >> 16) & 0xFFFF;+    if (sector_size==0)+      fdi->region[i].sector_size = 128 << chip_cfg;+    else+      fdi->region[i].sector_size = (sector_size*256) << chip_cfg;++    fdi->region[i].num_sectors = (reg_info & 0xFFFF) + 1;++    DEBUG("sector %i size: %d, num_sectors: %d, total size: %d\n", i,+           fdi->region[i].sector_size , fdi->region[i].num_sectors,+           fdi->region[i].sector_size * fdi->region[i].num_sectors);++    offset += fdi->region[i].sector_size * fdi->region[i].num_sectors;+  }++  register_flash(fdi);++  /* Return to read array mode: */++  ptr[0] = 0xff;+  ptr[1] = 0xff;+  ptr[2] = 0xff;+  ptr[3] = 0xff;+}++static u_int read_with_chip_width(struct amd_flash *flash, u_long offs)+{+  u_int data;+  vu_char *ptr = flash->ptr;++  switch(individual_bit_width(flash)) {+  case 0: /* 8bit */+    data = (ptr[offs]);+    break;+  case 1: /* 16bit */+    data = (*(u_short *)&ptr[offs]);+    break;+  case 2: /* 32bit */+    data = (*(u_int *)&ptr[offs]);+    break;+  }+  return data;+}++#define PROGRAM_WRITE 1+#define PROGRAM_ERASE 2++static int program_in_progress(struct amd_flash *flash)+{+  /* This function doesn't work reliably if erase_suspend is used. */+  vu_char *ptr;+  int i;+  int num_chip;+  u_int data1, data2, data;++  num_chip = 1<<flash->chip_cfg;++  ptr = flash->ptr;++  for (i=0;i<num_chip;i++) {+    data1 = read_with_chip_width(flash, 0) & 0x44; /* mask out DQ6 and DQ2 */+    data2 = read_with_chip_width(flash, 0) & 0x44 ;/* mask out DQ6 and DQ2 */+    data = data1 ^ data2; /* xor */+    if (data&0x40) {+      /* DQ6 toggled, some program is running (might be in erase suspend) */+      DEBUG("dq6 on chip %d toggled, embedded program running.\n", i);+      if (data&0x04) {+        DEBUG("dq2 on chip %d toggled, erase runnung.\n", i);+        return PROGRAM_ERASE;+      } else {+        DEBUG("dq2 on chip %d not toggled, write runnung.\n", i);+        return PROGRAM_WRITE;+      }+    }+  }+  return 0; /* No program in progress. */+}++static void do_erase_sector(vu_char *ptr, off_t offset)+{+  u_long j;+  u_int  data;+  vu_int *addr;++  j = jiffies;++  addr = (vu_int *)(&ptr[0x555 << 2]); *addr = 0x00AA00AA;+  addr = (vu_int *)(&ptr[0x2AA << 2]); *addr = 0x00550055;+  addr = (vu_int *)(&ptr[0x555 << 2]); *addr = 0x00800080;+  addr = (vu_int *)(&ptr[0x555 << 2]); *addr = 0x00AA00AA;+  addr = (vu_int *)(&ptr[0x2AA << 2]); *addr = 0x00550055;+  addr = (vu_int *)(&ptr[offset    ]); *addr = 0x00300030;++  current->state = TASK_INTERRUPTIBLE;+  schedule_timeout(10*100/HZ); /* Time out 0.1 sec. */+  while ((data = *(vu_int *)&ptr[offset])!=0xffffffff) {+    current->state = TASK_INTERRUPTIBLE;+    schedule_timeout(10*100/HZ); /* Time out 0.1 sec. */+  }++  j = jiffies - j;+  DEBUG("Erasing @ 0x%lx took %ld jiffies\n", offset, j);+}++static int amd_read(struct flash_device_info *fdi,+                    char *buf, size_t count, off_t offset, int userspace_ptr)+{+  struct amd_flash *flash = fdi->handle;+  int ret;++  ret = 0;++/********+  DEBUG("amd_read buf=0x%lx, ptr=0x%x, count=%d, offset=0x%lx, us_ptr=0x%ld\n",+      (u_long)buf, (int)flash->ptr, (int)count, offset, (long) userspace_ptr);+********/++  down(&flash->mutex);++  if (program_in_progress(flash)) {+    printk("Error, embedded program in progress during flash read\n");+    ret = -EIO;+    goto error;+  }++  if (userspace_ptr) {+    if (copy_to_user(buf, (char *)flash->ptr+offset, count) > 0) {+      ret = -EFAULT;+    }+  } else {+    memcpy(buf, (char *)flash->ptr+offset, count);+  }++ error:++  up(&flash->mutex);++  return ret;+}++static void unlock_bypass(vu_char *ptr, off_t offset)+{+  vu_int *addr;++  addr = (vu_int *)(&ptr[0x555 << 2]); *addr = 0x00AA00AA;+  addr = (vu_int *)(&ptr[0x2AA << 2]); *addr = 0x00550055;+  addr = (vu_int *)(&ptr[0x555 << 2]); *addr = 0x00200020;+}++static void unlock_bypass_reset(vu_char *ptr, off_t offset)+{+  /* Address is "don't care" for unlock_bypass_reset */+  *(vu_int *)&ptr[offset] = 0x00900090;+  *(vu_int *)&ptr[offset] = 0x00000000;+}++static int do_write_int(vu_char *ptr, off_t offset, u_int data )+{+  int wait, wait1;+  u_int old;++  if ( ((old = *(vu_int *)&ptr[offset]) & data) != data) {+    printk("Flash write error, not fully erased at 0x%p+0x%lx: old 0x%08x  new 0x%08x\n", ptr, offset, old, data);+    return (-1);+  }+  /* Program word: */+  /* Address is "don't care" in unlock_bypass mode */+  *(vu_int *)&ptr[offset] = 0x00A000A0;+  *(vu_int *)&ptr[offset] = data;++  wait1 = wait = 0;+  while ((old = *(vu_int *)&ptr[offset]) != data) {+    wait++;+    if ((wait%10000)==0) {+      DEBUG("do_write_int, wait=%d\n", wait);+      DEBUG("addr = 0x%x, offset = 0x%lx, data = 0x%08x, flash: 0x%08x\n",+              (int)&ptr[offset], offset, data, old);+      if (++wait1 > 32) {+	return (-1);+      }+    }+    /* Busy wait */+  }+  return (0);+}++static int do_write_char(vu_char *ptr, off_t offset, u_char data )+{+  int wait, wait1;+  off_t s_offset;+  u_short value, old;+  u_char c;++  if ( ((c = ptr[offset]) & data) != data) {+    printk("Flash write error, not fully erased at 0x%p+0x%lx: old 0x%02x  new 0x%02x\n",+	ptr, offset, c, data);+    return (-1);+  }++  s_offset = offset & (~1);+  old      = *(vu_short *)&ptr[s_offset];++  if (s_offset == offset) {		/* even address	*/+	value = (old & 0x00FF) | (data << 8);+  } else {				/* off address	*/+  	value = (old & 0xFF00) | data;+  }++  *(vu_short *)&ptr[s_offset] = 0x00A0;+  *(vu_short *)&ptr[s_offset] = value;++  wait1 = wait = 0;+  while ((c = ptr[offset]) != data) {+    wait++;+    if ((wait%1000)==0) {+      old = *(vu_short *)&ptr[s_offset];+      DEBUG("do_write_char, wait=%d, "+      	    "offset = %lx, data = %02x, flash: %02x [0x%04x]\n",+              wait, offset, data, c, old);+      if (++wait1 > 32) {+	return (-1);+      }+    }+    /* Busy wait */+  }+  return (0);+}+++static int amd_write(struct flash_device_info *fdi,+                     const char *buf, size_t count, off_t offset, int userspace_ptr)+{+  struct amd_flash *flash = fdi->handle;+  struct timeval time1, time2;+  vu_char *ptr;+  int ret;+  off_t bypass_offset;+  u_long end_offset;+  u_int data;+  int loops;++  ret = 0;+  ptr = flash->ptr;++/***+  DEBUG("amd_write buf=0x%x, count=%d=0x%x, offset=0x%x, us_ptr=%d\n",+    (int)buf, (int)count, (int)count, (int)offset, (int) userspace_ptr);+***/++  down(&flash->mutex);++  if (program_in_progress(flash)) {+    printk("Error, embedded program in progress during flash write\n");+    ret = -EIO;+    goto ERROR;+  }++  end_offset = offset + count;++  if (userspace_ptr && (!access_ok(VERIFY_READ, buf, count)) ) {+    ret = -EFAULT;+    goto ERROR;+  }++  bypass_offset = offset;+  unlock_bypass(ptr, bypass_offset);++  do_gettimeofday(&time1);++  loops = 0;+  while (offset<end_offset) {+    if ((offset%4 == 0) && (end_offset-offset >= 4)) {+      if (userspace_ptr) {+        if (__get_user(data, (int *)buf)) {+          ret = -EFAULT;+          goto UNLOCK_BYPASS_RESET_ERROR;+        }+      } else {+        data = *(int *)buf;+      }++      if (do_write_int(ptr, offset, data)) {+	ret = -EFAULT;+	goto UNLOCK_BYPASS_RESET_ERROR;+      }+      buf += 4;+      offset += 4;+    } else {+      if (userspace_ptr) {+        if (__get_user(data, (char *)buf)) {+          ret = -EFAULT;+          goto UNLOCK_BYPASS_RESET_ERROR;+        }+      } else {+        data = *(char *)buf;+      }+      if (do_write_char(ptr, offset, data)) {+        ret = -EFAULT;+	goto UNLOCK_BYPASS_RESET_ERROR;+      }+      buf += 1;+      offset += 1;+    }++    /* every 32 writes we check if >1msec has passed. then we schedule */+    if ((++loops & 0x1f) == 0) {+      do_gettimeofday(&time2);+      time2.tv_sec -= time1.tv_sec;+      time2.tv_usec -= time1.tv_usec;++      if ((time2.tv_sec>0) || (time2.tv_usec>1000)) {+        /* May wait to short if tv_sec wraps. Who cares... */+        current->state = TASK_RUNNING;+        schedule();+        if (userspace_ptr && (!access_ok(VERIFY_READ, buf, count))) {+          ret = -EFAULT;+          goto UNLOCK_BYPASS_RESET_ERROR;+        }+        do_gettimeofday(&time1);+      }+    }+  }++UNLOCK_BYPASS_RESET_ERROR:+  unlock_bypass_reset(ptr, bypass_offset);+ERROR:+  up(&flash->mutex);++  return ret;+}++static int amd_erase_sector(struct flash_device_info *fdi,+                            off_t offset, size_t count)+{+  struct amd_flash *flash = fdi->handle;+  flash_region_info_t *region = NULL;+  u_long region_size, region_end;+  u_long end;+  int ret;+  int i;++  ret = 0;++  end = offset + count;++  DEBUG("%s[%d]: amd_erase count=%d, offset=0x%x, end=0x%x\n",__FILE__,__LINE__,+    (int)count, (int)offset,(int)end);++  down(&flash->mutex);++  if (!flash_on_sector_boundaries(fdi, offset, count)) {+    DEBUG("Trying to erase, but not at sector boundaries. offs=%x, count=%x\n",+            (int)offset, (int)count);+    ret = -EINVAL;+    goto error;+  }++  if (program_in_progress(flash)) {+    printk("Error, embedded program in progress during flash erase\n");+    ret = -EIO;+    goto error;+  }++  /* erase all sectors in mem region */+  /* Now guaranteed to be on sector boundaries */+  for (i = 0; i<fdi->num_regions; i++) {+    region = &fdi->region[i];++    region_size = region->sector_size * region->num_sectors;+    region_end  = region->offset + region_size;++    if (region->offset >= end) {+      break;+    }++    if  ( (offset >= region->offset) && (offset < region_end) ) {+      u_long erase_end = (end > region_end) ? region_end : end;++      while (offset < erase_end) {+	do_erase_sector(flash->ptr, offset);+	offset += region->sector_size;+      }+    }+  }++++ error:++  up(&flash->mutex);++  return ret;+}++static int amd_protect_sector(struct flash_device_info *fdi,+                              off_t offset, size_t count, int protected)+{+  return -ENOSYS;+}++static int amd_get_info(struct flash_device_info *fdi,+                         flash_info_t *flash_info)+{+  struct amd_flash *flash = fdi->handle;+  flash_info_t t;+  int ret;++  t.size = flash->size;+  t.bitwidth = 8<<individual_bit_width(flash);+  t.chip_config = 1<<flash->chip_cfg;+  t.num_regions = fdi->num_regions;+  t.num_regions = fdi->num_regions;++  ret = copy_to_user(flash_info, &t, sizeof(flash_info_t));+  if (ret)+    return -EFAULT;++  return 0;+}

⌨️ 快捷键说明

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