Mirror of CollapseOS
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

303 lignes
6.2KB

  1. ; blockdev
  2. ;
  3. ; A block device is an abstraction over something we can read from, write to.
  4. ;
  5. ; A device that fits this abstraction puts the proper hook into itself, and then
  6. ; the glue code assigns a blockdev ID to that device. It then becomes easy to
  7. ; access arbitrary devices in a convenient manner.
  8. ;
  9. ; This module exposes a seek/tell/getb/putb API that is then re-routed to
  10. ; underlying drivers. There will eventually be more than one driver type, but
  11. ; for now we sit on only one type of driver: random access driver.
  12. ;
  13. ; *** Random access drivers ***
  14. ;
  15. ; Random access drivers are expected to supply two routines: GetB and PutB.
  16. ;
  17. ; GetB:
  18. ; Reads one byte at address specified in DE/HL and returns its value in A.
  19. ; Sets Z according to whether read was successful: Set if successful, unset
  20. ; if not.
  21. ;
  22. ; Unsuccessful reads generally mean that requested addr is out of bounds (we
  23. ; reached EOF).
  24. ;
  25. ; PutB:
  26. ; Writes byte in A at address specified in DE/HL. Sets Z according to whether
  27. ; the operation was successful.
  28. ;
  29. ; Unsuccessful writes generally mean that we're out of bounds for writing.
  30. ;
  31. ; All routines are expected to preserve unused registers except IX which is
  32. ; explicitly protected during GetB/PutB calls. This makes quick "handle+jump"
  33. ; definitions possible.
  34. ; *** DEFINES ***
  35. ; BLOCKDEV_COUNT: The number of devices we manage.
  36. ; *** CONSTS ***
  37. ; *** VARIABLES ***
  38. ; Pointer to the selected block device. A block device is a 8 bytes block of
  39. ; memory with pointers to GetB, PutB, and a 32-bit counter, in that order.
  40. .equ BLOCKDEV_SEL BLOCKDEV_RAMSTART
  41. .equ BLOCKDEV_RAMEND @+BLOCKDEV_SIZE
  42. ; *** CODE ***
  43. ; Put the pointer to the "regular" blkdev selection in DE
  44. blkSelPtr:
  45. ld de, BLOCKDEV_SEL
  46. ; Select block index specified in A and place them in routine pointers at (DE).
  47. ; For example, for a "regular" blkSel, you will want to set DE to BLOCKDEV_SEL.
  48. ; Sets Z on success, reset on error.
  49. ; If A >= BLOCKDEV_COUNT, it's an error.
  50. blkSel:
  51. cp BLOCKDEV_COUNT
  52. jp nc, unsetZ ; if selection >= device count, error
  53. push af
  54. push de
  55. push hl
  56. ld hl, blkDevTbl
  57. or a ; cp 0
  58. jr z, .end ; index is zero? don't loop
  59. push bc ; <|
  60. ld b, a ; |
  61. .loop: ; |
  62. ld a, 4 ; |
  63. call addHL ; |
  64. djnz .loop ; |
  65. pop bc ; <|
  66. .end:
  67. call blkSet
  68. pop hl
  69. pop de
  70. pop af
  71. cp a ; ensure Z
  72. ret
  73. ; Setup blkdev handle in (DE) using routines at (HL).
  74. blkSet:
  75. push af
  76. push de
  77. push hl
  78. push bc
  79. ld bc, 4
  80. ldir
  81. ; Initialize pos
  82. ld b, 4
  83. xor a
  84. ex de, hl
  85. call fill
  86. pop bc
  87. pop hl
  88. pop de
  89. pop af
  90. ret
  91. _blkInc:
  92. ret nz ; don't advance when in error condition
  93. push af
  94. push hl
  95. ld a, BLOCKDEV_SEEK_FORWARD
  96. ld hl, 1
  97. call _blkSeek
  98. pop hl
  99. pop af
  100. ret
  101. ; Reads one byte from selected device and returns its value in A.
  102. ; Sets Z according to whether read was successful: Set if successful, unset
  103. ; if not.
  104. blkGetB:
  105. push ix
  106. ld ix, BLOCKDEV_SEL
  107. call _blkGetB
  108. pop ix
  109. ret
  110. _blkGetB:
  111. push hl
  112. push de
  113. call _blkTell
  114. call callIXI
  115. pop de
  116. pop hl
  117. jr _blkInc ; advance and return
  118. ; Writes byte in A in current position in the selected device. Sets Z according
  119. ; to whether the operation was successful.
  120. blkPutB:
  121. push ix
  122. ld ix, BLOCKDEV_SEL
  123. call _blkPutB
  124. pop ix
  125. ret
  126. _blkPutB:
  127. push ix
  128. push hl
  129. push de
  130. call _blkTell
  131. inc ix ; make IX point to PutB
  132. inc ix
  133. call callIXI
  134. pop de
  135. pop hl
  136. pop ix
  137. jr _blkInc ; advance and return
  138. ; Reads B chars from blkGetB and copy them in (HL).
  139. ; Sets Z if successful, unset Z if there was an error.
  140. blkRead:
  141. push ix
  142. ld ix, BLOCKDEV_SEL
  143. call _blkRead
  144. pop ix
  145. ret
  146. _blkRead:
  147. push hl
  148. push bc
  149. .loop:
  150. call _blkGetB
  151. jr nz, .end ; Z already unset
  152. ld (hl), a
  153. inc hl
  154. djnz .loop
  155. cp a ; ensure Z
  156. .end:
  157. pop bc
  158. pop hl
  159. ret
  160. ; Writes B chars to blkPutB from (HL).
  161. ; Sets Z if successful, unset Z if there was an error.
  162. blkWrite:
  163. push ix
  164. ld ix, BLOCKDEV_SEL
  165. call _blkWrite
  166. pop ix
  167. ret
  168. _blkWrite:
  169. push hl
  170. push bc
  171. .loop:
  172. ld a, (hl)
  173. call _blkPutB
  174. jr nz, .end ; Z already unset
  175. inc hl
  176. djnz .loop
  177. cp a ; ensure Z
  178. .end:
  179. pop bc
  180. pop hl
  181. ret
  182. ; Seeks the block device in one of 5 modes, which is the A argument:
  183. ; 0 : Move exactly to X, X being the HL/DE argument.
  184. ; 1 : Move forward by X bytes, X being the HL argument (no DE)
  185. ; 2 : Move backwards by X bytes, X being the HL argument (no DE)
  186. ; 3 : Move to the end
  187. ; 4 : Move to the beginning
  188. ; Set position of selected device to the value specified in HL (low) and DE
  189. ; (high). DE is only used for mode 0.
  190. ;
  191. ; When seeking to an out-of-bounds position, the resulting position will be
  192. ; one position ahead of the last valid position. Therefore, GetB after a seek
  193. ; to end would always fail.
  194. ;
  195. ; If the device is "growable", it's possible that seeking to end when calling
  196. ; PutB doesn't necessarily result in a failure.
  197. blkSeek:
  198. push ix
  199. ld ix, BLOCKDEV_SEL
  200. call _blkSeek
  201. pop ix
  202. ret
  203. _blkSeek:
  204. cp BLOCKDEV_SEEK_FORWARD
  205. jr z, .forward
  206. cp BLOCKDEV_SEEK_BACKWARD
  207. jr z, .backward
  208. cp BLOCKDEV_SEEK_BEGINNING
  209. jr z, .beginning
  210. cp BLOCKDEV_SEEK_END
  211. jr z, .end
  212. ; all other modes are considered absolute
  213. ld (ix+4), e
  214. ld (ix+5), d
  215. ld (ix+6), l
  216. ld (ix+7), h
  217. ret
  218. .forward:
  219. push bc ; <-|
  220. push hl ; <||
  221. ld l, (ix+6) ; || low byte
  222. ld h, (ix+7) ; ||
  223. pop bc ; <||
  224. add hl, bc ; |
  225. pop bc ; <-|
  226. ld (ix+6), l
  227. ld (ix+7), h
  228. ret nc ; no carry? no need to adjust high byte
  229. ; carry, adjust high byte
  230. inc (ix+4)
  231. ret nz
  232. inc (ix+5)
  233. ret
  234. .backward:
  235. and a ; clear carry
  236. push bc ; <-|
  237. push hl ; <||
  238. ld l, (ix+6) ; || low byte
  239. ld h, (ix+7) ; ||
  240. pop bc ; <||
  241. sbc hl, bc ; |
  242. pop bc ; <-|
  243. ld (ix+6), l
  244. ld (ix+7), h
  245. ret nc ; no carry? no need to adjust high byte
  246. ld a, 0xff
  247. dec (ix+4)
  248. cp (ix+4)
  249. ret nz
  250. ; we decremented from 0
  251. dec (ix+5)
  252. ret
  253. .beginning:
  254. xor a
  255. ld (ix+4), a
  256. ld (ix+5), a
  257. ld (ix+6), a
  258. ld (ix+7), a
  259. ret
  260. .end:
  261. ld a, 0xff
  262. ld (ix+4), a
  263. ld (ix+5), a
  264. ld (ix+6), a
  265. ld (ix+7), a
  266. ret
  267. ; Returns the current position of the selected device in HL (low) and DE (high).
  268. blkTell:
  269. push ix
  270. ld ix, BLOCKDEV_SEL
  271. call _blkTell
  272. pop ix
  273. ret
  274. _blkTell:
  275. ld e, (ix+4)
  276. ld d, (ix+5)
  277. ld l, (ix+6)
  278. ld h, (ix+7)
  279. ret
  280. ; This label is at the end of the file on purpose: the glue file should include
  281. ; a list of device routine table entries just after the include. Each line
  282. ; has 2 word addresses: GetB and PutB. An entry could look like:
  283. ; .dw mmapGetB, mmapPutB
  284. blkDevTbl: