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

📄 cmd_doc.c

📁 F:worksip2440a board可启动u-boot-like.tar.gz F:worksip2440a board可启动u-boot-like.tar.gz
💻 C
📖 第 1 页 / 共 3 页
字号:
	volatile int dummy;	int modulus = 0xffff;	unsigned long docptr;	int i;	docptr = doc->virtadr;	if (len <= 0)		return;	if (DoC_is_Millennium(doc)) {		/* Read the data via the internal pipeline through CDSN IO register,		   see Pipelined Read Operations 11.3 */		dummy = ReadDOC(docptr, ReadPipeInit);		/* Millennium should use the LastDataRead register - Pipeline Reads */		len--;		/* This is needed for correctly ECC calculation */		modulus = 0xff;	}	for (i = 0; i < len; i++)		buf[i] = ReadDOC_(docptr, doc->ioreg + (i & modulus));	if (DoC_is_Millennium(doc)) {		buf[i] = ReadDOC(docptr, LastDataRead);	}}/* Write a buffer to DoC, taking care of Millennium oddities */static void DoC_WriteBuf(struct DiskOnChip *doc, const u_char * buf, int len){	unsigned long docptr;	int i;	docptr = doc->virtadr;	if (len <= 0)		return;	for (i = 0; i < len; i++)		WriteDOC_(buf[i], docptr, doc->ioreg + i);	if (DoC_is_Millennium(doc)) {		WriteDOC(0x00, docptr, WritePipeTerm);	}}/* DoC_SelectChip: Select a given flash chip within the current floor */static inline int DoC_SelectChip(struct DiskOnChip *doc, int chip){	unsigned long docptr = doc->virtadr;	/* Software requirement 11.4.4 before writing DeviceSelect */	/* Deassert the CE line to eliminate glitches on the FCE# outputs */	WriteDOC(CDSN_CTRL_WP, docptr, CDSNControl);	DoC_Delay(doc, 4);	/* Software requirement 11.4.3 for Millennium */	/* Select the individual flash chip requested */	WriteDOC(chip, docptr, CDSNDeviceSelect);	DoC_Delay(doc, 4);	/* Reassert the CE line */	WriteDOC(CDSN_CTRL_CE | CDSN_CTRL_FLASH_IO | CDSN_CTRL_WP, docptr,		 CDSNControl);	DoC_Delay(doc, 4);	/* Software requirement 11.4.3 for Millennium */	/* Wait for it to be ready */	return DoC_WaitReady(doc);}/* DoC_SelectFloor: Select a given floor (bank of flash chips) */static inline int DoC_SelectFloor(struct DiskOnChip *doc, int floor){	unsigned long docptr = doc->virtadr;	/* Select the floor (bank) of chips required */	WriteDOC(floor, docptr, FloorSelect);	/* Wait for the chip to be ready */	return DoC_WaitReady(doc);}/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip){	int mfr, id, i;	volatile char dummy;	/* Page in the required floor/chip */	DoC_SelectFloor(doc, floor);	DoC_SelectChip(doc, chip);	/* Reset the chip */	if (DoC_Command(doc, NAND_CMD_RESET, CDSN_CTRL_WP)) {#ifdef DOC_DEBUG		printf("DoC_Command (reset) for %d,%d returned true\n",		       floor, chip);#endif		return 0;	}	/* Read the NAND chip ID: 1. Send ReadID command */	if (DoC_Command(doc, NAND_CMD_READID, CDSN_CTRL_WP)) {#ifdef DOC_DEBUG		printf("DoC_Command (ReadID) for %d,%d returned true\n",		       floor, chip);#endif		return 0;	}	/* Read the NAND chip ID: 2. Send address byte zero */	DoC_Address(doc, ADDR_COLUMN, 0, CDSN_CTRL_WP, 0);	/* Read the manufacturer and device id codes from the device */	/* CDSN Slow IO register see Software Requirement 11.4 item 5. */	dummy = ReadDOC(doc->virtadr, CDSNSlowIO);	DoC_Delay(doc, 2);	mfr = ReadDOC_(doc->virtadr, doc->ioreg);	/* CDSN Slow IO register see Software Requirement 11.4 item 5. */	dummy = ReadDOC(doc->virtadr, CDSNSlowIO);	DoC_Delay(doc, 2);	id = ReadDOC_(doc->virtadr, doc->ioreg);	/* No response - return failure */	if (mfr == 0xff || mfr == 0)		return 0;	/* Check it's the same as the first chip we identified.	 * M-Systems say that any given DiskOnChip device should only	 * contain _one_ type of flash part, although that's not a	 * hardware restriction. */	if (doc->mfr) {		if (doc->mfr == mfr && doc->id == id)			return 1;	/* This is another the same the first */		else			printf("Flash chip at floor %d, chip %d is different:\n",			       floor, chip);	}	/* Print and store the manufacturer and ID codes. */	for (i = 0; nand_flash_ids[i].name != NULL; i++) {		if (mfr == nand_flash_ids[i].manufacture_id &&		    id == nand_flash_ids[i].model_id) {#ifdef DOC_DEBUG			printf("Flash chip found: Manufacturer ID: %2.2X, "			       "Chip ID: %2.2X (%s)\n", mfr, id,			       nand_flash_ids[i].name);#endif			if (!doc->mfr) {				doc->mfr = mfr;				doc->id = id;				doc->chipshift =				    nand_flash_ids[i].chipshift;				doc->page256 = nand_flash_ids[i].page256;				doc->pageadrlen =				    nand_flash_ids[i].pageadrlen;				doc->erasesize =				    nand_flash_ids[i].erasesize;				doc->chips_name =				    nand_flash_ids[i].name;				return 1;			}			return 0;		}	}#ifdef DOC_DEBUG	/* We haven't fully identified the chip. Print as much as we know. */	printf("Unknown flash chip found: %2.2X %2.2X\n",	       id, mfr);#endif	return 0;}/* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */static void DoC_ScanChips(struct DiskOnChip *this){	int floor, chip;	int numchips[MAX_FLOORS];	int maxchips = MAX_CHIPS;	int ret = 1;	this->numchips = 0;	this->mfr = 0;	this->id = 0;	if (DoC_is_Millennium(this))		maxchips = MAX_CHIPS_MIL;	/* For each floor, find the number of valid chips it contains */	for (floor = 0; floor < MAX_FLOORS; floor++) {		ret = 1;		numchips[floor] = 0;		for (chip = 0; chip < maxchips && ret != 0; chip++) {			ret = DoC_IdentChip(this, floor, chip);			if (ret) {				numchips[floor]++;				this->numchips++;			}		}	}	/* If there are none at all that we recognise, bail */	if (!this->numchips) {		puts ("No flash chips recognised.\n");		return;	}	/* Allocate an array to hold the information for each chip */	this->chips = malloc(sizeof(struct Nand) * this->numchips);	if (!this->chips) {		puts ("No memory for allocating chip info structures\n");		return;	}	ret = 0;	/* Fill out the chip array with {floor, chipno} for each	 * detected chip in the device. */	for (floor = 0; floor < MAX_FLOORS; floor++) {		for (chip = 0; chip < numchips[floor]; chip++) {			this->chips[ret].floor = floor;			this->chips[ret].chip = chip;			this->chips[ret].curadr = 0;			this->chips[ret].curmode = 0x50;			ret++;		}	}	/* Calculate and print the total size of the device */	this->totlen = this->numchips * (1 << this->chipshift);#ifdef DOC_DEBUG	printf("%d flash chips found. Total DiskOnChip size: %ld MB\n",	       this->numchips, this->totlen >> 20);#endif}/* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the *	various device information of the NFTL partition and Bad Unit Table. Update *	the ReplUnitTable[] table accroding to the Bad Unit Table. ReplUnitTable[] *	is used for management of Erase Unit in other routines in nftl.c and nftlmount.c */static int find_boot_record(struct NFTLrecord *nftl){	struct nftl_uci1 h1;	struct nftl_oob oob;	unsigned int block, boot_record_count = 0;	int retlen;	u8 buf[SECTORSIZE];	struct NFTLMediaHeader *mh = &nftl->MediaHdr;	unsigned int i;	nftl->MediaUnit = BLOCK_NIL;	nftl->SpareMediaUnit = BLOCK_NIL;	/* search for a valid boot record */	for (block = 0; block < nftl->nb_blocks; block++) {		int ret;		/* Check for ANAND header first. Then can whinge if it's found but later		   checks fail */		if ((ret = doc_read_ecc(nftl->mtd, block * nftl->EraseSize, SECTORSIZE,					&retlen, buf, NULL))) {			static int warncount = 5;			if (warncount) {				printf("Block read at 0x%x failed\n", block * nftl->EraseSize);				if (!--warncount)					puts ("Further failures for this block will not be printed\n");			}			continue;		}		if (retlen < 6 || memcmp(buf, "ANAND", 6)) {			/* ANAND\0 not found. Continue */#ifdef PSYCHO_DEBUG			printf("ANAND header not found at 0x%x\n", block * nftl->EraseSize);#endif			continue;		}#ifdef NFTL_DEBUG		printf("ANAND header found at 0x%x\n", block * nftl->EraseSize);#endif		/* To be safer with BIOS, also use erase mark as discriminant */		if ((ret = doc_read_oob(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8,				8, &retlen, (char *)&h1) < 0)) {#ifdef NFTL_DEBUG			printf("ANAND header found at 0x%x, but OOB data read failed\n",			       block * nftl->EraseSize);#endif			continue;		}		/* OK, we like it. */		if (boot_record_count) {			/* We've already processed one. So we just check if			   this one is the same as the first one we found */			if (memcmp(mh, buf, sizeof(struct NFTLMediaHeader))) {#ifdef NFTL_DEBUG				printf("NFTL Media Headers at 0x%x and 0x%x disagree.\n",				       nftl->MediaUnit * nftl->EraseSize, block * nftl->EraseSize);#endif				/* if (debug) Print both side by side */				return -1;			}			if (boot_record_count == 1)				nftl->SpareMediaUnit = block;			boot_record_count++;			continue;		}		/* This is the first we've seen. Copy the media header structure into place */		memcpy(mh, buf, sizeof(struct NFTLMediaHeader));		/* Do some sanity checks on it */		if (mh->UnitSizeFactor == 0) {#ifdef NFTL_DEBUG			puts ("UnitSizeFactor 0x00 detected.\n"			      "This violates the spec but we think we know what it means...\n");#endif		} else if (mh->UnitSizeFactor != 0xff) {			printf ("Sorry, we don't support UnitSizeFactor "			      "of != 1 yet.\n");			return -1;		}		nftl->nb_boot_blocks = le16_to_cpu(mh->FirstPhysicalEUN);		if ((nftl->nb_boot_blocks + 2) >= nftl->nb_blocks) {			printf ("NFTL Media Header sanity check failed:\n"				"nb_boot_blocks (%d) + 2 > nb_blocks (%d)\n",				nftl->nb_boot_blocks, nftl->nb_blocks);			return -1;		}		nftl->numvunits = le32_to_cpu(mh->FormattedSize) / nftl->EraseSize;		if (nftl->numvunits > (nftl->nb_blocks - nftl->nb_boot_blocks - 2)) {			printf ("NFTL Media Header sanity check failed:\n"				"numvunits (%d) > nb_blocks (%d) - nb_boot_blocks(%d) - 2\n",				nftl->numvunits,				nftl->nb_blocks,				nftl->nb_boot_blocks);			return -1;		}		nftl->nr_sects  = nftl->numvunits * (nftl->EraseSize / SECTORSIZE);		/* If we're not using the last sectors in the device for some reason,		   reduce nb_blocks accordingly so we forget they're there */		nftl->nb_blocks = le16_to_cpu(mh->NumEraseUnits) + le16_to_cpu(mh->FirstPhysicalEUN);		/* read the Bad Erase Unit Table and modify ReplUnitTable[] accordingly */		for (i = 0; i < nftl->nb_blocks; i++) {			if ((i & (SECTORSIZE - 1)) == 0) {				/* read one sector for every SECTORSIZE of blocks */				if ((ret = doc_read_ecc(nftl->mtd, block * nftl->EraseSize +						       i + SECTORSIZE, SECTORSIZE,						       &retlen, buf, (char *)&oob)) < 0) {					puts ("Read of bad sector table failed\n");					return -1;				}			}			/* mark the Bad Erase Unit as RESERVED in ReplUnitTable */			if (buf[i & (SECTORSIZE - 1)] != 0xff)				nftl->ReplUnitTable[i] = BLOCK_RESERVED;		}		nftl->MediaUnit = block;		boot_record_count++;	} /* foreach (block) */	return boot_record_count?0:-1;}/* This routine is made available to other mtd code via * inter_module_register.  It must only be accessed through * inter_module_get which will bump the use count of this module.  The * addresses passed back in mtd are valid as long as the use count of * this module is non-zero, i.e. between inter_module_get and * inter_module_put.  Keith Owens <kaos@ocs.com.au> 29 Oct 2000. */static void DoC2k_init(struct DiskOnChip* this){	struct NFTLrecord *nftl;	switch (this->ChipID) {	case DOC_ChipID_Doc2k:		this->name = "DiskOnChip 2000";		this->ioreg = DoC_2k_CDSN_IO;		break;	case DOC_ChipID_DocMil:		this->name = "DiskOnChip Millennium";		this->ioreg = DoC_Mil_CDSN_IO;		break;	}#ifdef DOC_DEBUG	printf("%s found at address 0x%lX\n", this->name,	       this->physadr);#endif	this->totlen = 0;	this->numchips = 0;	this->curfloor = -1;	this->curchip = -1;	/* Ident all the chips present. */	DoC_ScanChips(this);	if ((!this->numchips) || (!this->chips))		return;	nftl = &this->nftl;	/* Get physical parameters */	nftl->EraseSize = this->erasesize;	nftl->nb_blocks = this->totlen / this->erasesize;	nftl->mtd = this;	if (find_boot_record(nftl) != 0)		this->nftl_found = 0;	else		this->nftl_found = 1;	printf("%s @ 0x%lX, %ld MB\n", this->name, this->physadr, this->totlen >> 20);}int doc_read_ecc(struct DiskOnChip* this, loff_t from, size_t len,		 size_t * retlen, u_char * buf, u_char * eccbuf){	unsigned long docptr;	struct Nand *mychip;	unsigned char syndrome[6];	volatile char dummy;	int i, len256 = 0, ret=0;	docptr = this->virtadr;	/* Don't allow read past end of device */	if (from >= this->totlen) {		puts ("Out of flash\n");		return DOC_EINVAL;	}	/* Don't allow a single read to cross a 512-byte block boundary */	if (from + len > ((from | 0x1ff) + 1))		len = ((from | 0x1ff) + 1) - from;	/* The ECC will not be calculated correctly if less than 512 is read */	if (len != 0x200 && eccbuf)		printf("ECC needs a full sector read (adr: %lx size %lx)\n",		       (long) from, (long) len);#ifdef PSYCHO_DEBUG	printf("DoC_Read (adr: %lx size %lx)\n", (long) from, (long) len);#endif	/* Find the chip which is to be used and select it */	mychip = &this->chips[shr(from, this->chipshift)];	if (this->curfloor != mychip->floor) {		DoC_SelectFloor(this, mychip->floor);		DoC_SelectChip(this, mychip->chip);	} else if (this->curchip != mychip->chip) {		DoC_SelectChip(this, mychip->chip);	}	this->curfloor = mychip->floor;	this->curchip = mychip->chip;	DoC_Command(this,		    (!this->page256		     && (from & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0,		    CDSN_CTRL_WP);	DoC_Address(this, ADDR_COLUMN_PAGE, from, CDSN_CTRL_WP,		    CDSN_CTRL_ECC_IO);	if (eccbuf) {		/* Prime the ECC engine */		WriteDOC(DOC_ECC_RESET, docptr, ECCConf);		WriteDOC(DOC_ECC_EN, docptr, ECCConf);	} else {		/* disable the ECC engine */		WriteDOC(DOC_ECC_RESET, docptr, ECCConf);		WriteDOC(DOC_ECC_DIS, docptr, ECCConf);	}	/* treat crossing 256-byte sector for 2M x 8bits devices */	if (this->page256 && from + len > (from | 0xff) + 1) {		len256 = (from | 0xff) + 1 - from;		DoC_ReadBuf(this, buf, len256);		DoC_Command(this, NAND_CMD_READ0, CDSN_CTRL_WP);		DoC_Address(this, ADDR_COLUMN_PAGE, from + len256,			    CDSN_CTRL_WP, CDSN_CTRL_ECC_IO);	}	DoC_ReadBuf(this, &buf[len256], len - len256);	/* Let the caller know we completed it */	*retlen = len;	if (eccbuf) {		/* Read the ECC data through the DiskOnChip ECC logic */		/* Note: this will work even with 2M x 8bit devices as   */		/*       they have 8 bytes of OOB per 256 page. mf.      */		DoC_ReadBuf(this, eccbuf, 6);		/* Flush the pipeline */		if (DoC_is_Millennium(this)) {			dummy = ReadDOC(docptr, ECCConf);			dummy = ReadDOC(docptr, ECCConf);

⌨️ 快捷键说明

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