static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) { struct NFTLrecord *nftl; unsigned long temp; if (mtd->type != MTD_NANDFLASH) return; /* OK, this is moderately ugly. But probably safe. Alternatives? */ if (memcmp(mtd->name, "DiskOnChip", 10)) return; if (!mtd->block_isbad) { printk(KERN_ERR "NFTL no longer supports the old DiskOnChip drivers loaded via docprobe.\n" "Please use the new diskonchip driver under the NAND subsystem.\n"); return; } DEBUG(MTD_DEBUG_LEVEL1, "NFTL: add_mtd for %s\n", mtd->name); nftl = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL); if (!nftl) { printk(KERN_WARNING "NFTL: out of memory for data structures\n"); return; } memset(nftl, 0, sizeof(*nftl)); nftl->mbd.mtd = mtd; nftl->mbd.devnum = -1; nftl->mbd.blksize = 512; nftl->mbd.tr = tr; memcpy(&nftl->oobinfo, &mtd->oobinfo, sizeof(struct nand_oobinfo)); nftl->oobinfo.useecc = MTD_NANDECC_PLACEONLY; if (NFTL_mount(nftl) < 0) { printk(KERN_WARNING "NFTL: could not mount device\n"); kfree(nftl); return; } /* OK, it's a new one. Set up all the data structures. */ /* Calculate geometry */ nftl->cylinders = 1024; nftl->heads = 16; temp = nftl->cylinders * nftl->heads; nftl->sectors = nftl->mbd.size / temp; if (nftl->mbd.size % temp) { nftl->sectors++; temp = nftl->cylinders * nftl->sectors; nftl->heads = nftl->mbd.size / temp; if (nftl->mbd.size % temp) { nftl->heads++; temp = nftl->heads * nftl->sectors; nftl->cylinders = nftl->mbd.size / temp; } } if (nftl->mbd.size != nftl->heads * nftl->cylinders * nftl->sectors) { /* Oh no we don't have mbd.size == heads * cylinders * sectors */ printk(KERN_WARNING "NFTL: cannot calculate a geometry to " "match size of 0x%lx.\n", nftl->mbd.size); printk(KERN_WARNING "NFTL: using C:%d H:%d S:%d " "(== 0x%lx sects)\n", nftl->cylinders, nftl->heads , nftl->sectors, (long)nftl->cylinders * (long)nftl->heads * (long)nftl->sectors ); } if (add_mtd_blktrans_dev(&nftl->mbd)) { if (nftl->ReplUnitTable) kfree(nftl->ReplUnitTable); if (nftl->EUNtable) kfree(nftl->EUNtable); kfree(nftl); return; } #ifdef PSYCHO_DEBUG printk(KERN_INFO "NFTL: Found new nftl%c\n", nftl->mbd.devnum + 'a'); #endif }
static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) { struct NFTLrecord *nftl; unsigned long temp; if (mtd->ecctype != MTD_ECC_RS_DiskOnChip) return; DEBUG(MTD_DEBUG_LEVEL1, "NFTL: add_mtd for %s\n", mtd->name); nftl = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL); if (!nftl) { printk(KERN_WARNING "NFTL: out of memory for data structures\n"); return; } memset(nftl, 0, sizeof(*nftl)); nftl->mbd.mtd = mtd; nftl->mbd.devnum = -1; nftl->mbd.blksize = 512; nftl->mbd.tr = tr; if (NFTL_mount(nftl) < 0) { printk(KERN_WARNING "NFTL: could not mount device\n"); kfree(nftl); return; } /* OK, it's a new one. Set up all the data structures. */ /* Calculate geometry */ nftl->cylinders = 1024; nftl->heads = 16; temp = nftl->cylinders * nftl->heads; nftl->sectors = nftl->mbd.size / temp; if (nftl->mbd.size % temp) { nftl->sectors++; temp = nftl->cylinders * nftl->sectors; nftl->heads = nftl->mbd.size / temp; if (nftl->mbd.size % temp) { nftl->heads++; temp = nftl->heads * nftl->sectors; nftl->cylinders = nftl->mbd.size / temp; } } if (nftl->mbd.size != nftl->heads * nftl->cylinders * nftl->sectors) { /* Oh no we don't have mbd.size == heads * cylinders * sectors */ printk(KERN_WARNING "NFTL: cannot calculate a geometry to " "match size of 0x%lx.\n", nftl->mbd.size); printk(KERN_WARNING "NFTL: using C:%d H:%d S:%d " "(== 0x%lx sects)\n", nftl->cylinders, nftl->heads , nftl->sectors, (long)nftl->cylinders * (long)nftl->heads * (long)nftl->sectors ); } if (add_mtd_blktrans_dev(&nftl->mbd)) { if (nftl->ReplUnitTable) kfree(nftl->ReplUnitTable); if (nftl->EUNtable) kfree(nftl->EUNtable); kfree(nftl); return; } #ifdef PSYCHO_DEBUG printk(KERN_INFO "NFTL: Found new nftl%c\n", nftl->mbd.devnum + 'a'); #endif }
static void NFTL_setup(struct mtd_info *mtd) { int i; struct NFTLrecord *nftl; unsigned long temp; int firstfree = -1; DEBUG(MTD_DEBUG_LEVEL1,"NFTL_setup\n"); for (i = 0; i < MAX_NFTLS; i++) { if (!NFTLs[i] && firstfree == -1) firstfree = i; else if (NFTLs[i] && NFTLs[i]->mtd == mtd) { /* This is a Spare Media Header for an NFTL we've already found */ DEBUG(MTD_DEBUG_LEVEL1, "MTD already mounted as NFTL\n"); return; } } if (firstfree == -1) { printk(KERN_WARNING "No more NFTL slot available\n"); return; } nftl = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL); if (!nftl) { printk(KERN_WARNING "Out of memory for NFTL data structures\n"); return; } init_MUTEX(&nftl->mutex); nftl->mtd = mtd; if (NFTL_mount(nftl) < 0) { printk(KERN_WARNING "Could not mount NFTL device\n"); kfree(nftl); return; } /* OK, it's a new one. Set up all the data structures. */ #ifdef PSYCHO_DEBUG printk("Found new NFTL nftl%c\n", firstfree + 'a'); #endif /* linux stuff */ nftl->usecount = 0; nftl->cylinders = 1024; nftl->heads = 16; temp = nftl->cylinders * nftl->heads; nftl->sectors = nftl->nr_sects / temp; if (nftl->nr_sects % temp) { nftl->sectors++; temp = nftl->cylinders * nftl->sectors; nftl->heads = nftl->nr_sects / temp; if (nftl->nr_sects % temp) { nftl->heads++; temp = nftl->heads * nftl->sectors; nftl->cylinders = nftl->nr_sects / temp; } } if (nftl->nr_sects != nftl->heads * nftl->cylinders * nftl->sectors) { printk(KERN_WARNING "Cannot calculate an NFTL geometry to " "match size of 0x%x.\n", nftl->nr_sects); printk(KERN_WARNING "Using C:%d H:%d S:%d (== 0x%lx sects)\n", nftl->cylinders, nftl->heads , nftl->sectors, (long)nftl->cylinders * (long)nftl->heads * (long)nftl->sectors ); /* Oh no we don't have nftl->nr_sects = nftl->heads * nftl->cylinders * nftl->sectors; */ } NFTLs[firstfree] = nftl; /* Finally, set up the block device sizes */ nftl_sizes[firstfree * 16] = nftl->nr_sects; //nftl_blocksizes[firstfree*16] = 512; part_table[firstfree * 16].nr_sects = nftl->nr_sects; nftl_gendisk.nr_real++; /* partition check ... */ #if LINUX_VERSION_CODE < 0x20328 resetup_one_dev(&nftl_gendisk, firstfree); #else grok_partitions(&nftl_gendisk, firstfree, 1<<NFTL_PARTN_BITS, nftl->nr_sects); #endif }
static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) { struct NFTLrecord *nftl; unsigned long temp; if (mtd->type != MTD_NANDFLASH || mtd->size > UINT_MAX) return; /* OK, this is moderately ugly. But probably safe. Alternatives? */ if (memcmp(mtd->name, "DiskOnChip", 10)) return; pr_debug("NFTL: add_mtd for %s\n", mtd->name); nftl = kzalloc(sizeof(struct NFTLrecord), GFP_KERNEL); if (!nftl) return; nftl->mbd.mtd = mtd; nftl->mbd.devnum = -1; nftl->mbd.tr = tr; if (NFTL_mount(nftl) < 0) { printk(KERN_WARNING "NFTL: could not mount device\n"); kfree(nftl); return; } /* OK, it's a new one. Set up all the data structures. */ /* Calculate geometry */ nftl->cylinders = 1024; nftl->heads = 16; temp = nftl->cylinders * nftl->heads; nftl->sectors = nftl->mbd.size / temp; if (nftl->mbd.size % temp) { nftl->sectors++; temp = nftl->cylinders * nftl->sectors; nftl->heads = nftl->mbd.size / temp; if (nftl->mbd.size % temp) { nftl->heads++; temp = nftl->heads * nftl->sectors; nftl->cylinders = nftl->mbd.size / temp; } } if (nftl->mbd.size != nftl->heads * nftl->cylinders * nftl->sectors) { /* Oh no we don't have mbd.size == heads * cylinders * sectors */ printk(KERN_WARNING "NFTL: cannot calculate a geometry to " "match size of 0x%lx.\n", nftl->mbd.size); printk(KERN_WARNING "NFTL: using C:%d H:%d S:%d " "(== 0x%lx sects)\n", nftl->cylinders, nftl->heads , nftl->sectors, (long)nftl->cylinders * (long)nftl->heads * (long)nftl->sectors ); } if (add_mtd_blktrans_dev(&nftl->mbd)) { kfree(nftl->ReplUnitTable); kfree(nftl->EUNtable); kfree(nftl); return; } #ifdef PSYCHO_DEBUG printk(KERN_INFO "NFTL: Found new nftl%c\n", nftl->mbd.devnum + 'a'); #endif }