+ struct mtd_info *mtd = yaffs_DeviceToContext(dev)->mtd;
+#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
+ struct mtd_oob_ops ops;
+#endif
+ size_t dummy;
+ int retval = 0;
+
+ loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
+#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
+ __u8 spareAsBytes[8]; /* OOB */
+
+ if (data && !spare)
+ retval = mtd->read(mtd, addr, dev->nDataBytesPerChunk,
+ &dummy, data);
+ else if (spare) {
+ if (dev->param.useNANDECC) {
+ ops.mode = MTD_OOB_AUTO;
+ ops.ooblen = 8; /* temp hack */
+ } else {
+ ops.mode = MTD_OOB_RAW;
+ ops.ooblen = YAFFS_BYTES_PER_SPARE;
+ }
+ ops.len = data ? dev->nDataBytesPerChunk : ops.ooblen;
+ ops.datbuf = data;
+ ops.ooboffs = 0;
+ ops.oobbuf = spareAsBytes;
+ retval = mtd->read_oob(mtd, addr, &ops);
+ if (dev->param.useNANDECC)
+ translate_oob2spare(spare, spareAsBytes);
+ }
+#else
+ __u8 *spareAsBytes = (__u8 *) spare;
+
+ if (data && spare) {
+ if (dev->param.useNANDECC) {
+ /* Careful, this call adds 2 ints */
+ /* to the end of the spare data. Calling function */
+ /* should allocate enough memory for spare, */
+ /* i.e. [YAFFS_BYTES_PER_SPARE+2*sizeof(int)]. */
+ retval =
+ mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
+ &dummy, data, spareAsBytes,
+ &yaffs_oobinfo);
+ } else {
+ retval =
+ mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
+ &dummy, data, spareAsBytes,
+ &yaffs_noeccinfo);
+ }
+ } else {
+ if (data)
+ retval =
+ mtd->read(mtd, addr, dev->nDataBytesPerChunk, &dummy,
+ data);
+ if (spare)
+ retval =
+ mtd->read_oob(mtd, addr, YAFFS_BYTES_PER_SPARE,
+ &dummy, spareAsBytes);
+ }