geometry.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. // Copyright (C) 2013 Michael McMaster <michael@codesrc.com>
  2. //
  3. // This file is part of SCSI2SD.
  4. //
  5. // SCSI2SD is free software: you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation, either version 3 of the License, or
  8. // (at your option) any later version.
  9. //
  10. // SCSI2SD is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with SCSI2SD. If not, see <http://www.gnu.org/licenses/>.
  17. #include "geometry.h"
  18. #include "scsi.h"
  19. #include "sd.h"
  20. #include "config.h"
  21. #include <string.h>
  22. uint32_t getScsiCapacity(
  23. uint32_t sdSectorStart,
  24. uint16_t bytesPerSector,
  25. uint32_t scsiSectors)
  26. {
  27. uint32_t capacity =
  28. (sdDev.capacity - sdSectorStart - S2S_CFG_SIZE) /
  29. SDSectorsPerSCSISector(bytesPerSector);
  30. if (sdDev.capacity == 0)
  31. {
  32. capacity = 0;
  33. }
  34. else if (sdSectorStart >= (sdDev.capacity - S2S_CFG_SIZE))
  35. {
  36. capacity = 0;
  37. }
  38. else if (scsiSectors && (capacity > scsiSectors))
  39. {
  40. capacity = scsiSectors;
  41. }
  42. return capacity;
  43. }
  44. uint32_t SCSISector2SD(
  45. uint32_t sdSectorStart,
  46. uint16_t bytesPerSector,
  47. uint32_t scsiSector)
  48. {
  49. return scsiSector * SDSectorsPerSCSISector(bytesPerSector) + sdSectorStart;
  50. }
  51. // Standard mapping according to ECMA-107 and ISO/IEC 9293:1994
  52. // Sector always starts at 1. There is no 0 sector.
  53. uint64_t CHS2LBA(
  54. uint32_t c,
  55. uint8_t h,
  56. uint32_t s,
  57. uint16_t headsPerCylinder,
  58. uint16_t sectorsPerTrack)
  59. {
  60. return (
  61. (((uint64_t)c) * headsPerCylinder + h) *
  62. (uint64_t) sectorsPerTrack
  63. ) + (s - 1);
  64. }
  65. void LBA2CHS(
  66. uint32_t lba,
  67. uint32_t* c,
  68. uint8_t* h,
  69. uint32_t* s,
  70. uint16_t headsPerCylinder,
  71. uint16_t sectorsPerTrack)
  72. {
  73. *c = lba / (((uint32_t) sectorsPerTrack) * headsPerCylinder);
  74. *h = (lba / sectorsPerTrack) % headsPerCylinder;
  75. *s = (lba % sectorsPerTrack) + 1;
  76. }
  77. uint64_t scsiByteAddress(
  78. uint16_t bytesPerSector,
  79. uint16_t headsPerCylinder,
  80. uint16_t sectorsPerTrack,
  81. int format,
  82. const uint8_t* addr)
  83. {
  84. uint64_t result;
  85. switch (format)
  86. {
  87. case ADDRESS_BLOCK:
  88. {
  89. uint32_t lba =
  90. (((uint32_t) addr[0]) << 24) +
  91. (((uint32_t) addr[1]) << 16) +
  92. (((uint32_t) addr[2]) << 8) +
  93. addr[3];
  94. result = (uint64_t) bytesPerSector * lba;
  95. } break;
  96. case ADDRESS_PHYSICAL_BYTE:
  97. {
  98. uint32_t cyl =
  99. (((uint32_t) addr[0]) << 16) +
  100. (((uint32_t) addr[1]) << 8) +
  101. addr[2];
  102. uint8_t head = addr[3];
  103. uint32_t bytes =
  104. (((uint32_t) addr[4]) << 24) +
  105. (((uint32_t) addr[5]) << 16) +
  106. (((uint32_t) addr[6]) << 8) +
  107. addr[7];
  108. result = CHS2LBA(cyl, head, 1, headsPerCylinder, sectorsPerTrack) *
  109. (uint64_t) bytesPerSector + bytes;
  110. } break;
  111. case ADDRESS_PHYSICAL_SECTOR:
  112. {
  113. uint32_t cyl =
  114. (((uint32_t) addr[0]) << 16) +
  115. (((uint32_t) addr[1]) << 8) +
  116. addr[2];
  117. uint8_t head = scsiDev.data[3];
  118. uint32_t sector =
  119. (((uint32_t) addr[4]) << 24) +
  120. (((uint32_t) addr[5]) << 16) +
  121. (((uint32_t) addr[6]) << 8) +
  122. addr[7];
  123. result = CHS2LBA(cyl, head, sector, headsPerCylinder, sectorsPerTrack) * (uint64_t) bytesPerSector;
  124. } break;
  125. default:
  126. result = (uint64_t) -1;
  127. }
  128. return result;
  129. }
  130. void scsiSaveByteAddress(
  131. uint16_t bytesPerSector,
  132. uint16_t headsPerCylinder,
  133. uint16_t sectorsPerTrack,
  134. int format,
  135. uint64_t byteAddr,
  136. uint8_t* buf)
  137. {
  138. uint32_t lba = byteAddr / bytesPerSector;
  139. uint32_t byteOffset = byteAddr % bytesPerSector;
  140. switch (format)
  141. {
  142. case ADDRESS_BLOCK:
  143. {
  144. buf[0] = lba >> 24;
  145. buf[1] = lba >> 16;
  146. buf[2] = lba >> 8;
  147. buf[3] = lba;
  148. buf[4] = 0;
  149. buf[5] = 0;
  150. buf[6] = 0;
  151. buf[7] = 0;
  152. } break;
  153. case ADDRESS_PHYSICAL_BYTE:
  154. {
  155. uint32_t cyl;
  156. uint8_t head;
  157. uint32_t sector;
  158. uint32_t bytes;
  159. LBA2CHS(lba, &cyl, &head, &sector, headsPerCylinder, sectorsPerTrack);
  160. bytes = sector * bytesPerSector + byteOffset;
  161. buf[0] = cyl >> 16;
  162. buf[1] = cyl >> 8;
  163. buf[2] = cyl;
  164. buf[3] = head;
  165. buf[4] = bytes >> 24;
  166. buf[5] = bytes >> 16;
  167. buf[6] = bytes >> 8;
  168. buf[7] = bytes;
  169. } break;
  170. case ADDRESS_PHYSICAL_SECTOR:
  171. {
  172. uint32_t cyl;
  173. uint8_t head;
  174. uint32_t sector;
  175. LBA2CHS(lba, &cyl, &head, &sector, headsPerCylinder, sectorsPerTrack);
  176. buf[0] = cyl >> 16;
  177. buf[1] = cyl >> 8;
  178. buf[2] = cyl;
  179. buf[3] = head;
  180. buf[4] = sector >> 24;
  181. buf[5] = sector >> 16;
  182. buf[6] = sector >> 8;
  183. buf[7] = sector;
  184. } break;
  185. default:
  186. memset(buf, 0, 8);
  187. }
  188. }