These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / seabios / src / hw / blockcmd.c
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_GLOBALFLAT
9 #include "block.h" // struct disk_op_s
10 #include "blockcmd.h" // struct cdb_request_sense
11 #include "byteorder.h" // be32_to_cpu
12 #include "output.h" // dprintf
13 #include "std/disk.h" // DISK_RET_EPARAM
14 #include "string.h" // memset
15 #include "util.h" // timer_calc
16
17
18 /****************************************************************
19  * Low level command requests
20  ****************************************************************/
21
22 static int
23 cdb_get_inquiry(struct disk_op_s *op, struct cdbres_inquiry *data)
24 {
25     struct cdb_request_sense cmd;
26     memset(&cmd, 0, sizeof(cmd));
27     cmd.command = CDB_CMD_INQUIRY;
28     cmd.length = sizeof(*data);
29     op->command = CMD_SCSI;
30     op->count = 1;
31     op->buf_fl = data;
32     op->cdbcmd = &cmd;
33     op->blocksize = sizeof(*data);
34     return process_op(op);
35 }
36
37 // Request SENSE
38 static int
39 cdb_get_sense(struct disk_op_s *op, struct cdbres_request_sense *data)
40 {
41     struct cdb_request_sense cmd;
42     memset(&cmd, 0, sizeof(cmd));
43     cmd.command = CDB_CMD_REQUEST_SENSE;
44     cmd.length = sizeof(*data);
45     op->command = CMD_SCSI;
46     op->count = 1;
47     op->buf_fl = data;
48     op->cdbcmd = &cmd;
49     op->blocksize = sizeof(*data);
50     return process_op(op);
51 }
52
53 // Test unit ready
54 static int
55 cdb_test_unit_ready(struct disk_op_s *op)
56 {
57     struct cdb_request_sense cmd;
58     memset(&cmd, 0, sizeof(cmd));
59     cmd.command = CDB_CMD_TEST_UNIT_READY;
60     op->command = CMD_SCSI;
61     op->count = 0;
62     op->buf_fl = NULL;
63     op->cdbcmd = &cmd;
64     op->blocksize = 0;
65     return process_op(op);
66 }
67
68 // Request capacity
69 static int
70 cdb_read_capacity(struct disk_op_s *op, struct cdbres_read_capacity *data)
71 {
72     struct cdb_read_capacity cmd;
73     memset(&cmd, 0, sizeof(cmd));
74     cmd.command = CDB_CMD_READ_CAPACITY;
75     op->command = CMD_SCSI;
76     op->count = 1;
77     op->buf_fl = data;
78     op->cdbcmd = &cmd;
79     op->blocksize = sizeof(*data);
80     return process_op(op);
81 }
82
83 // Mode sense, geometry page.
84 static int
85 cdb_mode_sense_geom(struct disk_op_s *op, struct cdbres_mode_sense_geom *data)
86 {
87     struct cdb_mode_sense cmd;
88     memset(&cmd, 0, sizeof(cmd));
89     cmd.command = CDB_CMD_MODE_SENSE;
90     cmd.flags = 8; /* DBD */
91     cmd.page = MODE_PAGE_HD_GEOMETRY;
92     cmd.count = cpu_to_be16(sizeof(*data));
93     op->command = CMD_SCSI;
94     op->count = 1;
95     op->buf_fl = data;
96     op->cdbcmd = &cmd;
97     op->blocksize = sizeof(*data);
98     return process_op(op);
99 }
100
101
102 /****************************************************************
103  * Main SCSI commands
104  ****************************************************************/
105
106 // Create a scsi command request from a disk_op_s request
107 int
108 scsi_fill_cmd(struct disk_op_s *op, void *cdbcmd, int maxcdb)
109 {
110     switch (op->command) {
111     case CMD_READ:
112     case CMD_WRITE: ;
113         struct cdb_rwdata_10 *cmd = cdbcmd;
114         memset(cmd, 0, maxcdb);
115         cmd->command = (op->command == CMD_READ ? CDB_CMD_READ_10
116                         : CDB_CMD_WRITE_10);
117         cmd->lba = cpu_to_be32(op->lba);
118         cmd->count = cpu_to_be16(op->count);
119         return GET_GLOBALFLAT(op->drive_gf->blksize);
120     case CMD_SCSI:
121         memcpy(cdbcmd, op->cdbcmd, maxcdb);
122         return op->blocksize;
123     default:
124         return -1;
125     }
126 }
127
128 // Determine if the command is a request to pull data from the device
129 int
130 scsi_is_read(struct disk_op_s *op)
131 {
132     return op->command == CMD_READ || (op->command == CMD_SCSI && op->blocksize);
133 }
134
135 // Check if a SCSI device is ready to receive commands
136 int
137 scsi_is_ready(struct disk_op_s *op)
138 {
139     dprintf(6, "scsi_is_ready (drive=%p)\n", op->drive_gf);
140
141     /* Retry TEST UNIT READY for 5 seconds unless MEDIUM NOT PRESENT is
142      * reported by the device.  If the device reports "IN PROGRESS",
143      * 30 seconds is added. */
144     int in_progress = 0;
145     u32 end = timer_calc(5000);
146     for (;;) {
147         if (timer_check(end)) {
148             dprintf(1, "test unit ready failed\n");
149             return -1;
150         }
151
152         int ret = cdb_test_unit_ready(op);
153         if (!ret)
154             // Success
155             break;
156
157         struct cdbres_request_sense sense;
158         ret = cdb_get_sense(op, &sense);
159         if (ret)
160             // Error - retry.
161             continue;
162
163         // Sense succeeded.
164         if (sense.asc == 0x3a) { /* MEDIUM NOT PRESENT */
165             dprintf(1, "Device reports MEDIUM NOT PRESENT\n");
166             return -1;
167         }
168
169         if (sense.asc == 0x04 && sense.ascq == 0x01 && !in_progress) {
170             /* IN PROGRESS OF BECOMING READY */
171             dprintf(1, "Waiting for device to detect medium... ");
172             /* Allow 30 seconds more */
173             end = timer_calc(30000);
174             in_progress = 1;
175         }
176     }
177     return 0;
178 }
179
180 // Validate drive, find block size / sector count, and register drive.
181 int
182 scsi_drive_setup(struct drive_s *drive, const char *s, int prio)
183 {
184     struct disk_op_s dop;
185     memset(&dop, 0, sizeof(dop));
186     dop.drive_gf = drive;
187     struct cdbres_inquiry data;
188     int ret = cdb_get_inquiry(&dop, &data);
189     if (ret)
190         return ret;
191     char vendor[sizeof(data.vendor)+1], product[sizeof(data.product)+1];
192     char rev[sizeof(data.rev)+1];
193     strtcpy(vendor, data.vendor, sizeof(vendor));
194     nullTrailingSpace(vendor);
195     strtcpy(product, data.product, sizeof(product));
196     nullTrailingSpace(product);
197     strtcpy(rev, data.rev, sizeof(rev));
198     nullTrailingSpace(rev);
199     int pdt = data.pdt & 0x1f;
200     int removable = !!(data.removable & 0x80);
201     dprintf(1, "%s vendor='%s' product='%s' rev='%s' type=%d removable=%d\n"
202             , s, vendor, product, rev, pdt, removable);
203     drive->removable = removable;
204
205     if (pdt == SCSI_TYPE_CDROM) {
206         drive->blksize = CDROM_SECTOR_SIZE;
207         drive->sectors = (u64)-1;
208
209         char *desc = znprintf(MAXDESCSIZE, "DVD/CD [%s Drive %s %s %s]"
210                               , s, vendor, product, rev);
211         boot_add_cd(drive, desc, prio);
212         return 0;
213     }
214
215     ret = scsi_is_ready(&dop);
216     if (ret) {
217         dprintf(1, "scsi_is_ready returned %d\n", ret);
218         return ret;
219     }
220
221     struct cdbres_read_capacity capdata;
222     ret = cdb_read_capacity(&dop, &capdata);
223     if (ret)
224         return ret;
225
226     // READ CAPACITY returns the address of the last block.
227     // We do not bother with READ CAPACITY(16) because BIOS does not support
228     // 64-bit LBA anyway.
229     drive->blksize = be32_to_cpu(capdata.blksize);
230     if (drive->blksize != DISK_SECTOR_SIZE) {
231         dprintf(1, "%s: unsupported block size %d\n", s, drive->blksize);
232         return -1;
233     }
234     drive->sectors = (u64)be32_to_cpu(capdata.sectors) + 1;
235     dprintf(1, "%s blksize=%d sectors=%d\n"
236             , s, drive->blksize, (unsigned)drive->sectors);
237
238     // We do not recover from USB stalls, so try to be safe and avoid
239     // sending the command if the (obsolete, but still provided by QEMU)
240     // fixed disk geometry page may not be supported.
241     //
242     // We could also send the command only to small disks (e.g. <504MiB)
243     // but some old USB keys only support a very small subset of SCSI which
244     // does not even include the MODE SENSE command!
245     //
246     if (CONFIG_QEMU_HARDWARE && memcmp(vendor, "QEMU", 5) == 0) {
247         struct cdbres_mode_sense_geom geomdata;
248         ret = cdb_mode_sense_geom(&dop, &geomdata);
249         if (ret == 0) {
250             u32 cylinders;
251             cylinders = geomdata.cyl[0] << 16;
252             cylinders |= geomdata.cyl[1] << 8;
253             cylinders |= geomdata.cyl[2];
254             if (cylinders && geomdata.heads &&
255                 drive->sectors <= 0xFFFFFFFFULL &&
256                 ((u32)drive->sectors % (geomdata.heads * cylinders) == 0)) {
257                 drive->pchs.cylinder = cylinders;
258                 drive->pchs.head = geomdata.heads;
259                 drive->pchs.sector = (u32)drive->sectors / (geomdata.heads * cylinders);
260             }
261         }
262     }
263
264     char *desc = znprintf(MAXDESCSIZE, "%s Drive %s %s %s"
265                           , s, vendor, product, rev);
266     boot_add_hd(drive, desc, prio);
267     return 0;
268 }