Kevin O'Connor | 76977b2 | 2010-02-17 01:01:32 -0500 | [diff] [blame] | 1 | // Support for several common scsi like command data block requests |
| 2 | // |
| 3 | // Copyright (C) 2010 Kevin O'Connor <kevin@koconnor.net> |
| 4 | // Copyright (C) 2002 MandrakeSoft S.A. |
| 5 | // |
| 6 | // This file may be distributed under the terms of the GNU LGPLv3 license. |
| 7 | |
| 8 | #include "biosvar.h" // GET_GLOBAL |
| 9 | #include "util.h" // htonl |
| 10 | #include "disk.h" // struct disk_op_s |
| 11 | #include "blockcmd.h" // struct cdb_request_sense |
| 12 | #include "ata.h" // atapi_cmd_data |
Gerd Hoffmann | d52fdf6 | 2010-11-29 09:42:13 +0100 | [diff] [blame] | 13 | #include "ahci.h" // atapi_cmd_data |
Kevin O'Connor | 7149fc8 | 2010-02-17 23:24:42 -0500 | [diff] [blame] | 14 | #include "usb-msc.h" // usb_cmd_data |
Kevin O'Connor | 76977b2 | 2010-02-17 01:01:32 -0500 | [diff] [blame] | 15 | |
Kevin O'Connor | 7149fc8 | 2010-02-17 23:24:42 -0500 | [diff] [blame] | 16 | // Route command to low-level handler. |
Kevin O'Connor | 76977b2 | 2010-02-17 01:01:32 -0500 | [diff] [blame] | 17 | static int |
| 18 | cdb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize) |
| 19 | { |
| 20 | u8 type = GET_GLOBAL(op->drive_g->type); |
| 21 | switch (type) { |
| 22 | case DTYPE_ATAPI: |
| 23 | return atapi_cmd_data(op, cdbcmd, blocksize); |
Kevin O'Connor | 7149fc8 | 2010-02-17 23:24:42 -0500 | [diff] [blame] | 24 | case DTYPE_USB: |
| 25 | return usb_cmd_data(op, cdbcmd, blocksize); |
Gerd Hoffmann | d52fdf6 | 2010-11-29 09:42:13 +0100 | [diff] [blame] | 26 | case DTYPE_AHCI: |
| 27 | return ahci_cmd_data(op, cdbcmd, blocksize); |
Kevin O'Connor | 76977b2 | 2010-02-17 01:01:32 -0500 | [diff] [blame] | 28 | default: |
| 29 | op->count = 0; |
| 30 | return DISK_RET_EPARAM; |
| 31 | } |
| 32 | } |
| 33 | |
Kevin O'Connor | 7149fc8 | 2010-02-17 23:24:42 -0500 | [diff] [blame] | 34 | int |
| 35 | cdb_get_inquiry(struct disk_op_s *op, struct cdbres_inquiry *data) |
| 36 | { |
| 37 | struct cdb_request_sense cmd; |
| 38 | memset(&cmd, 0, sizeof(cmd)); |
| 39 | cmd.command = CDB_CMD_INQUIRY; |
| 40 | cmd.length = sizeof(*data); |
| 41 | op->count = 1; |
| 42 | op->buf_fl = data; |
| 43 | return cdb_cmd_data(op, &cmd, sizeof(*data)); |
| 44 | } |
| 45 | |
Kevin O'Connor | 76977b2 | 2010-02-17 01:01:32 -0500 | [diff] [blame] | 46 | // Request SENSE |
| 47 | int |
| 48 | cdb_get_sense(struct disk_op_s *op, struct cdbres_request_sense *data) |
| 49 | { |
| 50 | struct cdb_request_sense cmd; |
| 51 | memset(&cmd, 0, sizeof(cmd)); |
| 52 | cmd.command = CDB_CMD_REQUEST_SENSE; |
| 53 | cmd.length = sizeof(*data); |
| 54 | op->count = 1; |
| 55 | op->buf_fl = data; |
| 56 | return cdb_cmd_data(op, &cmd, sizeof(*data)); |
| 57 | } |
| 58 | |
Paolo Bonzini | 0082374 | 2011-11-16 13:02:42 +0100 | [diff] [blame] | 59 | // Test unit ready |
| 60 | int |
| 61 | cdb_test_unit_ready(struct disk_op_s *op) |
| 62 | { |
| 63 | struct cdb_request_sense cmd; |
| 64 | memset(&cmd, 0, sizeof(cmd)); |
| 65 | cmd.command = CDB_CMD_TEST_UNIT_READY; |
| 66 | op->count = 0; |
| 67 | op->buf_fl = NULL; |
| 68 | return cdb_cmd_data(op, &cmd, 0); |
| 69 | } |
| 70 | |
Kevin O'Connor | 76977b2 | 2010-02-17 01:01:32 -0500 | [diff] [blame] | 71 | // Request capacity |
| 72 | int |
| 73 | cdb_read_capacity(struct disk_op_s *op, struct cdbres_read_capacity *data) |
| 74 | { |
| 75 | struct cdb_read_capacity cmd; |
| 76 | memset(&cmd, 0, sizeof(cmd)); |
| 77 | cmd.command = CDB_CMD_READ_CAPACITY; |
| 78 | op->count = 1; |
| 79 | op->buf_fl = data; |
| 80 | return cdb_cmd_data(op, &cmd, sizeof(*data)); |
| 81 | } |
| 82 | |
| 83 | // Read sectors. |
| 84 | int |
| 85 | cdb_read(struct disk_op_s *op) |
| 86 | { |
| 87 | struct cdb_rwdata_10 cmd; |
| 88 | memset(&cmd, 0, sizeof(cmd)); |
| 89 | cmd.command = CDB_CMD_READ_10; |
| 90 | cmd.lba = htonl(op->lba); |
| 91 | cmd.count = htons(op->count); |
Kevin O'Connor | 7149fc8 | 2010-02-17 23:24:42 -0500 | [diff] [blame] | 92 | return cdb_cmd_data(op, &cmd, GET_GLOBAL(op->drive_g->blksize)); |
Kevin O'Connor | 76977b2 | 2010-02-17 01:01:32 -0500 | [diff] [blame] | 93 | } |
Paolo Bonzini | ddb8ceb | 2011-11-16 13:02:47 +0100 | [diff] [blame^] | 94 | |
| 95 | // Write sectors. |
| 96 | int |
| 97 | cdb_write(struct disk_op_s *op) |
| 98 | { |
| 99 | struct cdb_rwdata_10 cmd; |
| 100 | memset(&cmd, 0, sizeof(cmd)); |
| 101 | cmd.command = CDB_CMD_WRITE_10; |
| 102 | cmd.lba = htonl(op->lba); |
| 103 | cmd.count = htons(op->count); |
| 104 | return cdb_cmd_data(op, &cmd, GET_GLOBAL(op->drive_g->blksize)); |
| 105 | } |