You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

scsi.c 8.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*
  2. * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18. #include <stddef.h>
  19. #include <string.h>
  20. #include <byteswap.h>
  21. #include <errno.h>
  22. #include <gpxe/blockdev.h>
  23. #include <gpxe/scsi.h>
  24. /** @file
  25. *
  26. * SCSI block device
  27. *
  28. */
  29. static inline __attribute__ (( always_inline )) struct scsi_device *
  30. block_to_scsi ( struct block_device *blockdev ) {
  31. return container_of ( blockdev, struct scsi_device, blockdev );
  32. }
  33. /**
  34. * Issue SCSI command
  35. *
  36. * @v scsi SCSI device
  37. * @v command SCSI command
  38. * @ret rc Return status code
  39. */
  40. static int scsi_command ( struct scsi_device *scsi,
  41. struct scsi_command *command ) {
  42. int rc;
  43. /* Clear sense response code before issuing command */
  44. command->sense_response = 0;
  45. /* Issue SCSI command */
  46. if ( ( rc = scsi->command ( scsi, command ) ) != 0 ) {
  47. /* Something went wrong with the issuing mechanism,
  48. * (rather than with the command itself)
  49. */
  50. DBG ( "SCSI %p " SCSI_CDB_FORMAT " err %d\n",
  51. scsi, SCSI_CDB_DATA ( command->cdb ), rc );
  52. return rc;
  53. }
  54. /* Check for SCSI errors */
  55. if ( command->status != 0 ) {
  56. DBG ( "SCSI %p " SCSI_CDB_FORMAT " status %02x sense %02x\n",
  57. scsi, SCSI_CDB_DATA ( command->cdb ),
  58. command->status, command->sense_response );
  59. return -EIO;
  60. }
  61. return 0;
  62. }
  63. /**
  64. * Read block from SCSI device using READ (10)
  65. *
  66. * @v blockdev Block device
  67. * @v block LBA block number
  68. * @v count Block count
  69. * @v buffer Data buffer
  70. * @ret rc Return status code
  71. */
  72. static int scsi_read_10 ( struct block_device *blockdev, uint64_t block,
  73. unsigned long count, userptr_t buffer ) {
  74. struct scsi_device *scsi = block_to_scsi ( blockdev );
  75. struct scsi_command command;
  76. struct scsi_cdb_read_10 *cdb = &command.cdb.read10;
  77. /* Issue READ (10) */
  78. memset ( &command, 0, sizeof ( command ) );
  79. cdb->opcode = SCSI_OPCODE_READ_10;
  80. cdb->lba = cpu_to_be32 ( block );
  81. cdb->len = cpu_to_be16 ( count );
  82. command.data_in = buffer;
  83. command.data_in_len = ( count * blockdev->blksize );
  84. return scsi_command ( scsi, &command );
  85. }
  86. /**
  87. * Read block from SCSI device using READ (16)
  88. *
  89. * @v blockdev Block device
  90. * @v block LBA block number
  91. * @v count Block count
  92. * @v buffer Data buffer
  93. * @ret rc Return status code
  94. */
  95. static int scsi_read_16 ( struct block_device *blockdev, uint64_t block,
  96. unsigned long count, userptr_t buffer ) {
  97. struct scsi_device *scsi = block_to_scsi ( blockdev );
  98. struct scsi_command command;
  99. struct scsi_cdb_read_16 *cdb = &command.cdb.read16;
  100. /* Issue READ (16) */
  101. memset ( &command, 0, sizeof ( command ) );
  102. cdb->opcode = SCSI_OPCODE_READ_16;
  103. cdb->lba = cpu_to_be64 ( block );
  104. cdb->len = cpu_to_be32 ( count );
  105. command.data_in = buffer;
  106. command.data_in_len = ( count * blockdev->blksize );
  107. return scsi_command ( scsi, &command );
  108. }
  109. /**
  110. * Write block to SCSI device using WRITE (10)
  111. *
  112. * @v blockdev Block device
  113. * @v block LBA block number
  114. * @v count Block count
  115. * @v buffer Data buffer
  116. * @ret rc Return status code
  117. */
  118. static int scsi_write_10 ( struct block_device *blockdev, uint64_t block,
  119. unsigned long count, userptr_t buffer ) {
  120. struct scsi_device *scsi = block_to_scsi ( blockdev );
  121. struct scsi_command command;
  122. struct scsi_cdb_write_10 *cdb = &command.cdb.write10;
  123. /* Issue WRITE (10) */
  124. memset ( &command, 0, sizeof ( command ) );
  125. cdb->opcode = SCSI_OPCODE_WRITE_10;
  126. cdb->lba = cpu_to_be32 ( block );
  127. cdb->len = cpu_to_be16 ( count );
  128. command.data_out = buffer;
  129. command.data_out_len = ( count * blockdev->blksize );
  130. return scsi_command ( scsi, &command );
  131. }
  132. /**
  133. * Write block to SCSI device using WRITE (16)
  134. *
  135. * @v blockdev Block device
  136. * @v block LBA block number
  137. * @v count Block count
  138. * @v buffer Data buffer
  139. * @ret rc Return status code
  140. */
  141. static int scsi_write_16 ( struct block_device *blockdev, uint64_t block,
  142. unsigned long count, userptr_t buffer ) {
  143. struct scsi_device *scsi = block_to_scsi ( blockdev );
  144. struct scsi_command command;
  145. struct scsi_cdb_write_16 *cdb = &command.cdb.write16;
  146. /* Issue WRITE (16) */
  147. memset ( &command, 0, sizeof ( command ) );
  148. cdb->opcode = SCSI_OPCODE_WRITE_16;
  149. cdb->lba = cpu_to_be64 ( block );
  150. cdb->len = cpu_to_be32 ( count );
  151. command.data_out = buffer;
  152. command.data_out_len = ( count * blockdev->blksize );
  153. return scsi_command ( scsi, &command );
  154. }
  155. /**
  156. * Read capacity of SCSI device via READ CAPACITY (10)
  157. *
  158. * @v blockdev Block device
  159. * @ret rc Return status code
  160. */
  161. static int scsi_read_capacity_10 ( struct block_device *blockdev ) {
  162. struct scsi_device *scsi = block_to_scsi ( blockdev );
  163. struct scsi_command command;
  164. struct scsi_cdb_read_capacity_10 *cdb = &command.cdb.readcap10;
  165. struct scsi_capacity_10 capacity;
  166. int rc;
  167. /* Issue READ CAPACITY (10) */
  168. memset ( &command, 0, sizeof ( command ) );
  169. cdb->opcode = SCSI_OPCODE_READ_CAPACITY_10;
  170. command.data_in = virt_to_user ( &capacity );
  171. command.data_in_len = sizeof ( capacity );
  172. if ( ( rc = scsi_command ( scsi, &command ) ) != 0 )
  173. return rc;
  174. /* Fill in block device fields */
  175. blockdev->blksize = be32_to_cpu ( capacity.blksize );
  176. blockdev->blocks = ( be32_to_cpu ( capacity.lba ) + 1 );
  177. return 0;
  178. }
  179. /**
  180. * Read capacity of SCSI device via READ CAPACITY (16)
  181. *
  182. * @v blockdev Block device
  183. * @ret rc Return status code
  184. */
  185. static int scsi_read_capacity_16 ( struct block_device *blockdev ) {
  186. struct scsi_device *scsi = block_to_scsi ( blockdev );
  187. struct scsi_command command;
  188. struct scsi_cdb_read_capacity_16 *cdb = &command.cdb.readcap16;
  189. struct scsi_capacity_16 capacity;
  190. int rc;
  191. /* Issue READ CAPACITY (16) */
  192. memset ( &command, 0, sizeof ( command ) );
  193. cdb->opcode = SCSI_OPCODE_SERVICE_ACTION_IN;
  194. cdb->service_action = SCSI_SERVICE_ACTION_READ_CAPACITY_16;
  195. cdb->len = cpu_to_be32 ( sizeof ( capacity ) );
  196. command.data_in = virt_to_user ( &capacity );
  197. command.data_in_len = sizeof ( capacity );
  198. if ( ( rc = scsi_command ( scsi, &command ) ) != 0 )
  199. return rc;
  200. /* Fill in block device fields */
  201. blockdev->blksize = be32_to_cpu ( capacity.blksize );
  202. blockdev->blocks = ( be64_to_cpu ( capacity.lba ) + 1 );
  203. return 0;
  204. }
  205. /**
  206. * Initialise SCSI device
  207. *
  208. * @v scsi SCSI device
  209. * @ret rc Return status code
  210. *
  211. * Initialises a SCSI device. The scsi_device::command and
  212. * scsi_device::lun fields must already be filled in. This function
  213. * will configure scsi_device::blockdev, including issuing a READ
  214. * CAPACITY call to determine the block size and total device size.
  215. */
  216. int init_scsidev ( struct scsi_device *scsi ) {
  217. int rc;
  218. /* Issue a theoretically extraneous READ CAPACITY (10)
  219. * command, solely in order to draw out the "CHECK CONDITION
  220. * (power-on occurred)" that some dumb targets insist on
  221. * sending as an error at start of day.
  222. */
  223. scsi_read_capacity_10 ( &scsi->blockdev );
  224. /* Try READ CAPACITY (10), which is a mandatory command, first. */
  225. scsi->blockdev.read = scsi_read_10;
  226. scsi->blockdev.write = scsi_write_10;
  227. if ( ( rc = scsi_read_capacity_10 ( &scsi->blockdev ) ) != 0 )
  228. return rc;
  229. /* If capacity range was exceeded (i.e. capacity.lba was
  230. * 0xffffffff, meaning that blockdev->blocks is now zero), use
  231. * READ CAPACITY (16) instead. READ CAPACITY (16) is not
  232. * mandatory, so we can't just use it straight off.
  233. */
  234. if ( scsi->blockdev.blocks == 0 ) {
  235. scsi->blockdev.read = scsi_read_16;
  236. scsi->blockdev.write = scsi_write_16;
  237. if ( ( rc = scsi_read_capacity_16 ( &scsi->blockdev ) ) != 0 )
  238. return rc;
  239. }
  240. return 0;
  241. }