PageRenderTime 44ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/pc-bios/s390-ccw/virtio-scsi.c

https://github.com/mstsirkin/qemu
C | 418 lines | 321 code | 65 blank | 32 comment | 48 complexity | 94012bd577953119fe9265857c95006c MD5 | raw file
  1. /*
  2. * Virtio-SCSI implementation for s390 machine loader for qemu
  3. *
  4. * Copyright 2015 IBM Corp.
  5. * Author: Eugene "jno" Dvurechenski <jno@linux.vnet.ibm.com>
  6. *
  7. * This work is licensed under the terms of the GNU GPL, version 2 or (at
  8. * your option) any later version. See the COPYING file in the top-level
  9. * directory.
  10. */
  11. #include "libc.h"
  12. #include "s390-ccw.h"
  13. #include "virtio.h"
  14. #include "scsi.h"
  15. #include "virtio-scsi.h"
  16. static ScsiDevice default_scsi_device;
  17. static VirtioScsiCmdReq req;
  18. static VirtioScsiCmdResp resp;
  19. static uint8_t scsi_inquiry_std_response[256];
  20. static ScsiInquiryEvpdPages scsi_inquiry_evpd_pages_response;
  21. static ScsiInquiryEvpdBl scsi_inquiry_evpd_bl_response;
  22. static inline void vs_assert(bool term, const char **msgs)
  23. {
  24. if (!term) {
  25. int i = 0;
  26. sclp_print("\n! ");
  27. while (msgs[i]) {
  28. sclp_print(msgs[i++]);
  29. }
  30. panic(" !\n");
  31. }
  32. }
  33. static void virtio_scsi_verify_response(VirtioScsiCmdResp *resp,
  34. const char *title)
  35. {
  36. const char *mr[] = {
  37. title, ": response ", virtio_scsi_response_msg(resp), 0
  38. };
  39. const char *ms[] = {
  40. title,
  41. CDB_STATUS_VALID(resp->status) ? ": " : ": invalid ",
  42. scsi_cdb_status_msg(resp->status),
  43. resp->status == CDB_STATUS_CHECK_CONDITION ? " " : 0,
  44. resp->sense_len ? scsi_cdb_asc_msg(resp->sense)
  45. : "no sense data",
  46. scsi_sense_response(resp->sense) == 0x70 ? ", sure" : "?",
  47. 0
  48. };
  49. vs_assert(resp->response == VIRTIO_SCSI_S_OK, mr);
  50. vs_assert(resp->status == CDB_STATUS_GOOD, ms);
  51. }
  52. static void prepare_request(VDev *vdev, const void *cdb, int cdb_size,
  53. void *data, uint32_t data_size)
  54. {
  55. const ScsiDevice *sdev = vdev->scsi_device;
  56. memset(&req, 0, sizeof(req));
  57. req.lun = make_lun(sdev->channel, sdev->target, sdev->lun);
  58. memcpy(&req.cdb, cdb, cdb_size);
  59. memset(&resp, 0, sizeof(resp));
  60. resp.status = 0xff; /* set invalid */
  61. resp.response = 0xff; /* */
  62. if (data && data_size) {
  63. memset(data, 0, data_size);
  64. }
  65. }
  66. static inline void vs_io_assert(bool term, const char *msg)
  67. {
  68. if (!term) {
  69. virtio_scsi_verify_response(&resp, msg);
  70. }
  71. }
  72. static void vs_run(const char *title, VirtioCmd *cmd, VDev *vdev,
  73. const void *cdb, int cdb_size,
  74. void *data, uint32_t data_size)
  75. {
  76. prepare_request(vdev, cdb, cdb_size, data, data_size);
  77. vs_io_assert(virtio_run(vdev, VR_REQUEST, cmd) == 0, title);
  78. }
  79. /* SCSI protocol implementation routines */
  80. static bool scsi_inquiry(VDev *vdev, uint8_t evpd, uint8_t page,
  81. void *data, uint32_t data_size)
  82. {
  83. ScsiCdbInquiry cdb = {
  84. .command = 0x12,
  85. .b1 = evpd,
  86. .b2 = page,
  87. .alloc_len = data_size < 65535 ? data_size : 65535,
  88. };
  89. VirtioCmd inquiry[] = {
  90. { &req, sizeof(req), VRING_DESC_F_NEXT },
  91. { &resp, sizeof(resp), VRING_DESC_F_WRITE | VRING_DESC_F_NEXT },
  92. { data, data_size, VRING_DESC_F_WRITE },
  93. };
  94. vs_run("inquiry", inquiry, vdev, &cdb, sizeof(cdb), data, data_size);
  95. return virtio_scsi_response_ok(&resp);
  96. }
  97. static bool scsi_test_unit_ready(VDev *vdev)
  98. {
  99. ScsiCdbTestUnitReady cdb = {
  100. .command = 0x00,
  101. };
  102. VirtioCmd test_unit_ready[] = {
  103. { &req, sizeof(req), VRING_DESC_F_NEXT },
  104. { &resp, sizeof(resp), VRING_DESC_F_WRITE },
  105. };
  106. prepare_request(vdev, &cdb, sizeof(cdb), 0, 0);
  107. virtio_run(vdev, VR_REQUEST, test_unit_ready); /* ignore errors here */
  108. return virtio_scsi_response_ok(&resp);
  109. }
  110. static bool scsi_report_luns(VDev *vdev, void *data, uint32_t data_size)
  111. {
  112. ScsiCdbReportLuns cdb = {
  113. .command = 0xa0,
  114. .select_report = 0x02, /* REPORT ALL */
  115. .alloc_len = data_size,
  116. };
  117. VirtioCmd report_luns[] = {
  118. { &req, sizeof(req), VRING_DESC_F_NEXT },
  119. { &resp, sizeof(resp), VRING_DESC_F_WRITE | VRING_DESC_F_NEXT },
  120. { data, data_size, VRING_DESC_F_WRITE },
  121. };
  122. vs_run("report luns", report_luns,
  123. vdev, &cdb, sizeof(cdb), data, data_size);
  124. return virtio_scsi_response_ok(&resp);
  125. }
  126. static bool scsi_read_10(VDev *vdev,
  127. ulong sector, int sectors, void *data,
  128. unsigned int data_size)
  129. {
  130. ScsiCdbRead10 cdb = {
  131. .command = 0x28,
  132. .lba = sector,
  133. .xfer_length = sectors,
  134. };
  135. VirtioCmd read_10[] = {
  136. { &req, sizeof(req), VRING_DESC_F_NEXT },
  137. { &resp, sizeof(resp), VRING_DESC_F_WRITE | VRING_DESC_F_NEXT },
  138. { data, data_size, VRING_DESC_F_WRITE },
  139. };
  140. debug_print_int("read_10 sector", sector);
  141. debug_print_int("read_10 sectors", sectors);
  142. vs_run("read(10)", read_10, vdev, &cdb, sizeof(cdb), data, data_size);
  143. return virtio_scsi_response_ok(&resp);
  144. }
  145. static bool scsi_read_capacity(VDev *vdev,
  146. void *data, uint32_t data_size)
  147. {
  148. ScsiCdbReadCapacity16 cdb = {
  149. .command = 0x9e, /* SERVICE_ACTION_IN_16 */
  150. .service_action = 0x10, /* SA_READ_CAPACITY */
  151. .alloc_len = data_size,
  152. };
  153. VirtioCmd read_capacity_16[] = {
  154. { &req, sizeof(req), VRING_DESC_F_NEXT },
  155. { &resp, sizeof(resp), VRING_DESC_F_WRITE | VRING_DESC_F_NEXT },
  156. { data, data_size, VRING_DESC_F_WRITE },
  157. };
  158. vs_run("read capacity", read_capacity_16,
  159. vdev, &cdb, sizeof(cdb), data, data_size);
  160. return virtio_scsi_response_ok(&resp);
  161. }
  162. /* virtio-scsi routines */
  163. static void virtio_scsi_locate_device(VDev *vdev)
  164. {
  165. const uint16_t channel = 0; /* again, it's what QEMU does */
  166. uint16_t target;
  167. static uint8_t data[16 + 8 * 63];
  168. ScsiLunReport *r = (void *) data;
  169. ScsiDevice *sdev = vdev->scsi_device;
  170. int i, luns;
  171. /* QEMU has hardcoded channel #0 in many places.
  172. * If this hardcoded value is ever changed, we'll need to add code for
  173. * vdev->config.scsi.max_channel != 0 here.
  174. */
  175. debug_print_int("config.scsi.max_channel", vdev->config.scsi.max_channel);
  176. debug_print_int("config.scsi.max_target ", vdev->config.scsi.max_target);
  177. debug_print_int("config.scsi.max_lun ", vdev->config.scsi.max_lun);
  178. debug_print_int("config.scsi.max_sectors", vdev->config.scsi.max_sectors);
  179. if (vdev->scsi_device_selected) {
  180. sdev->channel = vdev->selected_scsi_device.channel;
  181. sdev->target = vdev->selected_scsi_device.target;
  182. sdev->lun = vdev->selected_scsi_device.lun;
  183. IPL_check(sdev->channel == 0, "non-zero channel requested");
  184. IPL_check(sdev->target <= vdev->config.scsi.max_target, "target# high");
  185. IPL_check(sdev->lun <= vdev->config.scsi.max_lun, "LUN# high");
  186. return;
  187. }
  188. for (target = 0; target <= vdev->config.scsi.max_target; target++) {
  189. sdev->channel = channel;
  190. sdev->target = target;
  191. sdev->lun = 0; /* LUN has to be 0 for REPORT LUNS */
  192. if (!scsi_report_luns(vdev, data, sizeof(data))) {
  193. if (resp.response == VIRTIO_SCSI_S_BAD_TARGET) {
  194. continue;
  195. }
  196. print_int("target", target);
  197. virtio_scsi_verify_response(&resp, "SCSI cannot report LUNs");
  198. }
  199. if (r->lun_list_len == 0) {
  200. print_int("no LUNs for target", target);
  201. continue;
  202. }
  203. luns = r->lun_list_len / 8;
  204. debug_print_int("LUNs reported", luns);
  205. if (luns == 1) {
  206. /* There is no ",lun=#" arg for -device or ",lun=0" given.
  207. * Hence, the only LUN reported.
  208. * Usually, it's 0.
  209. */
  210. sdev->lun = r->lun[0].v16[0]; /* it's returned this way */
  211. debug_print_int("Have to use LUN", sdev->lun);
  212. return; /* we have to use this device */
  213. }
  214. for (i = 0; i < luns; i++) {
  215. if (r->lun[i].v64) {
  216. /* Look for non-zero LUN - we have where to choose from */
  217. sdev->lun = r->lun[i].v16[0];
  218. debug_print_int("Will use LUN", sdev->lun);
  219. return; /* we have found a device */
  220. }
  221. }
  222. }
  223. panic("\n! Cannot locate virtio-scsi device !\n");
  224. }
  225. int virtio_scsi_read_many(VDev *vdev,
  226. ulong sector, void *load_addr, int sec_num)
  227. {
  228. int sector_count;
  229. int f = vdev->blk_factor;
  230. unsigned int data_size;
  231. unsigned int max_transfer = MIN_NON_ZERO(vdev->config.scsi.max_sectors,
  232. vdev->max_transfer);
  233. do {
  234. sector_count = MIN_NON_ZERO(sec_num, max_transfer);
  235. data_size = sector_count * virtio_get_block_size() * f;
  236. if (!scsi_read_10(vdev, sector * f, sector_count * f, load_addr,
  237. data_size)) {
  238. virtio_scsi_verify_response(&resp, "virtio-scsi:read_many");
  239. }
  240. load_addr += data_size;
  241. sector += sector_count;
  242. sec_num -= sector_count;
  243. } while (sec_num > 0);
  244. return 0;
  245. }
  246. static bool virtio_scsi_inquiry_response_is_cdrom(void *data)
  247. {
  248. const ScsiInquiryStd *response = data;
  249. const int resp_data_fmt = response->b3 & 0x0f;
  250. int i;
  251. IPL_check(resp_data_fmt == 2, "Wrong INQUIRY response format");
  252. if (resp_data_fmt != 2) {
  253. return false; /* cannot decode */
  254. }
  255. if ((response->peripheral_qdt & 0x1f) == SCSI_INQ_RDT_CDROM) {
  256. return true;
  257. }
  258. for (i = 0; i < sizeof(response->prod_id); i++) {
  259. if (response->prod_id[i] != QEMU_CDROM_SIGNATURE[i]) {
  260. return false;
  261. }
  262. }
  263. return true;
  264. }
  265. static void scsi_parse_capacity_report(void *data,
  266. uint64_t *last_lba, uint32_t *lb_len)
  267. {
  268. ScsiReadCapacity16Data *p = data;
  269. if (last_lba) {
  270. *last_lba = p->ret_lba;
  271. }
  272. if (lb_len) {
  273. *lb_len = p->lb_len;
  274. }
  275. }
  276. void virtio_scsi_setup(VDev *vdev)
  277. {
  278. int retry_test_unit_ready = 3;
  279. uint8_t data[256];
  280. uint32_t data_size = sizeof(data);
  281. ScsiInquiryEvpdPages *evpd = &scsi_inquiry_evpd_pages_response;
  282. ScsiInquiryEvpdBl *evpd_bl = &scsi_inquiry_evpd_bl_response;
  283. int i;
  284. vdev->scsi_device = &default_scsi_device;
  285. virtio_scsi_locate_device(vdev);
  286. /* We have to "ping" the device before it becomes readable */
  287. while (!scsi_test_unit_ready(vdev)) {
  288. if (!virtio_scsi_response_ok(&resp)) {
  289. uint8_t code = resp.sense[0] & SCSI_SENSE_CODE_MASK;
  290. uint8_t sense_key = resp.sense[2] & SCSI_SENSE_KEY_MASK;
  291. IPL_assert(resp.sense_len != 0, "virtio-scsi:setup: no SENSE data");
  292. IPL_assert(retry_test_unit_ready && code == 0x70 &&
  293. sense_key == SCSI_SENSE_KEY_UNIT_ATTENTION,
  294. "virtio-scsi:setup: cannot retry");
  295. /* retry on CHECK_CONDITION/UNIT_ATTENTION as it
  296. * may not designate a real error, but it may be
  297. * a result of device reset, etc.
  298. */
  299. retry_test_unit_ready--;
  300. sleep(1);
  301. continue;
  302. }
  303. virtio_scsi_verify_response(&resp, "virtio-scsi:setup");
  304. }
  305. /* read and cache SCSI INQUIRY response */
  306. if (!scsi_inquiry(vdev,
  307. SCSI_INQUIRY_STANDARD,
  308. SCSI_INQUIRY_STANDARD_NONE,
  309. scsi_inquiry_std_response,
  310. sizeof(scsi_inquiry_std_response))) {
  311. virtio_scsi_verify_response(&resp, "virtio-scsi:setup:inquiry");
  312. }
  313. if (virtio_scsi_inquiry_response_is_cdrom(scsi_inquiry_std_response)) {
  314. sclp_print("SCSI CD-ROM detected.\n");
  315. vdev->is_cdrom = true;
  316. vdev->scsi_block_size = VIRTIO_ISO_BLOCK_SIZE;
  317. }
  318. if (!scsi_inquiry(vdev,
  319. SCSI_INQUIRY_EVPD,
  320. SCSI_INQUIRY_EVPD_SUPPORTED_PAGES,
  321. evpd,
  322. sizeof(*evpd))) {
  323. virtio_scsi_verify_response(&resp, "virtio-scsi:setup:supported_pages");
  324. }
  325. debug_print_int("EVPD length", evpd->page_length);
  326. for (i = 0; i <= evpd->page_length; i++) {
  327. debug_print_int("supported EVPD page", evpd->byte[i]);
  328. if (evpd->byte[i] != SCSI_INQUIRY_EVPD_BLOCK_LIMITS) {
  329. continue;
  330. }
  331. if (!scsi_inquiry(vdev,
  332. SCSI_INQUIRY_EVPD,
  333. SCSI_INQUIRY_EVPD_BLOCK_LIMITS,
  334. evpd_bl,
  335. sizeof(*evpd_bl))) {
  336. virtio_scsi_verify_response(&resp, "virtio-scsi:setup:blocklimits");
  337. }
  338. debug_print_int("max transfer", evpd_bl->max_transfer);
  339. vdev->max_transfer = evpd_bl->max_transfer;
  340. }
  341. /*
  342. * The host sg driver will often be unhappy with particularly large
  343. * I/Os that exceed the block iovec limits. Let's enforce something
  344. * reasonable, despite what the device configuration tells us.
  345. */
  346. vdev->max_transfer = MIN_NON_ZERO(VIRTIO_SCSI_MAX_SECTORS,
  347. vdev->max_transfer);
  348. if (!scsi_read_capacity(vdev, data, data_size)) {
  349. virtio_scsi_verify_response(&resp, "virtio-scsi:setup:read_capacity");
  350. }
  351. scsi_parse_capacity_report(data, &vdev->scsi_last_block,
  352. (uint32_t *) &vdev->scsi_block_size);
  353. }