SdDisks.Mos 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. MODULE SdDisks;
  2. (**
  3. AUTHOR Timothée Martiel, 12/2015
  4. PURPOSE Disk interface for the SD card driver
  5. *)
  6. IMPORT
  7. SYSTEM,
  8. Disks, Strings,
  9. Sd, SdEnvironment,
  10. Trace;
  11. CONST
  12. (** Base name for SD block devices *)
  13. BaseDevName = "SD";
  14. (** Number of entries used in the cache *)
  15. CacheSize = 32;
  16. TYPE
  17. (** SD Block Device *)
  18. BlockDevice * = POINTER TO BlockDeviceDesc;
  19. BlockDeviceDesc * = RECORD (Disks.BlockDeviceDesc)
  20. card: Sd.Card;
  21. bufferSize: LONGINT;
  22. cache: POINTER TO ARRAY OF CacheEntry;
  23. nextSd: BlockDevice;
  24. END;
  25. (** SD cache entry. *)
  26. CacheEntry = RECORD
  27. buffer: POINTER TO ARRAY OF CHAR;
  28. au: LONGINT;
  29. active, mod: BOOLEAN;
  30. END;
  31. (** Create a new block device for the specified card *)
  32. PROCEDURE InitBlockDevice * (d: BlockDevice; card: Sd.Card);
  33. VAR
  34. name, id: ARRAY 32 OF CHAR;
  35. ignore, i: LONGINT;
  36. BEGIN
  37. name := BaseDevName;
  38. Strings.IntToStr(devId, id);
  39. INC(devId);
  40. Strings.Append(name, id);
  41. Disks.InitBlockDevice(d, name);
  42. d.bufferSize := card.sdStatus.auSize DIV Sd.BlockSize;
  43. NEW(d.cache, CacheSize);
  44. FOR i := 0 TO CacheSize - 1 DO NEW(d.cache[i].buffer, d.bufferSize * Sd.BlockSize) END;
  45. d.blockSize := Sd.BlockSize;
  46. d.Read := Read;
  47. d.Write := Write;
  48. d.Open := Open;
  49. d.Close := Close;
  50. d.Reset := Reset;
  51. d.GetSize := GetSize;
  52. d.Handle := Handle;
  53. d.card := card
  54. END InitBlockDevice;
  55. (** Read blocks from SD card *)
  56. PROCEDURE Read (dev: Disks.BlockDevice; block, num: LONGINT; VAR data: ARRAY OF SYSTEM.BYTE; ofs: LONGINT; VAR res: LONGINT);
  57. VAR
  58. au, auOfs, idx, size, s: LONGINT;
  59. BEGIN
  60. WITH dev: BlockDevice DO
  61. size := num * Sd.BlockSize;
  62. WHILE size > 0 DO
  63. au := block DIV dev.bufferSize;
  64. auOfs := block MOD dev.bufferSize;
  65. idx := au MOD CacheSize;
  66. IF ~UpdateCacheEntry(dev, dev.cache[idx], au, res) THEN RETURN END;
  67. s := MIN(size, (dev.bufferSize - auOfs) * Sd.BlockSize);
  68. SYSTEM.MOVE(ADDRESSOF(dev.cache[idx].buffer[auOfs * Sd.BlockSize]), ADDRESSOF(data[ofs]), s);
  69. DEC(size, s);
  70. INC(ofs, s);
  71. INC(block, s DIV Sd.BlockSize)
  72. END
  73. END
  74. END Read;
  75. (** Write blocks to SD card *)
  76. PROCEDURE Write (dev: Disks.BlockDevice; block, num: LONGINT; VAR data: ARRAY OF SYSTEM.BYTE; ofs: LONGINT; VAR res: LONGINT);
  77. VAR
  78. au, auOfs, idx, size, s: LONGINT;
  79. BEGIN
  80. WITH dev: BlockDevice DO
  81. size := num * Sd.BlockSize;
  82. WHILE size > 0 DO
  83. au := block DIV dev.bufferSize;
  84. auOfs := block MOD dev.bufferSize;
  85. idx := au MOD CacheSize;
  86. IF ~UpdateCacheEntry(dev, dev.cache[idx], au, res) THEN RETURN END;
  87. dev.cache[idx].mod := TRUE;
  88. s := MIN(size, (dev.bufferSize - auOfs) * Sd.BlockSize);
  89. ASSERT(ofs + s <= LEN(data));
  90. ASSERT(auOfs * Sd.BlockSize + s <= LEN(dev.cache[idx].buffer));
  91. SYSTEM.MOVE(ADDRESSOF(data[ofs]), ADDRESSOF(dev.cache[idx].buffer[auOfs * Sd.BlockSize]), s);
  92. DEC(size, s);
  93. INC(ofs, s);
  94. INC(block, s DIV Sd.BlockSize)
  95. END
  96. END
  97. END Write;
  98. (** Update cache entry to make sure it contains the data for the given au *)
  99. PROCEDURE UpdateCacheEntry (dev: BlockDevice; VAR cache: CacheEntry; au: LONGINT; VAR res: LONGINT): BOOLEAN;
  100. VAR
  101. ignore: BOOLEAN;
  102. BEGIN
  103. IF ~cache.active OR (cache.au # au) THEN
  104. IF cache.active & cache.mod THEN
  105. IF ~Sd.Write(dev.card, cache.au * dev.bufferSize, dev.bufferSize * Sd.BlockSize, cache.buffer^, 0, res) THEN
  106. RETURN FALSE
  107. END;
  108. END;
  109. IF ~Sd.Read(dev.card, au * dev.bufferSize, dev.bufferSize * Sd.BlockSize, cache.buffer^, 0, res) THEN
  110. RETURN FALSE
  111. END;
  112. cache.active := TRUE;
  113. cache.mod := FALSE;
  114. cache.au := au
  115. END;
  116. RETURN TRUE
  117. END UpdateCacheEntry;
  118. (** Open a device: turn LED on *)
  119. PROCEDURE Open (dev: Disks.BlockDevice; VAR res: LONGINT);
  120. BEGIN
  121. Sd.SetLedState(dev(BlockDevice).card.hc, TRUE)
  122. END Open;
  123. (** Close a device: turn off LED and sync cache *)
  124. PROCEDURE Close (dev: Disks.BlockDevice; VAR res: LONGINT);
  125. VAR
  126. i: LONGINT;
  127. BEGIN
  128. WITH dev: BlockDevice DO
  129. (* Sync cache *)
  130. FOR i := 0 TO CacheSize - 1 DO
  131. IF dev.cache[i].active & dev.cache[i].mod THEN
  132. IF ~Sd.Write(dev.card, dev.cache[i].au * dev.bufferSize, dev.bufferSize * Sd.BlockSize, dev.cache[i].buffer^, 0, res) THEN RETURN END;
  133. END
  134. END;
  135. (* Turn LED off *)
  136. Sd.SetLedState(dev.card.hc, FALSE)
  137. END
  138. END Close;
  139. (** Reset SD card -- not implemented yet *)
  140. PROCEDURE Reset (dev: Disks.BlockDevice; VAR res: LONGINT);
  141. BEGIN
  142. END Reset;
  143. (** Get size of device *)
  144. PROCEDURE GetSize (dev: Disks.BlockDevice; VAR size, res: LONGINT);
  145. BEGIN
  146. size := LONGINT(dev(BlockDevice).card.csd.capacity);
  147. IF size < 0 THEN size := MAX(LONGINT) END;
  148. res := Disks.Ok
  149. END GetSize;
  150. (** Handle messages *)
  151. PROCEDURE Handle (dev: Disks.BlockDevice; msg: LONGINT; par1, par2: LONGINT; VAR res: LONGINT);
  152. BEGIN
  153. res := Disks.Ok
  154. END Handle;
  155. (** Handle SD Controller Events: create & register a new disk on card insertion, remove disk on card removal *)
  156. PROCEDURE HandleSdEvent * (card: Sd.Card; event: LONGINT; param: ANY);
  157. VAR
  158. dev, prev: BlockDevice;
  159. BEGIN
  160. CASE event OF
  161. Sd.OnInitialization:
  162. NEW(dev);
  163. InitBlockDevice(dev, card);
  164. INCL(dev.flags, Disks.Removable);
  165. Disks.Register(dev);
  166. INC(devId);
  167. dev.nextSd := devices;
  168. devices := dev;
  169. SdEnvironment.String("Disk ");
  170. SdEnvironment.String(dev.name);
  171. SdEnvironment.String(" is now available");
  172. SdEnvironment.Ln
  173. |Sd.OnRemoval:
  174. ASSERT(devices # NIL);
  175. IF devices.card = card THEN
  176. SdEnvironment.String("Removed disk ");
  177. SdEnvironment.String(devices.name);
  178. SdEnvironment.Ln;
  179. devices := devices.nextSd
  180. ELSE
  181. dev := devices;
  182. WHILE (dev # NIL) & (dev.card # card) DO
  183. prev := dev;
  184. dev := dev.nextSd
  185. END;
  186. ASSERT(dev # NIL);
  187. SdEnvironment.String("[SD] ERROR: device ");
  188. SdEnvironment.String(dev.name);
  189. SdEnvironment.String(" was removed");
  190. SdEnvironment.Ln;
  191. prev.nextSd := dev.nextSd
  192. END;
  193. END
  194. END HandleSdEvent;
  195. VAR
  196. devId: LONGINT; (** Identifier number for next SD device *)
  197. devices: BlockDevice; (** List of SD block devices *)
  198. END SdDisks.