flashio.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /*
  2. * JFFS2 -- Journalling Flash File System, Version 2.
  3. *
  4. * Copyright (C) 2001-2003 Red Hat, Inc.
  5. *
  6. * Created by Dominic Ostrowski <dominic.ostrowski@3glab.com>
  7. * Contributors: David Woodhouse, Nick Garnett, Richard Panton.
  8. *
  9. * For licensing information, see the file 'LICENCE' in this directory.
  10. *
  11. * $Id: flashio.c,v 1.1 2003/11/26 14:09:29 dwmw2 Exp $
  12. *
  13. */
  14. #include <linux/kernel.h>
  15. #include "nodelist.h"
  16. #include <rtdevice.h>
  17. int jffs2_flash_read(struct jffs2_sb_info * c, uint32_t offset,
  18. const size_t size,
  19. size_t * return_size,
  20. unsigned char *buffer)
  21. {
  22. uint32_t len;
  23. struct super_block *sb = OFNI_BS_2SFFJ(c);
  24. len = rt_mtd_read(RT_MTD_DEVICE(sb->s_dev), offset, buffer, size);
  25. if (len != size)
  26. return -EIO;
  27. * return_size = len;
  28. return ENOERR;
  29. }
  30. int jffs2_flash_write(struct jffs2_sb_info * c,
  31. uint32_t offset, const size_t size,
  32. size_t * return_size, unsigned char *buffer)
  33. {
  34. uint32_t len;
  35. struct super_block *sb = OFNI_BS_2SFFJ(c);
  36. len = rt_mtd_write(RT_MTD_DEVICE(sb->s_dev), offset, buffer, size);
  37. if (len != size)
  38. return -EIO;
  39. * return_size = len;
  40. return ENOERR;
  41. }
  42. int jffs2_flash_erase(struct jffs2_sb_info * c,
  43. struct jffs2_eraseblock * jeb)
  44. {
  45. rt_err_t result;
  46. struct super_block *sb = OFNI_BS_2SFFJ(c);
  47. result = rt_mtd_erase_block(RT_MTD_DEVICE(sb->s_dev), jeb->offset);
  48. if (result != RT_EOK)
  49. return -EIO;
  50. return ENOERR;
  51. }
  52. int jffs2_flash_direct_writev(struct jffs2_sb_info *c,
  53. const struct iovec *vecs, unsigned long count, loff_t to,
  54. size_t * retlen)
  55. {
  56. unsigned long i;
  57. size_t totlen = 0, thislen;
  58. int ret = 0;
  59. for (i = 0; i < count; i++)
  60. {
  61. // writes need to be aligned but the data we're passed may not be
  62. // Observation suggests most unaligned writes are small, so we
  63. // optimize for that case.
  64. if (((vecs[i].iov_len & (sizeof(int) - 1))) ||
  65. (((unsigned long) vecs[i].iov_base & (sizeof(unsigned long) - 1))))
  66. {
  67. // are there iov's after this one? Or is it so much we'd need
  68. // to do multiple writes anyway?
  69. if ((i + 1) < count || vecs[i].iov_len > 256)
  70. {
  71. // cop out and malloc
  72. unsigned long j;
  73. ssize_t sizetomalloc = 0, totvecsize = 0;
  74. char *cbuf, *cbufptr;
  75. for (j = i; j < count; j++)
  76. totvecsize += vecs[j].iov_len;
  77. // pad up in case unaligned
  78. sizetomalloc = totvecsize + sizeof(int) - 1;
  79. sizetomalloc &= ~(sizeof(int) - 1);
  80. cbuf = (char *) rt_malloc(sizetomalloc);
  81. // malloc returns aligned memory
  82. if (!cbuf)
  83. {
  84. ret = -ENOMEM;
  85. goto writev_out;
  86. }
  87. cbufptr = cbuf;
  88. for (j = i; j < count; j++)
  89. {
  90. memcpy(cbufptr, vecs[j].iov_base, vecs[j].iov_len);
  91. cbufptr += vecs[j].iov_len;
  92. }
  93. //rt_kprintf("direct_write: offset %d, size %d\n", to, sizetomalloc);
  94. ret = jffs2_flash_write(c, to, sizetomalloc, &thislen,
  95. (unsigned char *) cbuf);
  96. if (thislen > totvecsize) // in case it was aligned up
  97. thislen = totvecsize;
  98. totlen += thislen;
  99. rt_free(cbuf);
  100. goto writev_out;
  101. }
  102. else
  103. {
  104. // otherwise optimize for the common case
  105. int buf[256/sizeof(int)]; // int, so int aligned
  106. size_t lentowrite;
  107. lentowrite = vecs[i].iov_len;
  108. // pad up in case its unaligned
  109. lentowrite += sizeof(int) - 1;
  110. lentowrite &= ~(sizeof(int) - 1);
  111. memcpy(buf, vecs[i].iov_base, lentowrite);
  112. //rt_kprintf("direct_write: offset %d, size %d\n", to, lentowrite);
  113. ret = jffs2_flash_write(c, to, lentowrite, &thislen,
  114. (unsigned char *) &buf);
  115. if (thislen > vecs[i].iov_len)
  116. thislen = vecs[i].iov_len;
  117. }
  118. }
  119. else
  120. {
  121. //rt_kprintf("direct_writev: offset %d, size %d\n", to, vecs[i].iov_len);
  122. ret = jffs2_flash_write(c, to, vecs[i].iov_len, &thislen,
  123. vecs[i].iov_base);
  124. }
  125. totlen += thislen;
  126. if (ret || thislen != vecs[i].iov_len) break;
  127. to += vecs[i].iov_len;
  128. }
  129. writev_out:
  130. if (retlen) *retlen = totlen;
  131. return ret;
  132. }