📄 flash.patch
字号:
+static+struct flash_device_info *flash_find_device (kdev_t dev)+{+ struct flash_device_info *fdi;++ fdi = flash_devices;+ while (fdi != NULL && fdi->dev != dev)+ fdi = fdi->next;+ return fdi;+}+++static int flash_open(struct inode * inode, struct file * filp)+{+ kdev_t dev = inode->i_rdev;+ struct flash_device_info *fdi = flash_find_device(dev);++ DEBUG("entering flash_open, minor==%d\n", MINOR(dev));+ if (fdi == NULL)+ return -ENODEV;++ filp->private_data = fdi;++ DEBUG("opened device /dev/flash%d\n", MINOR(dev));++ return 0;+}+++static struct file_operations flash_fops = {+ flash_lseek, /* lseek */+ flash_read, /* read */+ flash_write, /* write */+ NULL, /* readdir */+ NULL, /* poll */+ flash_ioctl, /* ioctl */+ NULL, /* mmap */+ flash_open, /* open */+ NULL, /* flush */+ NULL, /* release */+ NULL /* fsync */+};++int flash_on_sector_boundaries(struct flash_device_info *fdi,+ off_t offset, size_t count)+{+ flash_region_info_t *region = NULL;+ int i;+ u_long region_size;++ /* find start and check that it is on sector boundary */+ for (i = 0; i<fdi->num_regions; i++) {+ region = &fdi->region[i];+ region_size = region->sector_size*region->num_sectors;+ if ( (offset >= region->offset) &&+ (offset < region->offset+region_size) ) {+ if ((offset % region->sector_size) != 0) {+ return 0; /* Not on sector boundaries */+ } else {+ break; /* OK: start is on sector boundary */+ }+ }+ }+ /* find end and check that it is on sector boundary */+ offset += count;+ for ( ; i<fdi->num_regions; i++) {+ region = &fdi->region[i];+ region_size = region->sector_size*region->num_sectors;+ if ( (offset >= region->offset) &&+ (offset <= region->offset+region_size) ) { /* include end here, too */+ if ((offset % region->sector_size) != 0) {+ return 0; /* Not on sector boundaries */+ } else {+ return 1; /* OK: end is on sector boundary, too */+ }+ }+ }+ /* we fell trough: end is beyond device limit */+ return 0;+}+++++/********** Init stuff: ********/++#ifdef CONFIG_AMD_FLASH+extern void amd_flash_init(char *ptr, u_long size, int bit_width, int chip_cfg) __init;+#endif++static char *vendor_name_table[] __initdata = {+ "Unknown",+ "None",+ "Intel/Sharp extended",+ "AMD/Fujitsu standard",+ "Intel standard",+ "AMD/Fujitsu extended",+ "Mitsubishi standard",+ "Mitsubishi extended"+ /* Add new at end */+};++static void __init cfi_flash_init(void)+{+ volatile unsigned char *ptr;+ unsigned long probe_addr, end_addr;+ unsigned char qry[8];+ int total_buswidth=0;+ int chip_buswidth=0;+ int found_flash;+ int bit_width;+ int chip_cfg;+ u_short primary_vendor;+ unsigned char *vendor_name;+ u_long size;+ bd_t *bd = (bd_t *)res; /* pointer to board info data */++ end_addr = bd->bi_flashstart + bd->bi_flashsize;++ for (probe_addr = bd->bi_flashstart; probe_addr < end_addr ; ) {++ DEBUG("Probing for FLASH memory at 0x%lx ...\n", probe_addr);++ /*+ * Map only 16k now; remap for real size later+ */+ ptr = ioremap_nocache(probe_addr, 16<<10);++ found_flash = 0;++ /*+ * Probe at 0x10 for 8/8 bit device chip+ */+ ptr[CFI_QUERY_OFFSET] = CFI_QUERY_CMD;+ qry[0] = ptr[0x10]; /* Extra read cycle */+ qry[0] = ptr[0x10];+ qry[1] = ptr[0x11];+ qry[2] = ptr[0x12];+ if ((qry[0]=='Q') &&+ (qry[1]=='R') &&+ (qry[2]=='Y')) {+ found_flash = 1;+ total_buswidth=8;+ chip_buswidth=8;+ }++ /*+ * Probe at 0x20 for 16/8 bit device chip+ */+ if (!found_flash) {+ *(u_short *)&ptr[CFI_QUERY_OFFSET<<1] = MAKE_TWO(CFI_QUERY_CMD);+ qry[0] = ptr[0x20]; /* Extra read cycle */+ qry[0] = ptr[0x20];+ qry[1] = ptr[0x21];+ qry[2] = ptr[0x22];+ qry[3] = ptr[0x23];+ qry[4] = ptr[0x24];+ qry[5] = ptr[0x25];+ if ((qry[0]=='Q') && (qry[1]=='Q') &&+ (qry[2]=='R') && (qry[3]=='R') &&+ (qry[4]=='Y') && (qry[5]=='Y')) {+ found_flash = 1;+ total_buswidth=16;+ chip_buswidth=8;+ }+ }++ /*+ * Probe at 0x20 for 16/16 bit device chip+ */+ if (!found_flash) {+ *(u_short *)&ptr[CFI_QUERY_OFFSET<<1] = (u_short)CFI_QUERY_CMD;+ qry[0] = ptr[0x20]; /* Extra read cycle */+ qry[0] = ptr[0x20];+ qry[1] = ptr[0x21];+ qry[2] = ptr[0x22];+ qry[3] = ptr[0x23];+ qry[4] = ptr[0x24];+ qry[5] = ptr[0x25];+#ifdef __BIG_ENDIAN+ if ((qry[0]== 0 ) && (qry[1]=='Q') &&+ (qry[2]== 0 ) && (qry[3]=='R') &&+ (qry[4]== 0 ) && (qry[5]=='Y')) {+#else /* little_endian */+ if ((qry[0]=='Q') && (qry[1]== 0 ) &&+ (qry[2]=='R') && (qry[3]== 0 ) &&+ (qry[4]=='Y') && (qry[5]== 0 )) {+#endif+ found_flash = 1;+ total_buswidth=16;+ chip_buswidth=16;+ }+ }++ /*+ * Probe at 0x40 for 32/8 bit device chip+ */+ if (!found_flash) {+ *(u_int *)&ptr[CFI_QUERY_OFFSET<<2] = MAKE_FOUR(CFI_QUERY_CMD);+ qry[0] = ptr[0x40]; /* Extra read cycle */+ qry[0] = ptr[0x40];+ qry[1] = ptr[0x41];+ qry[2] = ptr[0x42];+ qry[3] = ptr[0x43];+ qry[4] = ptr[0x44];+ qry[5] = ptr[0x45];+ qry[6] = ptr[0x46];+ qry[7] = ptr[0x47];+ if ((qry[0]=='Q') && (qry[1]=='Q') &&+ (qry[2]=='Q') && (qry[3]=='Q') &&+ (qry[4]=='R') && (qry[5]=='R') &&+ (qry[6]=='R') && (qry[7]=='R')) {+ found_flash = 1;+ total_buswidth=32;+ chip_buswidth=8;+ }+ }++ /*+ * Probe at 0x40 for 32/16 bit device chip+ */+ if (!found_flash) {+ *(u_int *)&ptr[CFI_QUERY_OFFSET<<2] = (u_int)CFI_QUERY_CMD<<16 | CFI_QUERY_CMD ;+ qry[0] = ptr[0x40]; /* Extra read cycle */+ qry[0] = ptr[0x40];+ qry[1] = ptr[0x41];+ qry[2] = ptr[0x42];+ qry[3] = ptr[0x43];+ qry[4] = ptr[0x44];+ qry[5] = ptr[0x45];+ qry[6] = ptr[0x46];+ qry[7] = ptr[0x47];+#ifdef __BIG_ENDIAN+ if ((qry[0]== 0 ) && (qry[1]== 'Q' ) &&+ (qry[2]== 0 ) && (qry[3]== 'Q' ) &&+ (qry[4]== 0 ) && (qry[5]== 'R' ) &&+ (qry[6]== 0 ) && (qry[7]== 'R' )) {+#else /* little_endian */+ if ((qry[0]=='Q') && (qry[1]== 0 ) &&+ (qry[2]=='Q') && (qry[3]== 0 ) &&+ (qry[4]=='R') && (qry[5]== 0 ) &&+ (qry[6]=='R') && (qry[7]== 0 )) {+#endif+ found_flash = 1;+ total_buswidth=32;+ chip_buswidth=16;+ }+ }++ /*+ * Probe at 0x40 for 32/32 bit device chip+ */+ if (!found_flash) {+ *(u_int *)&ptr[CFI_QUERY_OFFSET<<2] = (u_int)CFI_QUERY_CMD;+ qry[0] = ptr[0x40]; /* Extra read cycle */+ qry[0] = ptr[0x40];+ qry[1] = ptr[0x41];+ qry[2] = ptr[0x42];+ qry[3] = ptr[0x43];+ qry[4] = ptr[0x44];+ qry[5] = ptr[0x45];+ qry[6] = ptr[0x46];+ qry[7] = ptr[0x47];+#ifdef __BIG_ENDIAN+ if ((qry[0]== 0 ) && (qry[1]== 0 ) &&+ (qry[2]== 0 ) && (qry[3]=='Q') &&+ (qry[4]== 0 ) && (qry[5]== 0 ) &&+ (qry[6]== 0 ) && (qry[7]=='R')) {+#else /* little_endian */+ if ((qry[0]== 0 ) && (qry[1]== 0 ) &&+ (qry[2]=='Q') && (qry[3]== 0 ) &&+ (qry[4]== 0 ) && (qry[5]== 0 ) &&+ (qry[6]=='R') && (qry[7]== 0 )) {+#endif+ found_flash = 1;+ total_buswidth=32;+ chip_buswidth=32;+ }+ }++ if (!found_flash) {+ printk("Couldn't find flash device at %lx\n", probe_addr);+ iounmap(ptr);+ break;+ }++ switch(total_buswidth) {+ case 32: bit_width = 2; break;+ case 16: bit_width = 1; break;+ case 8: bit_width = 0; break;+ }+ switch(total_buswidth/chip_buswidth) {+ case 4: chip_cfg = 2; break;+ case 2: chip_cfg = 1; break;+ case 1: chip_cfg = 0; break;+ }++ printk("bit_width: %d, chip_cfg: %d\n", bit_width, chip_cfg);++ primary_vendor = cfi_read_short(ptr, CFI_PRIMARY_VENDOR_ID_OFFSET, 0,+ bit_width, chip_cfg);++ switch(primary_vendor) {+ case CFI_VENDOR_NONE:+ vendor_name = vendor_name_table[1];+ case CFI_VENDOR_INTEL_SHARP_EXTENDED:+ vendor_name = vendor_name_table[2];+ break;+ case CFI_VENDOR_AMD_FUJITSU_STANDARD:+ vendor_name = vendor_name_table[3];+ break;+ case CFI_VENDOR_INTEL_STANDARD:+ vendor_name = vendor_name_table[4];+ break;+ case CFI_VENDOR_AMD_FUJITSU_EXTENDED:+ vendor_name = vendor_name_table[5];+ break;+ case CFI_VENDOR_MITSUBISHI_STANDARD:+ vendor_name = vendor_name_table[6];+ break;+ case CFI_VENDOR_MITSUBISHI_EXTENDED:+ vendor_name = vendor_name_table[7];+ break;+ default:+ vendor_name = vendor_name_table[0];+ break;+ }++ size = cfi_read_char(ptr, CFI_DEVICE_SIZE_OFFSET, 0, bit_width);+ size = (1<<size) << chip_cfg;++ printk("Found %dx%dbit %dMbyte CFI flash device of type %s at %lx\n",+ total_buswidth/chip_buswidth, chip_buswidth,+ (int) (size>>20),+ vendor_name, probe_addr);++ iounmap(ptr);+ ptr = ioremap_nocache(probe_addr, size);++#ifdef CONFIG_AMD_FLASH+ if (primary_vendor == CFI_VENDOR_AMD_FUJITSU_STANDARD)+ amd_flash_init(ptr, size, bit_width, chip_cfg);+#endif++ probe_addr += size;+ }+}++void __init flash_init(void)+{+ if (register_chrdev(FLASH_MAJOR,"flash",&flash_fops))+ printk("unable to get major %d for flash devs\n", FLASH_MAJOR);+ cfi_flash_init();++ /* probe for non-cfi flash memories are added here */+}+ diff -u linux-2.2.13/drivers/char/amd_flash.c.FLASH.ORIG linux-2.2.13/drivers/char/amd_flash.c--- linux-2.2.13/drivers/char/amd_flash.c.FLASH.ORIG Tue Jan 11 00:28:10 2000+++ linux-2.2.13/drivers/char/amd_flash.c Mon Jan 10 23:25:08 2000@@ -0,0 +1,541 @@+/*+ * linux/drivers/char/amd_flash.c Version 0.1+ *+ **********************************************************+ * NOTE:+ *+ * This driver has only been verified with an Am29LV017B 4x8bit configuration.+ *+ **********************************************************+ *+ * Copyright (C) 1999 Alexander Larsson (alla@lysator.liu.se or alex@signum.se)+ */++/*+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation; either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program 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 General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program; if not, write to the Free Software+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA+ */++#include <linux/config.h>+#include <linux/types.h>+#include <linux/kernel.h>+#include <linux/malloc.h>+#include <linux/init.h>+#include <linux/time.h>+#include <linux/flash.h>++#include <asm/uaccess.h>++typedef volatile unsigned int vu_int;+typedef volatile unsigned short vu_short;+typedef volatile unsigned char vu_char;++#undef DEBUGFLASH++#ifdef DEBUGFLASH+#define DEBUG(args...) printk(args)+#else+#define DEBUG(args...)+#endif++static int amd_read(struct flash_device_info *, char *, size_t, off_t, int );+static int amd_write(struct flash_device_info *, const char *, size_t, off_t, int);+static int amd_erase_sector(struct flash_device_info *, off_t, size_t);+static int amd_protect_sector(struct flash_device_info *, off_t, size_t, int);+static int amd_get_info(struct flash_device_info *, flash_info_t *);++struct amd_flash {+ vu_char *ptr;+ u_long size;+ short bit_width; /* 0==8bit, 1==16bit, 2==32bit */+ short chip_cfg; /* 0==1 chip, 1== 2 chip, 2== 4 chip */+ char erase_suspend; /* 0=unsupported, 1=read only, 2=r/w */+ struct semaphore mutex;+ /* etc.. sector protect etc... */+};+#define individual_bit_width(flash) ((flash)->bit_width-(flash)->chip_cfg)++struct flash_device_ops amd_ops = {+ amd_read,+ amd_write,+ amd_erase_sector,+ amd_protect_sector,+ amd_get_info+};++void __init amd_flash_init(char *ptr, u_long size, int bit_width, int chip_cfg)+{+ struct amd_flash *flash;+ struct flash_device_info *fdi;+ int i;+ u_long offset;+ u_long reg_info;+ int sector_size;++ flash = kmalloc(sizeof(struct amd_flash), GFP_KERNEL);+ if (!flash)+ return;++ fdi = kmalloc(sizeof(struct flash_device_info), GFP_KERNEL);+ if (!fdi) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -