int i, j, nand_maf_id, nand_dev_id, busw, maf_id; 
int i, nand_maf_id, nand_dev_id, busw, maf_id; 
int nand_scan (struct mtd_info *mtd, int maxchips){	int i, j, nand_maf_id, nand_dev_id, busw, maf_id;	struct nand_chip *this = mtd->priv;	/* Get buswidth to select the correct functions*/	busw = this->options & NAND_BUSWIDTH_16;	/* check for proper chip_delay setup, set 20us if not */	if (!this->chip_delay)		this->chip_delay = 20;	/* check, if a user supplied command function given */	if (this->cmdfunc == NULL)		this->cmdfunc = nand_command;	/* check, if a user supplied wait function given */	if (this->waitfunc == NULL)		this->waitfunc = nand_wait;	if (!this->select_chip)		this->select_chip = nand_select_chip;	if (!this->write_byte)		this->write_byte = busw ? nand_write_byte16 : nand_write_byte;	if (!this->read_byte)		this->read_byte = busw ? nand_read_byte16 : nand_read_byte;	if (!this->write_word)		this->write_word = nand_write_word;	if (!this->read_word)		this->read_word = nand_read_word;	if (!this->block_bad)		this->block_bad = nand_block_bad;	if (!this->block_markbad)		this->block_markbad = nand_default_block_markbad;	if (!this->write_buf)		this->write_buf = busw ? nand_write_buf16 : nand_write_buf;	if (!this->read_buf)		this->read_buf = busw ? nand_read_buf16 : nand_read_buf;	if (!this->verify_buf)		this->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;	if (!this->scan_bbt)		this->scan_bbt = nand_default_bbt;	/* Select the device */	this->select_chip(mtd, 0);	/* Send the command for reading device ID */	this->cmdfunc (mtd, NAND_CMD_READID, 0x00, -1);	/* Read manufacturer and device IDs */	nand_maf_id = this->read_byte(mtd);	nand_dev_id = this->read_byte(mtd);	/* Print and store flash device information */	for (i = 0; nand_flash_ids[i].name != NULL; i++) {						if (nand_dev_id != nand_flash_ids[i].id) 			continue;		if (!mtd->name) mtd->name = nand_flash_ids[i].name;		this->chipsize = nand_flash_ids[i].chipsize << 20;				/* New devices have all the information in additional id bytes */		if (!nand_flash_ids[i].pagesize) {			int extid;			/* The 3rd id byte contains non relevant data ATM */			extid = this->read_byte(mtd);			/* The 4th id byte is the important one */			extid = this->read_byte(mtd);			/* Calc pagesize */			mtd->oobblock = 1024 << (extid & 0x3);			extid >>= 2;			/* Calc oobsize */			mtd->oobsize = (8 << (extid & 0x03)) * (mtd->oobblock / 512);			extid >>= 2;			/* Calc blocksize. Blocksize is multiples of 64KiB */			mtd->erasesize = (64 * 1024)  << (extid & 0x03);			extid >>= 2;			/* Get buswidth information */			busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;				} else {			/* Old devices have this data hardcoded in the			 * device id table */			mtd->erasesize = nand_flash_ids[i].erasesize;			mtd->oobblock = nand_flash_ids[i].pagesize;			mtd->oobsize = mtd->oobblock / 32;			busw = nand_flash_ids[i].options & NAND_BUSWIDTH_16;		}		/* Try to identify manufacturer */		for (maf_id = 0; nand_manuf_ids[maf_id].id != 0x0; maf_id++) {			if (nand_manuf_ids[maf_id].id == nand_maf_id)				break;		}		/* Check, if buswidth is correct. Hardware drivers should set		 * this correct ! */		if (busw != (this->options & NAND_BUSWIDTH_16)) {			printk (KERN_INFO "NAND device: Manufacturer ID:"				" 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id, 				nand_manuf_ids[maf_id].name , mtd->name);			printk (KERN_WARNING 				"NAND bus width %d instead %d bit\n", 					(this->options & NAND_BUSWIDTH_16) ? 16 : 8,					busw ? 16 : 8);			this->select_chip(mtd, -1);			return 1;			}				/* Calculate the address shift from the page size */			this->page_shift = ffs(mtd->oobblock) - 1;		this->bbt_erase_shift = this->phys_erase_shift = ffs(mtd->erasesize) - 1;		this->chip_shift = ffs(this->chipsize) - 1;		/* Set the bad block position */		this->badblockpos = mtd->oobblock > 512 ? 			NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;		/* Get chip options, preserve non chip based options */		this->options &= ~NAND_CHIPOPTIONS_MSK;		this->options |= nand_flash_ids[i].options & NAND_CHIPOPTIONS_MSK;		/* Set this as a default. Board drivers can override it, if neccecary */		this->options |= NAND_NO_AUTOINCR;		/* Check if this is a not a samsung device. Do not clear the options		 * for chips which are not having an extended id.		 */			if (nand_maf_id != NAND_MFR_SAMSUNG && !nand_flash_ids[i].pagesize)			this->options &= ~NAND_SAMSUNG_LP_OPTIONS;				/* Check for AND chips with 4 page planes */		if (this->options & NAND_4PAGE_ARRAY)			this->erase_cmd = multi_erase_cmd;		else			this->erase_cmd = single_erase_cmd;		/* Do not replace user supplied command function ! */		if (mtd->oobblock > 512 && this->cmdfunc == nand_command)			this->cmdfunc = nand_command_lp;						printk (KERN_INFO "NAND device: Manufacturer ID:"			" 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id, 			nand_manuf_ids[maf_id].name , nand_flash_ids[i].name);		break;	}	if (!nand_flash_ids[i].name) {		printk (KERN_WARNING "No NAND device found!!!\n");		this->select_chip(mtd, -1);		return 1;	}	for (i=1; i < maxchips; i++) {		this->select_chip(mtd, i);		/* Send the command for reading device ID */		this->cmdfunc (mtd, NAND_CMD_READID, 0x00, -1);		/* Read manufacturer and device IDs */		if (nand_maf_id != this->read_byte(mtd) ||		    nand_dev_id != this->read_byte(mtd))			break;	}	if (i > 1)		printk(KERN_INFO "%d NAND chips detected\n", i);		/* Allocate buffers, if neccecary */	if (!this->oob_buf) {		size_t len;		len = mtd->oobsize << (this->phys_erase_shift - this->page_shift);		this->oob_buf = kmalloc (len, GFP_KERNEL);		if (!this->oob_buf) {			printk (KERN_ERR "nand_scan(): Cannot allocate oob_buf\n");			return -ENOMEM;		}		this->options |= NAND_OOBBUF_ALLOC;	}		if (!this->data_buf) {		size_t len;		len = mtd->oobblock + mtd->oobsize;		this->data_buf = kmalloc (len, GFP_KERNEL);		if (!this->data_buf) {			if (this->options & NAND_OOBBUF_ALLOC)				kfree (this->oob_buf);			printk (KERN_ERR "nand_scan(): Cannot allocate data_buf\n");			return -ENOMEM;		}		this->options |= NAND_DATABUF_ALLOC;	}	/* Store the number of chips and calc total size for mtd */	this->numchips = i;	mtd->size = i * this->chipsize;	/* Convert chipsize to number of pages per chip -1. */	this->pagemask = (this->chipsize >> this->page_shift) - 1;	/* Preset the internal oob buffer */	memset(this->oob_buf, 0xff, mtd->oobsize << (this->phys_erase_shift - this->page_shift));	/* If no default placement scheme is given, select an	 * appropriate one */	if (!this->autooob) {		/* Select the appropriate default oob placement scheme for		 * placement agnostic filesystems */		switch (mtd->oobsize) { 		case 8:			this->autooob = &nand_oob_8;			break;		case 16:			this->autooob = &nand_oob_16;			break;		case 64:			this->autooob = &nand_oob_64;			break;		default:			printk (KERN_WARNING "No oob scheme defined for oobsize %d\n",				mtd->oobsize);			BUG();		}	}		/* The number of bytes available for the filesystem to place fs dependend	 * oob data */	if (this->options & NAND_BUSWIDTH_16) {		mtd->oobavail = mtd->oobsize - (this->autooob->eccbytes + 2);		if (this->autooob->eccbytes & 0x01)			mtd->oobavail--;	} else		mtd->oobavail = mtd->oobsize - (this->autooob->eccbytes + 1);	/* 	 * check ECC mode, default to software	 * if 3byte/512byte hardware ECC is selected and we have 256 byte pagesize	 * fallback to software ECC 	*/	this->eccsize = 256;	/* set default eccsize */		this->eccbytes = 3;	switch (this->eccmode) {	case NAND_ECC_HW12_2048:		if (mtd->oobblock < 2048) {			printk(KERN_WARNING "2048 byte HW ECC not possible on %d byte page size, fallback to SW ECC\n",			       mtd->oobblock);			this->eccmode = NAND_ECC_SOFT;			this->calculate_ecc = nand_calculate_ecc;			this->correct_data = nand_correct_data;		} else			this->eccsize = 2048;		break;	case NAND_ECC_HW3_512: 	case NAND_ECC_HW6_512: 	case NAND_ECC_HW8_512: 		if (mtd->oobblock == 256) {			printk (KERN_WARNING "512 byte HW ECC not possible on 256 Byte pagesize, fallback to SW ECC \n");			this->eccmode = NAND_ECC_SOFT;			this->calculate_ecc = nand_calculate_ecc;			this->correct_data = nand_correct_data;		} else 			this->eccsize = 512; /* set eccsize to 512 */		break;				case NAND_ECC_HW3_256:		break;			case NAND_ECC_NONE: 		printk (KERN_WARNING "NAND_ECC_NONE selected by board driver. This is not recommended !!\n");		this->eccmode = NAND_ECC_NONE;		break;	case NAND_ECC_SOFT:			this->calculate_ecc = nand_calculate_ecc;		this->correct_data = nand_correct_data;		break;	default:		printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode);		BUG();		}		/* Check hardware ecc function availability and adjust number of ecc bytes per 	 * calculation step	*/	switch (this->eccmode) {	case NAND_ECC_HW12_2048:		this->eccbytes += 4;	case NAND_ECC_HW8_512: 		this->eccbytes += 2;	case NAND_ECC_HW6_512: 		this->eccbytes += 3;	case NAND_ECC_HW3_512: 	case NAND_ECC_HW3_256:		if (this->calculate_ecc && this->correct_data && this->enable_hwecc)			break;		printk (KERN_WARNING "No ECC functions supplied, Hardware ECC not possible\n");		BUG();		}			mtd->eccsize = this->eccsize;		/* Set the number of read / write steps for one page to ensure ECC generation */	switch (this->eccmode) {	case NAND_ECC_HW12_2048:		this->eccsteps = mtd->oobblock / 2048;		break;	case NAND_ECC_HW3_512:	case NAND_ECC_HW6_512:	case NAND_ECC_HW8_512:		this->eccsteps = mtd->oobblock / 512;		break;	case NAND_ECC_HW3_256:	case NAND_ECC_SOFT:			this->eccsteps = mtd->oobblock / 256;		break;			case NAND_ECC_NONE: 		this->eccsteps = 1;		break;	}		/* Initialize state, waitqueue and spinlock */	this->state = FL_READY;	init_waitqueue_head (&this->wq);	spin_lock_init (&this->chip_lock);	/* De-select the device */	this->select_chip(mtd, -1);	/* Invalidate the pagebuffer reference */	this->pagebuf = -1;	/* Fill in remaining MTD driver data */	mtd->type = MTD_NANDFLASH;	mtd->flags = MTD_CAP_NANDFLASH | MTD_ECC;	mtd->ecctype = MTD_ECC_SW;	mtd->erase = nand_erase;	mtd->point = NULL;	mtd->unpoint = NULL;	mtd->read = nand_read;	mtd->write = nand_write;	mtd->read_ecc = nand_read_ecc;	mtd->write_ecc = nand_write_ecc;	mtd->read_oob = nand_read_oob;	mtd->write_oob = nand_write_oob;	mtd->readv = NULL;	mtd->writev = nand_writev;	mtd->writev_ecc = nand_writev_ecc;	mtd->sync = nand_sync;	mtd->lock = NULL;	mtd->unlock = NULL;	mtd->suspend = NULL;	mtd->resume = NULL;	mtd->block_isbad = nand_block_isbad;	mtd->block_markbad = nand_block_markbad;	/* and make the autooob the default one */	memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo));	mtd->owner = THIS_MODULE;		/* Check, if we should skip the bad block table scan */	if (this->options & NAND_SKIP_BBTSCAN)		return 0;	/* Build bad block table */	return this->scan_bbt (mtd);}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/3b946e3f3dc0de473a88b4106f01731a5c016689/nand_base.c/clean/drivers/mtd/nand/nand_base.c