2
0

scsi.h 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. #ifndef QEMU_HW_SCSI_H
  2. #define QEMU_HW_SCSI_H
  3. #include "qdev.h"
  4. #include "block/block.h"
  5. #include "hw/block-common.h"
  6. #include "sysemu/sysemu.h"
  7. #define MAX_SCSI_DEVS 255
  8. #define SCSI_CMD_BUF_SIZE 16
  9. typedef struct SCSIBus SCSIBus;
  10. typedef struct SCSIBusInfo SCSIBusInfo;
  11. typedef struct SCSICommand SCSICommand;
  12. typedef struct SCSIDevice SCSIDevice;
  13. typedef struct SCSIRequest SCSIRequest;
  14. typedef struct SCSIReqOps SCSIReqOps;
  15. enum SCSIXferMode {
  16. SCSI_XFER_NONE, /* TEST_UNIT_READY, ... */
  17. SCSI_XFER_FROM_DEV, /* READ, INQUIRY, MODE_SENSE, ... */
  18. SCSI_XFER_TO_DEV, /* WRITE, MODE_SELECT, ... */
  19. };
  20. typedef struct SCSISense {
  21. uint8_t key;
  22. uint8_t asc;
  23. uint8_t ascq;
  24. } SCSISense;
  25. #define SCSI_SENSE_BUF_SIZE 96
  26. struct SCSICommand {
  27. uint8_t buf[SCSI_CMD_BUF_SIZE];
  28. int len;
  29. size_t xfer;
  30. uint64_t lba;
  31. enum SCSIXferMode mode;
  32. };
  33. struct SCSIRequest {
  34. SCSIBus *bus;
  35. SCSIDevice *dev;
  36. const SCSIReqOps *ops;
  37. uint32_t refcount;
  38. uint32_t tag;
  39. uint32_t lun;
  40. uint32_t status;
  41. size_t resid;
  42. SCSICommand cmd;
  43. BlockDriverAIOCB *aiocb;
  44. QEMUSGList *sg;
  45. bool dma_started;
  46. uint8_t sense[SCSI_SENSE_BUF_SIZE];
  47. uint32_t sense_len;
  48. bool enqueued;
  49. bool io_canceled;
  50. bool retry;
  51. void *hba_private;
  52. QTAILQ_ENTRY(SCSIRequest) next;
  53. };
  54. #define TYPE_SCSI_DEVICE "scsi-device"
  55. #define SCSI_DEVICE(obj) \
  56. OBJECT_CHECK(SCSIDevice, (obj), TYPE_SCSI_DEVICE)
  57. #define SCSI_DEVICE_CLASS(klass) \
  58. OBJECT_CLASS_CHECK(SCSIDeviceClass, (klass), TYPE_SCSI_DEVICE)
  59. #define SCSI_DEVICE_GET_CLASS(obj) \
  60. OBJECT_GET_CLASS(SCSIDeviceClass, (obj), TYPE_SCSI_DEVICE)
  61. typedef struct SCSIDeviceClass {
  62. DeviceClass parent_class;
  63. int (*init)(SCSIDevice *dev);
  64. void (*destroy)(SCSIDevice *s);
  65. SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun,
  66. uint8_t *buf, void *hba_private);
  67. void (*unit_attention_reported)(SCSIDevice *s);
  68. } SCSIDeviceClass;
  69. struct SCSIDevice
  70. {
  71. DeviceState qdev;
  72. VMChangeStateEntry *vmsentry;
  73. QEMUBH *bh;
  74. uint32_t id;
  75. BlockConf conf;
  76. SCSISense unit_attention;
  77. bool sense_is_ua;
  78. uint8_t sense[SCSI_SENSE_BUF_SIZE];
  79. uint32_t sense_len;
  80. QTAILQ_HEAD(, SCSIRequest) requests;
  81. uint32_t channel;
  82. uint32_t lun;
  83. int blocksize;
  84. int type;
  85. uint64_t max_lba;
  86. };
  87. extern const VMStateDescription vmstate_scsi_device;
  88. #define VMSTATE_SCSI_DEVICE(_field, _state) { \
  89. .name = (stringify(_field)), \
  90. .size = sizeof(SCSIDevice), \
  91. .vmsd = &vmstate_scsi_device, \
  92. .flags = VMS_STRUCT, \
  93. .offset = vmstate_offset_value(_state, _field, SCSIDevice), \
  94. }
  95. /* cdrom.c */
  96. int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);
  97. int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num);
  98. /* scsi-bus.c */
  99. struct SCSIReqOps {
  100. size_t size;
  101. void (*free_req)(SCSIRequest *req);
  102. int32_t (*send_command)(SCSIRequest *req, uint8_t *buf);
  103. void (*read_data)(SCSIRequest *req);
  104. void (*write_data)(SCSIRequest *req);
  105. void (*cancel_io)(SCSIRequest *req);
  106. uint8_t *(*get_buf)(SCSIRequest *req);
  107. void (*save_request)(QEMUFile *f, SCSIRequest *req);
  108. void (*load_request)(QEMUFile *f, SCSIRequest *req);
  109. };
  110. struct SCSIBusInfo {
  111. int tcq;
  112. int max_channel, max_target, max_lun;
  113. void (*transfer_data)(SCSIRequest *req, uint32_t arg);
  114. void (*complete)(SCSIRequest *req, uint32_t arg, size_t resid);
  115. void (*cancel)(SCSIRequest *req);
  116. void (*hotplug)(SCSIBus *bus, SCSIDevice *dev);
  117. void (*hot_unplug)(SCSIBus *bus, SCSIDevice *dev);
  118. void (*change)(SCSIBus *bus, SCSIDevice *dev, SCSISense sense);
  119. QEMUSGList *(*get_sg_list)(SCSIRequest *req);
  120. void (*save_request)(QEMUFile *f, SCSIRequest *req);
  121. void *(*load_request)(QEMUFile *f, SCSIRequest *req);
  122. void (*free_request)(SCSIBus *bus, void *priv);
  123. };
  124. #define TYPE_SCSI_BUS "SCSI"
  125. #define SCSI_BUS(obj) OBJECT_CHECK(SCSIBus, (obj), TYPE_SCSI_BUS)
  126. struct SCSIBus {
  127. BusState qbus;
  128. int busnr;
  129. SCSISense unit_attention;
  130. const SCSIBusInfo *info;
  131. };
  132. void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info);
  133. static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
  134. {
  135. return DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus);
  136. }
  137. SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
  138. int unit, bool removable, int bootindex);
  139. int scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
  140. /*
  141. * Predefined sense codes
  142. */
  143. /* No sense data available */
  144. extern const struct SCSISense sense_code_NO_SENSE;
  145. /* LUN not ready, Manual intervention required */
  146. extern const struct SCSISense sense_code_LUN_NOT_READY;
  147. /* LUN not ready, Medium not present */
  148. extern const struct SCSISense sense_code_NO_MEDIUM;
  149. /* LUN not ready, medium removal prevented */
  150. extern const struct SCSISense sense_code_NOT_READY_REMOVAL_PREVENTED;
  151. /* Hardware error, internal target failure */
  152. extern const struct SCSISense sense_code_TARGET_FAILURE;
  153. /* Illegal request, invalid command operation code */
  154. extern const struct SCSISense sense_code_INVALID_OPCODE;
  155. /* Illegal request, LBA out of range */
  156. extern const struct SCSISense sense_code_LBA_OUT_OF_RANGE;
  157. /* Illegal request, Invalid field in CDB */
  158. extern const struct SCSISense sense_code_INVALID_FIELD;
  159. /* Illegal request, Invalid field in parameter list */
  160. extern const struct SCSISense sense_code_INVALID_PARAM;
  161. /* Illegal request, Parameter list length error */
  162. extern const struct SCSISense sense_code_INVALID_PARAM_LEN;
  163. /* Illegal request, LUN not supported */
  164. extern const struct SCSISense sense_code_LUN_NOT_SUPPORTED;
  165. /* Illegal request, Saving parameters not supported */
  166. extern const struct SCSISense sense_code_SAVING_PARAMS_NOT_SUPPORTED;
  167. /* Illegal request, Incompatible format */
  168. extern const struct SCSISense sense_code_INCOMPATIBLE_FORMAT;
  169. /* Illegal request, medium removal prevented */
  170. extern const struct SCSISense sense_code_ILLEGAL_REQ_REMOVAL_PREVENTED;
  171. /* Command aborted, I/O process terminated */
  172. extern const struct SCSISense sense_code_IO_ERROR;
  173. /* Command aborted, I_T Nexus loss occurred */
  174. extern const struct SCSISense sense_code_I_T_NEXUS_LOSS;
  175. /* Command aborted, Logical Unit failure */
  176. extern const struct SCSISense sense_code_LUN_FAILURE;
  177. /* LUN not ready, Capacity data has changed */
  178. extern const struct SCSISense sense_code_CAPACITY_CHANGED;
  179. /* LUN not ready, Medium not present */
  180. extern const struct SCSISense sense_code_UNIT_ATTENTION_NO_MEDIUM;
  181. /* Unit attention, Power on, reset or bus device reset occurred */
  182. extern const struct SCSISense sense_code_RESET;
  183. /* Unit attention, Medium may have changed*/
  184. extern const struct SCSISense sense_code_MEDIUM_CHANGED;
  185. /* Unit attention, Reported LUNs data has changed */
  186. extern const struct SCSISense sense_code_REPORTED_LUNS_CHANGED;
  187. /* Unit attention, Device internal reset */
  188. extern const struct SCSISense sense_code_DEVICE_INTERNAL_RESET;
  189. /* Data Protection, Write Protected */
  190. extern const struct SCSISense sense_code_WRITE_PROTECTED;
  191. #define SENSE_CODE(x) sense_code_ ## x
  192. uint32_t scsi_data_cdb_length(uint8_t *buf);
  193. uint32_t scsi_cdb_length(uint8_t *buf);
  194. int scsi_sense_valid(SCSISense sense);
  195. int scsi_build_sense(uint8_t *in_buf, int in_len,
  196. uint8_t *buf, int len, bool fixed);
  197. SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
  198. uint32_t tag, uint32_t lun, void *hba_private);
  199. SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
  200. uint8_t *buf, void *hba_private);
  201. int32_t scsi_req_enqueue(SCSIRequest *req);
  202. void scsi_req_free(SCSIRequest *req);
  203. SCSIRequest *scsi_req_ref(SCSIRequest *req);
  204. void scsi_req_unref(SCSIRequest *req);
  205. void scsi_req_build_sense(SCSIRequest *req, SCSISense sense);
  206. void scsi_req_print(SCSIRequest *req);
  207. void scsi_req_continue(SCSIRequest *req);
  208. void scsi_req_data(SCSIRequest *req, int len);
  209. void scsi_req_complete(SCSIRequest *req, int status);
  210. uint8_t *scsi_req_get_buf(SCSIRequest *req);
  211. int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len);
  212. void scsi_req_abort(SCSIRequest *req, int status);
  213. void scsi_req_cancel(SCSIRequest *req);
  214. void scsi_req_retry(SCSIRequest *req);
  215. void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense);
  216. void scsi_device_set_ua(SCSIDevice *sdev, SCSISense sense);
  217. void scsi_device_report_change(SCSIDevice *dev, SCSISense sense);
  218. int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed);
  219. SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun);
  220. /* scsi-generic.c. */
  221. extern const SCSIReqOps scsi_generic_req_ops;
  222. #endif