aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/rfd_ftl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/rfd_ftl.c')
-rw-r--r--drivers/mtd/rfd_ftl.c114
1 files changed, 57 insertions, 57 deletions
diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c
index 7b9f359f04b7..041ee59ea77d 100644
--- a/drivers/mtd/rfd_ftl.c
+++ b/drivers/mtd/rfd_ftl.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Copyright (C) 2005 Sean Young <sean@mess.org> 4 * Copyright (C) 2005 Sean Young <sean@mess.org>
5 * 5 *
6 * $Id: rfd_ftl.c,v 1.4 2005/07/31 22:49:14 sean Exp $ 6 * $Id: rfd_ftl.c,v 1.5 2005/11/07 11:14:21 gleixner Exp $
7 * 7 *
8 * This type of flash translation layer (FTL) is used by the Embedded BIOS 8 * This type of flash translation layer (FTL) is used by the Embedded BIOS
9 * by General Software. It is known as the Resident Flash Disk (RFD), see: 9 * by General Software. It is known as the Resident Flash Disk (RFD), see:
@@ -95,7 +95,7 @@ static int build_block_map(struct partition *part, int block_no)
95{ 95{
96 struct block *block = &part->blocks[block_no]; 96 struct block *block = &part->blocks[block_no];
97 int i; 97 int i;
98 98
99 block->offset = part->block_size * block_no; 99 block->offset = part->block_size * block_no;
100 100
101 if (le16_to_cpu(part->header_cache[0]) != RFD_MAGIC) { 101 if (le16_to_cpu(part->header_cache[0]) != RFD_MAGIC) {
@@ -109,12 +109,12 @@ static int build_block_map(struct partition *part, int block_no)
109 109
110 for (i=0; i<part->data_sectors_per_block; i++) { 110 for (i=0; i<part->data_sectors_per_block; i++) {
111 u16 entry; 111 u16 entry;
112 112
113 entry = le16_to_cpu(part->header_cache[HEADER_MAP_OFFSET + i]); 113 entry = le16_to_cpu(part->header_cache[HEADER_MAP_OFFSET + i]);
114 114
115 if (entry == SECTOR_DELETED) 115 if (entry == SECTOR_DELETED)
116 continue; 116 continue;
117 117
118 if (entry == SECTOR_FREE) { 118 if (entry == SECTOR_FREE) {
119 block->free_sectors++; 119 block->free_sectors++;
120 continue; 120 continue;
@@ -122,9 +122,9 @@ static int build_block_map(struct partition *part, int block_no)
122 122
123 if (entry == SECTOR_ZERO) 123 if (entry == SECTOR_ZERO)
124 entry = 0; 124 entry = 0;
125 125
126 if (entry >= part->sector_count) { 126 if (entry >= part->sector_count) {
127 printk(KERN_NOTICE PREFIX 127 printk(KERN_NOTICE PREFIX
128 "'%s': unit #%d: entry %d corrupt, " 128 "'%s': unit #%d: entry %d corrupt, "
129 "sector %d out of range\n", 129 "sector %d out of range\n",
130 part->mbd.mtd->name, block_no, i, entry); 130 part->mbd.mtd->name, block_no, i, entry);
@@ -132,14 +132,14 @@ static int build_block_map(struct partition *part, int block_no)
132 } 132 }
133 133
134 if (part->sector_map[entry] != -1) { 134 if (part->sector_map[entry] != -1) {
135 printk(KERN_NOTICE PREFIX 135 printk(KERN_NOTICE PREFIX
136 "'%s': more than one entry for sector %d\n", 136 "'%s': more than one entry for sector %d\n",
137 part->mbd.mtd->name, entry); 137 part->mbd.mtd->name, entry);
138 part->errors = 1; 138 part->errors = 1;
139 continue; 139 continue;
140 } 140 }
141 141
142 part->sector_map[entry] = block->offset + 142 part->sector_map[entry] = block->offset +
143 (i + part->header_sectors_per_block) * SECTOR_SIZE; 143 (i + part->header_sectors_per_block) * SECTOR_SIZE;
144 144
145 block->used_sectors++; 145 block->used_sectors++;
@@ -165,14 +165,14 @@ static int scan_header(struct partition *part)
165 return -ENOENT; 165 return -ENOENT;
166 166
167 /* each erase block has three bytes header, followed by the map */ 167 /* each erase block has three bytes header, followed by the map */
168 part->header_sectors_per_block = 168 part->header_sectors_per_block =
169 ((HEADER_MAP_OFFSET + sectors_per_block) * 169 ((HEADER_MAP_OFFSET + sectors_per_block) *
170 sizeof(u16) + SECTOR_SIZE - 1) / SECTOR_SIZE; 170 sizeof(u16) + SECTOR_SIZE - 1) / SECTOR_SIZE;
171 171
172 part->data_sectors_per_block = sectors_per_block - 172 part->data_sectors_per_block = sectors_per_block -
173 part->header_sectors_per_block; 173 part->header_sectors_per_block;
174 174
175 part->header_size = (HEADER_MAP_OFFSET + 175 part->header_size = (HEADER_MAP_OFFSET +
176 part->data_sectors_per_block) * sizeof(u16); 176 part->data_sectors_per_block) * sizeof(u16);
177 177
178 part->cylinders = (part->data_sectors_per_block * 178 part->cylinders = (part->data_sectors_per_block *
@@ -188,7 +188,7 @@ static int scan_header(struct partition *part)
188 if (!part->header_cache) 188 if (!part->header_cache)
189 goto err; 189 goto err;
190 190
191 part->blocks = kcalloc(part->total_blocks, sizeof(struct block), 191 part->blocks = kcalloc(part->total_blocks, sizeof(struct block),
192 GFP_KERNEL); 192 GFP_KERNEL);
193 if (!part->blocks) 193 if (!part->blocks)
194 goto err; 194 goto err;
@@ -200,18 +200,18 @@ static int scan_header(struct partition *part)
200 goto err; 200 goto err;
201 } 201 }
202 202
203 for (i=0; i<part->sector_count; i++) 203 for (i=0; i<part->sector_count; i++)
204 part->sector_map[i] = -1; 204 part->sector_map[i] = -1;
205 205
206 for (i=0, blocks_found=0; i<part->total_blocks; i++) { 206 for (i=0, blocks_found=0; i<part->total_blocks; i++) {
207 rc = part->mbd.mtd->read(part->mbd.mtd, 207 rc = part->mbd.mtd->read(part->mbd.mtd,
208 i * part->block_size, part->header_size, 208 i * part->block_size, part->header_size,
209 &retlen, (u_char*)part->header_cache); 209 &retlen, (u_char*)part->header_cache);
210 210
211 if (!rc && retlen != part->header_size) 211 if (!rc && retlen != part->header_size)
212 rc = -EIO; 212 rc = -EIO;
213 213
214 if (rc) 214 if (rc)
215 goto err; 215 goto err;
216 216
217 if (!build_block_map(part, i)) 217 if (!build_block_map(part, i))
@@ -226,7 +226,7 @@ static int scan_header(struct partition *part)
226 } 226 }
227 227
228 if (part->reserved_block == -1) { 228 if (part->reserved_block == -1) {
229 printk(KERN_NOTICE PREFIX "'%s': no empty erase unit found\n", 229 printk(KERN_NOTICE PREFIX "'%s': no empty erase unit found\n",
230 part->mbd.mtd->name); 230 part->mbd.mtd->name);
231 231
232 part->errors = 1; 232 part->errors = 1;
@@ -248,7 +248,7 @@ static int rfd_ftl_readsect(struct mtd_blktrans_dev *dev, u_long sector, char *b
248 u_long addr; 248 u_long addr;
249 size_t retlen; 249 size_t retlen;
250 int rc; 250 int rc;
251 251
252 if (sector >= part->sector_count) 252 if (sector >= part->sector_count)
253 return -EIO; 253 return -EIO;
254 254
@@ -266,9 +266,9 @@ static int rfd_ftl_readsect(struct mtd_blktrans_dev *dev, u_long sector, char *b
266 } 266 }
267 } else 267 } else
268 memset(buf, 0, SECTOR_SIZE); 268 memset(buf, 0, SECTOR_SIZE);
269 269
270 return 0; 270 return 0;
271} 271}
272 272
273static void erase_callback(struct erase_info *erase) 273static void erase_callback(struct erase_info *erase)
274{ 274{
@@ -288,7 +288,7 @@ static void erase_callback(struct erase_info *erase)
288 288
289 if (erase->state != MTD_ERASE_DONE) { 289 if (erase->state != MTD_ERASE_DONE) {
290 printk(KERN_WARNING PREFIX "erase failed at 0x%x on '%s', " 290 printk(KERN_WARNING PREFIX "erase failed at 0x%x on '%s', "
291 "state %d\n", erase->addr, 291 "state %d\n", erase->addr,
292 part->mbd.mtd->name, erase->state); 292 part->mbd.mtd->name, erase->state);
293 293
294 part->blocks[i].state = BLOCK_FAILED; 294 part->blocks[i].state = BLOCK_FAILED;
@@ -307,17 +307,17 @@ static void erase_callback(struct erase_info *erase)
307 part->blocks[i].used_sectors = 0; 307 part->blocks[i].used_sectors = 0;
308 part->blocks[i].erases++; 308 part->blocks[i].erases++;
309 309
310 rc = part->mbd.mtd->write(part->mbd.mtd, 310 rc = part->mbd.mtd->write(part->mbd.mtd,
311 part->blocks[i].offset, sizeof(magic), &retlen, 311 part->blocks[i].offset, sizeof(magic), &retlen,
312 (u_char*)&magic); 312 (u_char*)&magic);
313 313
314 if (!rc && retlen != sizeof(magic)) 314 if (!rc && retlen != sizeof(magic))
315 rc = -EIO; 315 rc = -EIO;
316 316
317 if (rc) { 317 if (rc) {
318 printk(KERN_NOTICE PREFIX "'%s': unable to write RFD " 318 printk(KERN_NOTICE PREFIX "'%s': unable to write RFD "
319 "header at 0x%lx\n", 319 "header at 0x%lx\n",
320 part->mbd.mtd->name, 320 part->mbd.mtd->name,
321 part->blocks[i].offset); 321 part->blocks[i].offset);
322 part->blocks[i].state = BLOCK_FAILED; 322 part->blocks[i].state = BLOCK_FAILED;
323 } 323 }
@@ -374,17 +374,17 @@ static int move_block_contents(struct partition *part, int block_no, u_long *old
374 map = kmalloc(part->header_size, GFP_KERNEL); 374 map = kmalloc(part->header_size, GFP_KERNEL);
375 if (!map) 375 if (!map)
376 goto err2; 376 goto err2;
377 377
378 rc = part->mbd.mtd->read(part->mbd.mtd, 378 rc = part->mbd.mtd->read(part->mbd.mtd,
379 part->blocks[block_no].offset, part->header_size, 379 part->blocks[block_no].offset, part->header_size,
380 &retlen, (u_char*)map); 380 &retlen, (u_char*)map);
381 381
382 if (!rc && retlen != part->header_size) 382 if (!rc && retlen != part->header_size)
383 rc = -EIO; 383 rc = -EIO;
384 384
385 if (rc) { 385 if (rc) {
386 printk(KERN_NOTICE PREFIX "error reading '%s' at " 386 printk(KERN_NOTICE PREFIX "error reading '%s' at "
387 "0x%lx\n", part->mbd.mtd->name, 387 "0x%lx\n", part->mbd.mtd->name,
388 part->blocks[block_no].offset); 388 part->blocks[block_no].offset);
389 389
390 goto err; 390 goto err;
@@ -398,11 +398,11 @@ static int move_block_contents(struct partition *part, int block_no, u_long *old
398 if (entry == SECTOR_FREE || entry == SECTOR_DELETED) 398 if (entry == SECTOR_FREE || entry == SECTOR_DELETED)
399 continue; 399 continue;
400 400
401 if (entry == SECTOR_ZERO) 401 if (entry == SECTOR_ZERO)
402 entry = 0; 402 entry = 0;
403 403
404 /* already warned about and ignored in build_block_map() */ 404 /* already warned about and ignored in build_block_map() */
405 if (entry >= part->sector_count) 405 if (entry >= part->sector_count)
406 continue; 406 continue;
407 407
408 addr = part->blocks[block_no].offset + 408 addr = part->blocks[block_no].offset +
@@ -418,7 +418,7 @@ static int move_block_contents(struct partition *part, int block_no, u_long *old
418 } 418 }
419 rc = part->mbd.mtd->read(part->mbd.mtd, addr, 419 rc = part->mbd.mtd->read(part->mbd.mtd, addr,
420 SECTOR_SIZE, &retlen, sector_data); 420 SECTOR_SIZE, &retlen, sector_data);
421 421
422 if (!rc && retlen != SECTOR_SIZE) 422 if (!rc && retlen != SECTOR_SIZE)
423 rc = -EIO; 423 rc = -EIO;
424 424
@@ -429,11 +429,11 @@ static int move_block_contents(struct partition *part, int block_no, u_long *old
429 429
430 goto err; 430 goto err;
431 } 431 }
432 432
433 rc = rfd_ftl_writesect((struct mtd_blktrans_dev*)part, 433 rc = rfd_ftl_writesect((struct mtd_blktrans_dev*)part,
434 entry, sector_data); 434 entry, sector_data);
435 435
436 if (rc) 436 if (rc)
437 goto err; 437 goto err;
438 } 438 }
439 439
@@ -447,11 +447,11 @@ err3:
447 return rc; 447 return rc;
448} 448}
449 449
450static int reclaim_block(struct partition *part, u_long *old_sector) 450static int reclaim_block(struct partition *part, u_long *old_sector)
451{ 451{
452 int block, best_block, score, old_sector_block; 452 int block, best_block, score, old_sector_block;
453 int rc; 453 int rc;
454 454
455 /* we have a race if sync doesn't exist */ 455 /* we have a race if sync doesn't exist */
456 if (part->mbd.mtd->sync) 456 if (part->mbd.mtd->sync)
457 part->mbd.mtd->sync(part->mbd.mtd); 457 part->mbd.mtd->sync(part->mbd.mtd);
@@ -474,16 +474,16 @@ static int reclaim_block(struct partition *part, u_long *old_sector)
474 * more removed sectors is more efficient (have to move 474 * more removed sectors is more efficient (have to move
475 * less). 475 * less).
476 */ 476 */
477 if (part->blocks[block].free_sectors) 477 if (part->blocks[block].free_sectors)
478 return 0; 478 return 0;
479 479
480 this_score = part->blocks[block].used_sectors; 480 this_score = part->blocks[block].used_sectors;
481 481
482 if (block == old_sector_block) 482 if (block == old_sector_block)
483 this_score--; 483 this_score--;
484 else { 484 else {
485 /* no point in moving a full block */ 485 /* no point in moving a full block */
486 if (part->blocks[block].used_sectors == 486 if (part->blocks[block].used_sectors ==
487 part->data_sectors_per_block) 487 part->data_sectors_per_block)
488 continue; 488 continue;
489 } 489 }
@@ -529,7 +529,7 @@ static int find_free_block(const struct partition *part)
529 stop = block; 529 stop = block;
530 530
531 do { 531 do {
532 if (part->blocks[block].free_sectors && 532 if (part->blocks[block].free_sectors &&
533 block != part->reserved_block) 533 block != part->reserved_block)
534 return block; 534 return block;
535 535
@@ -563,7 +563,7 @@ static int find_writeable_block(struct partition *part, u_long *old_sector)
563 } 563 }
564 } 564 }
565 565
566 rc = part->mbd.mtd->read(part->mbd.mtd, part->blocks[block].offset, 566 rc = part->mbd.mtd->read(part->mbd.mtd, part->blocks[block].offset,
567 part->header_size, &retlen, (u_char*)part->header_cache); 567 part->header_size, &retlen, (u_char*)part->header_cache);
568 568
569 if (!rc && retlen != part->header_size) 569 if (!rc && retlen != part->header_size)
@@ -571,7 +571,7 @@ static int find_writeable_block(struct partition *part, u_long *old_sector)
571 571
572 if (rc) { 572 if (rc) {
573 printk(KERN_NOTICE PREFIX "'%s': unable to read header at " 573 printk(KERN_NOTICE PREFIX "'%s': unable to read header at "
574 "0x%lx\n", part->mbd.mtd->name, 574 "0x%lx\n", part->mbd.mtd->name,
575 part->blocks[block].offset); 575 part->blocks[block].offset);
576 goto err; 576 goto err;
577 } 577 }
@@ -580,7 +580,7 @@ static int find_writeable_block(struct partition *part, u_long *old_sector)
580 580
581err: 581err:
582 return rc; 582 return rc;
583} 583}
584 584
585static int mark_sector_deleted(struct partition *part, u_long old_addr) 585static int mark_sector_deleted(struct partition *part, u_long old_addr)
586{ 586{
@@ -590,7 +590,7 @@ static int mark_sector_deleted(struct partition *part, u_long old_addr)
590 u16 del = const_cpu_to_le16(SECTOR_DELETED); 590 u16 del = const_cpu_to_le16(SECTOR_DELETED);
591 591
592 block = old_addr / part->block_size; 592 block = old_addr / part->block_size;
593 offset = (old_addr % part->block_size) / SECTOR_SIZE - 593 offset = (old_addr % part->block_size) / SECTOR_SIZE -
594 part->header_sectors_per_block; 594 part->header_sectors_per_block;
595 595
596 addr = part->blocks[block].offset + 596 addr = part->blocks[block].offset +
@@ -604,7 +604,7 @@ static int mark_sector_deleted(struct partition *part, u_long old_addr)
604 if (rc) { 604 if (rc) {
605 printk(KERN_WARNING PREFIX "error writing '%s' at " 605 printk(KERN_WARNING PREFIX "error writing '%s' at "
606 "0x%lx\n", part->mbd.mtd->name, addr); 606 "0x%lx\n", part->mbd.mtd->name, addr);
607 if (rc) 607 if (rc)
608 goto err; 608 goto err;
609 } 609 }
610 if (block == part->current_block) 610 if (block == part->current_block)
@@ -627,7 +627,7 @@ static int find_free_sector(const struct partition *part, const struct block *bl
627 i = stop = part->data_sectors_per_block - block->free_sectors; 627 i = stop = part->data_sectors_per_block - block->free_sectors;
628 628
629 do { 629 do {
630 if (le16_to_cpu(part->header_cache[HEADER_MAP_OFFSET + i]) 630 if (le16_to_cpu(part->header_cache[HEADER_MAP_OFFSET + i])
631 == SECTOR_FREE) 631 == SECTOR_FREE)
632 return i; 632 return i;
633 633
@@ -653,7 +653,7 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf,
653 !part->blocks[part->current_block].free_sectors) { 653 !part->blocks[part->current_block].free_sectors) {
654 654
655 rc = find_writeable_block(part, old_addr); 655 rc = find_writeable_block(part, old_addr);
656 if (rc) 656 if (rc)
657 goto err; 657 goto err;
658 } 658 }
659 659
@@ -665,10 +665,10 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf,
665 rc = -ENOSPC; 665 rc = -ENOSPC;
666 goto err; 666 goto err;
667 } 667 }
668 668
669 addr = (i + part->header_sectors_per_block) * SECTOR_SIZE + 669 addr = (i + part->header_sectors_per_block) * SECTOR_SIZE +
670 block->offset; 670 block->offset;
671 rc = part->mbd.mtd->write(part->mbd.mtd, 671 rc = part->mbd.mtd->write(part->mbd.mtd,
672 addr, SECTOR_SIZE, &retlen, (u_char*)buf); 672 addr, SECTOR_SIZE, &retlen, (u_char*)buf);
673 673
674 if (!rc && retlen != SECTOR_SIZE) 674 if (!rc && retlen != SECTOR_SIZE)
@@ -677,7 +677,7 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf,
677 if (rc) { 677 if (rc) {
678 printk(KERN_WARNING PREFIX "error writing '%s' at 0x%lx\n", 678 printk(KERN_WARNING PREFIX "error writing '%s' at 0x%lx\n",
679 part->mbd.mtd->name, addr); 679 part->mbd.mtd->name, addr);
680 if (rc) 680 if (rc)
681 goto err; 681 goto err;
682 } 682 }
683 683
@@ -697,7 +697,7 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf,
697 if (rc) { 697 if (rc) {
698 printk(KERN_WARNING PREFIX "error writing '%s' at 0x%lx\n", 698 printk(KERN_WARNING PREFIX "error writing '%s' at 0x%lx\n",
699 part->mbd.mtd->name, addr); 699 part->mbd.mtd->name, addr);
700 if (rc) 700 if (rc)
701 goto err; 701 goto err;
702 } 702 }
703 block->used_sectors++; 703 block->used_sectors++;
@@ -738,7 +738,7 @@ static int rfd_ftl_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *
738 break; 738 break;
739 } 739 }
740 740
741 if (i == SECTOR_SIZE) 741 if (i == SECTOR_SIZE)
742 part->sector_map[sector] = -1; 742 part->sector_map[sector] = -1;
743 743
744 if (old_addr != -1) 744 if (old_addr != -1)
@@ -801,7 +801,7 @@ static void rfd_ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
801 801
802 if (!add_mtd_blktrans_dev((void*)part)) 802 if (!add_mtd_blktrans_dev((void*)part))
803 return; 803 return;
804 } 804 }
805 805
806 kfree(part); 806 kfree(part);
807} 807}
@@ -828,7 +828,7 @@ struct mtd_blktrans_ops rfd_ftl_tr = {
828 .major = RFD_FTL_MAJOR, 828 .major = RFD_FTL_MAJOR,
829 .part_bits = PART_BITS, 829 .part_bits = PART_BITS,
830 .readsect = rfd_ftl_readsect, 830 .readsect = rfd_ftl_readsect,
831 .writesect = rfd_ftl_writesect, 831 .writesect = rfd_ftl_writesect,
832 .getgeo = rfd_ftl_getgeo, 832 .getgeo = rfd_ftl_getgeo,
833 .add_mtd = rfd_ftl_add_mtd, 833 .add_mtd = rfd_ftl_add_mtd,
834 .remove_dev = rfd_ftl_remove_dev, 834 .remove_dev = rfd_ftl_remove_dev,