Commit 2e5d83bbef5a539f22970c2bccd19b125d82aab0

Authored by pbrook
1 parent e6f3e5e0

Rearrange SCSI disk emulation code.

Add USB mass storage device emulation.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1940 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile.target
@@ -306,8 +306,11 @@ ifdef CONFIG_ADLIB @@ -306,8 +306,11 @@ ifdef CONFIG_ADLIB
306 SOUND_HW += fmopl.o adlib.o 306 SOUND_HW += fmopl.o adlib.o
307 endif 307 endif
308 308
  309 +# SCSI layer
  310 +VL_OBJS+= scsi-disk.o cdrom.o
  311 +
309 # USB layer 312 # USB layer
310 -VL_OBJS+= usb.o usb-hub.o usb-linux.o usb-hid.o usb-ohci.o 313 +VL_OBJS+= usb.o usb-hub.o usb-linux.o usb-hid.o usb-ohci.o usb-msd.o
311 314
312 # PCI network cards 315 # PCI network cards
313 VL_OBJS+= ne2000.o rtl8139.o 316 VL_OBJS+= ne2000.o rtl8139.o
hw/cdrom.c 0 → 100644
  1 +/*
  2 + * QEMU ATAPI CD-ROM Emulator
  3 + *
  4 + * Copyright (c) 2006 Fabrice Bellard
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +
  25 +/* ??? Most of the ATAPI emulation is still in ide.c. It should be moved
  26 + here. */
  27 +
  28 +#include <vl.h>
  29 +
  30 +static void lba_to_msf(uint8_t *buf, int lba)
  31 +{
  32 + lba += 150;
  33 + buf[0] = (lba / 75) / 60;
  34 + buf[1] = (lba / 75) % 60;
  35 + buf[2] = lba % 75;
  36 +}
  37 +
  38 +/* same toc as bochs. Return -1 if error or the toc length */
  39 +/* XXX: check this */
  40 +int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track)
  41 +{
  42 + uint8_t *q;
  43 + int len;
  44 +
  45 + if (start_track > 1 && start_track != 0xaa)
  46 + return -1;
  47 + q = buf + 2;
  48 + *q++ = 1; /* first session */
  49 + *q++ = 1; /* last session */
  50 + if (start_track <= 1) {
  51 + *q++ = 0; /* reserved */
  52 + *q++ = 0x14; /* ADR, control */
  53 + *q++ = 1; /* track number */
  54 + *q++ = 0; /* reserved */
  55 + if (msf) {
  56 + *q++ = 0; /* reserved */
  57 + lba_to_msf(q, 0);
  58 + q += 3;
  59 + } else {
  60 + /* sector 0 */
  61 + cpu_to_be32wu((uint32_t *)q, 0);
  62 + q += 4;
  63 + }
  64 + }
  65 + /* lead out track */
  66 + *q++ = 0; /* reserved */
  67 + *q++ = 0x16; /* ADR, control */
  68 + *q++ = 0xaa; /* track number */
  69 + *q++ = 0; /* reserved */
  70 + if (msf) {
  71 + *q++ = 0; /* reserved */
  72 + lba_to_msf(q, nb_sectors);
  73 + q += 3;
  74 + } else {
  75 + cpu_to_be32wu((uint32_t *)q, nb_sectors);
  76 + q += 4;
  77 + }
  78 + len = q - buf;
  79 + cpu_to_be16wu((uint16_t *)buf, len - 2);
  80 + return len;
  81 +}
  82 +
  83 +/* mostly same info as PearPc */
  84 +int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num)
  85 +{
  86 + uint8_t *q;
  87 + int len;
  88 +
  89 + q = buf + 2;
  90 + *q++ = 1; /* first session */
  91 + *q++ = 1; /* last session */
  92 +
  93 + *q++ = 1; /* session number */
  94 + *q++ = 0x14; /* data track */
  95 + *q++ = 0; /* track number */
  96 + *q++ = 0xa0; /* lead-in */
  97 + *q++ = 0; /* min */
  98 + *q++ = 0; /* sec */
  99 + *q++ = 0; /* frame */
  100 + *q++ = 0;
  101 + *q++ = 1; /* first track */
  102 + *q++ = 0x00; /* disk type */
  103 + *q++ = 0x00;
  104 +
  105 + *q++ = 1; /* session number */
  106 + *q++ = 0x14; /* data track */
  107 + *q++ = 0; /* track number */
  108 + *q++ = 0xa1;
  109 + *q++ = 0; /* min */
  110 + *q++ = 0; /* sec */
  111 + *q++ = 0; /* frame */
  112 + *q++ = 0;
  113 + *q++ = 1; /* last track */
  114 + *q++ = 0x00;
  115 + *q++ = 0x00;
  116 +
  117 + *q++ = 1; /* session number */
  118 + *q++ = 0x14; /* data track */
  119 + *q++ = 0; /* track number */
  120 + *q++ = 0xa2; /* lead-out */
  121 + *q++ = 0; /* min */
  122 + *q++ = 0; /* sec */
  123 + *q++ = 0; /* frame */
  124 + if (msf) {
  125 + *q++ = 0; /* reserved */
  126 + lba_to_msf(q, nb_sectors);
  127 + q += 3;
  128 + } else {
  129 + cpu_to_be32wu((uint32_t *)q, nb_sectors);
  130 + q += 4;
  131 + }
  132 +
  133 + *q++ = 1; /* session number */
  134 + *q++ = 0x14; /* ADR, control */
  135 + *q++ = 0; /* track number */
  136 + *q++ = 1; /* point */
  137 + *q++ = 0; /* min */
  138 + *q++ = 0; /* sec */
  139 + *q++ = 0; /* frame */
  140 + if (msf) {
  141 + *q++ = 0;
  142 + lba_to_msf(q, 0);
  143 + q += 3;
  144 + } else {
  145 + *q++ = 0;
  146 + *q++ = 0;
  147 + *q++ = 0;
  148 + *q++ = 0;
  149 + }
  150 +
  151 + len = q - buf;
  152 + cpu_to_be16wu((uint16_t *)buf, len - 2);
  153 + return len;
  154 +}
  155 +
  156 +
hw/esp.c
@@ -38,17 +38,14 @@ do { printf(&quot;ESP: set_irq(%d): %d\n&quot;, (irq), (level)); pic_set_irq((irq),(level) @@ -38,17 +38,14 @@ do { printf(&quot;ESP: set_irq(%d): %d\n&quot;, (irq), (level)); pic_set_irq((irq),(level)
38 #define ESPDMA_REGS 4 38 #define ESPDMA_REGS 4
39 #define ESPDMA_MAXADDR (ESPDMA_REGS * 4 - 1) 39 #define ESPDMA_MAXADDR (ESPDMA_REGS * 4 - 1)
40 #define ESP_MAXREG 0x3f 40 #define ESP_MAXREG 0x3f
41 -#define TI_BUFSZ 1024*1024 // XXX 41 +#define TI_BUFSZ 32
42 #define DMA_VER 0xa0000000 42 #define DMA_VER 0xa0000000
43 #define DMA_INTR 1 43 #define DMA_INTR 1
44 #define DMA_INTREN 0x10 44 #define DMA_INTREN 0x10
  45 +#define DMA_WRITE_MEM 0x100
45 #define DMA_LOADED 0x04000000 46 #define DMA_LOADED 0x04000000
46 typedef struct ESPState ESPState; 47 typedef struct ESPState ESPState;
47 48
48 -typedef int ESPDMAFunc(ESPState *s,  
49 - target_phys_addr_t phys_addr,  
50 - int transfer_size1);  
51 -  
52 struct ESPState { 49 struct ESPState {
53 BlockDriverState **bd; 50 BlockDriverState **bd;
54 uint8_t rregs[ESP_MAXREG]; 51 uint8_t rregs[ESP_MAXREG];
@@ -57,12 +54,10 @@ struct ESPState { @@ -57,12 +54,10 @@ struct ESPState {
57 uint32_t espdmaregs[ESPDMA_REGS]; 54 uint32_t espdmaregs[ESPDMA_REGS];
58 uint32_t ti_size; 55 uint32_t ti_size;
59 uint32_t ti_rptr, ti_wptr; 56 uint32_t ti_rptr, ti_wptr;
60 - int ti_dir;  
61 uint8_t ti_buf[TI_BUFSZ]; 57 uint8_t ti_buf[TI_BUFSZ];
62 int dma; 58 int dma;
63 - ESPDMAFunc *dma_cb;  
64 - int64_t offset, len;  
65 - int target; 59 + SCSIDevice *scsi_dev[MAX_DISKS];
  60 + SCSIDevice *current_dev;
66 }; 61 };
67 62
68 #define STAT_DO 0x00 63 #define STAT_DO 0x00
@@ -83,195 +78,33 @@ struct ESPState { @@ -83,195 +78,33 @@ struct ESPState {
83 #define SEQ_0 0x0 78 #define SEQ_0 0x0
84 #define SEQ_CD 0x4 79 #define SEQ_CD 0x4
85 80
86 -/* XXX: stolen from ide.c, move to common ATAPI/SCSI library */  
87 -static void lba_to_msf(uint8_t *buf, int lba)  
88 -{  
89 - lba += 150;  
90 - buf[0] = (lba / 75) / 60;  
91 - buf[1] = (lba / 75) % 60;  
92 - buf[2] = lba % 75;  
93 -}  
94 -  
95 -static inline void cpu_to_ube16(uint8_t *buf, int val)  
96 -{  
97 - buf[0] = val >> 8;  
98 - buf[1] = val;  
99 -}  
100 -  
101 -static inline void cpu_to_ube32(uint8_t *buf, unsigned int val)  
102 -{  
103 - buf[0] = val >> 24;  
104 - buf[1] = val >> 16;  
105 - buf[2] = val >> 8;  
106 - buf[3] = val;  
107 -}  
108 -  
109 -/* same toc as bochs. Return -1 if error or the toc length */  
110 -/* XXX: check this */  
111 -static int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track)  
112 -{  
113 - uint8_t *q;  
114 - int len;  
115 -  
116 - if (start_track > 1 && start_track != 0xaa)  
117 - return -1;  
118 - q = buf + 2;  
119 - *q++ = 1; /* first session */  
120 - *q++ = 1; /* last session */  
121 - if (start_track <= 1) {  
122 - *q++ = 0; /* reserved */  
123 - *q++ = 0x14; /* ADR, control */  
124 - *q++ = 1; /* track number */  
125 - *q++ = 0; /* reserved */  
126 - if (msf) {  
127 - *q++ = 0; /* reserved */  
128 - lba_to_msf(q, 0);  
129 - q += 3;  
130 - } else {  
131 - /* sector 0 */  
132 - cpu_to_ube32(q, 0);  
133 - q += 4;  
134 - }  
135 - }  
136 - /* lead out track */  
137 - *q++ = 0; /* reserved */  
138 - *q++ = 0x16; /* ADR, control */  
139 - *q++ = 0xaa; /* track number */  
140 - *q++ = 0; /* reserved */  
141 - if (msf) {  
142 - *q++ = 0; /* reserved */  
143 - lba_to_msf(q, nb_sectors);  
144 - q += 3;  
145 - } else {  
146 - cpu_to_ube32(q, nb_sectors);  
147 - q += 4;  
148 - }  
149 - len = q - buf;  
150 - cpu_to_ube16(buf, len - 2);  
151 - return len;  
152 -}  
153 -  
154 -/* mostly same info as PearPc */  
155 -static int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf,  
156 - int session_num)  
157 -{  
158 - uint8_t *q;  
159 - int len;  
160 -  
161 - q = buf + 2;  
162 - *q++ = 1; /* first session */  
163 - *q++ = 1; /* last session */  
164 -  
165 - *q++ = 1; /* session number */  
166 - *q++ = 0x14; /* data track */  
167 - *q++ = 0; /* track number */  
168 - *q++ = 0xa0; /* lead-in */  
169 - *q++ = 0; /* min */  
170 - *q++ = 0; /* sec */  
171 - *q++ = 0; /* frame */  
172 - *q++ = 0;  
173 - *q++ = 1; /* first track */  
174 - *q++ = 0x00; /* disk type */  
175 - *q++ = 0x00;  
176 -  
177 - *q++ = 1; /* session number */  
178 - *q++ = 0x14; /* data track */  
179 - *q++ = 0; /* track number */  
180 - *q++ = 0xa1;  
181 - *q++ = 0; /* min */  
182 - *q++ = 0; /* sec */  
183 - *q++ = 0; /* frame */  
184 - *q++ = 0;  
185 - *q++ = 1; /* last track */  
186 - *q++ = 0x00;  
187 - *q++ = 0x00;  
188 -  
189 - *q++ = 1; /* session number */  
190 - *q++ = 0x14; /* data track */  
191 - *q++ = 0; /* track number */  
192 - *q++ = 0xa2; /* lead-out */  
193 - *q++ = 0; /* min */  
194 - *q++ = 0; /* sec */  
195 - *q++ = 0; /* frame */  
196 - if (msf) {  
197 - *q++ = 0; /* reserved */  
198 - lba_to_msf(q, nb_sectors);  
199 - q += 3;  
200 - } else {  
201 - cpu_to_ube32(q, nb_sectors);  
202 - q += 4;  
203 - }  
204 -  
205 - *q++ = 1; /* session number */  
206 - *q++ = 0x14; /* ADR, control */  
207 - *q++ = 0; /* track number */  
208 - *q++ = 1; /* point */  
209 - *q++ = 0; /* min */  
210 - *q++ = 0; /* sec */  
211 - *q++ = 0; /* frame */  
212 - if (msf) {  
213 - *q++ = 0;  
214 - lba_to_msf(q, 0);  
215 - q += 3;  
216 - } else {  
217 - *q++ = 0;  
218 - *q++ = 0;  
219 - *q++ = 0;  
220 - *q++ = 0;  
221 - }  
222 -  
223 - len = q - buf;  
224 - cpu_to_ube16(buf, len - 2);  
225 - return len;  
226 -}  
227 -  
228 -static int esp_write_dma_cb(ESPState *s,  
229 - target_phys_addr_t phys_addr,  
230 - int transfer_size1)  
231 -{  
232 - int len;  
233 - if (bdrv_get_type_hint(s->bd[s->target]) == BDRV_TYPE_CDROM) {  
234 - len = transfer_size1/2048;  
235 - } else {  
236 - len = transfer_size1/512;  
237 - }  
238 - DPRINTF("Write callback (offset %lld len %lld size %d trans_size %d)\n",  
239 - s->offset, s->len, s->ti_size, transfer_size1);  
240 -  
241 - bdrv_write(s->bd[s->target], s->offset, s->ti_buf+s->ti_rptr, len);  
242 - s->offset+=len;  
243 - return 0;  
244 -}  
245 -  
246 static void handle_satn(ESPState *s) 81 static void handle_satn(ESPState *s)
247 { 82 {
248 uint8_t buf[32]; 83 uint8_t buf[32];
249 uint32_t dmaptr, dmalen; 84 uint32_t dmaptr, dmalen;
250 - unsigned int i;  
251 - int64_t nb_sectors;  
252 int target; 85 int target;
  86 + int32_t datalen;
253 87
254 dmalen = s->wregs[0] | (s->wregs[1] << 8); 88 dmalen = s->wregs[0] | (s->wregs[1] << 8);
255 target = s->wregs[4] & 7; 89 target = s->wregs[4] & 7;
256 DPRINTF("Select with ATN len %d target %d\n", dmalen, target); 90 DPRINTF("Select with ATN len %d target %d\n", dmalen, target);
257 if (s->dma) { 91 if (s->dma) {
258 dmaptr = iommu_translate(s->espdmaregs[1]); 92 dmaptr = iommu_translate(s->espdmaregs[1]);
259 - DPRINTF("DMA Direction: %c, addr 0x%8.8x\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr); 93 + DPRINTF("DMA Direction: %c, addr 0x%8.8x\n",
  94 + s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', dmaptr);
260 cpu_physical_memory_read(dmaptr, buf, dmalen); 95 cpu_physical_memory_read(dmaptr, buf, dmalen);
261 } else { 96 } else {
262 buf[0] = 0; 97 buf[0] = 0;
263 memcpy(&buf[1], s->ti_buf, dmalen); 98 memcpy(&buf[1], s->ti_buf, dmalen);
264 dmalen++; 99 dmalen++;
265 } 100 }
266 - for (i = 0; i < dmalen; i++) {  
267 - DPRINTF("Command %2.2x\n", buf[i]);  
268 - }  
269 - s->ti_dir = 0; 101 +
270 s->ti_size = 0; 102 s->ti_size = 0;
271 s->ti_rptr = 0; 103 s->ti_rptr = 0;
272 s->ti_wptr = 0; 104 s->ti_wptr = 0;
273 105
274 - if (target >= 4 || !s->bd[target]) { // No such drive 106 + if (target >= 4 || !s->scsi_dev[target]) {
  107 + // No such drive
275 s->rregs[4] = STAT_IN; 108 s->rregs[4] = STAT_IN;
276 s->rregs[5] = INTR_DC; 109 s->rregs[5] = INTR_DC;
277 s->rregs[6] = SEQ_0; 110 s->rregs[6] = SEQ_0;
@@ -279,141 +112,20 @@ static void handle_satn(ESPState *s) @@ -279,141 +112,20 @@ static void handle_satn(ESPState *s)
279 pic_set_irq(s->irq, 1); 112 pic_set_irq(s->irq, 1);
280 return; 113 return;
281 } 114 }
282 - switch (buf[1]) {  
283 - case 0x0:  
284 - DPRINTF("Test Unit Ready (len %d)\n", buf[5]);  
285 - break;  
286 - case 0x12:  
287 - DPRINTF("Inquiry (len %d)\n", buf[5]);  
288 - memset(s->ti_buf, 0, 36);  
289 - if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) {  
290 - s->ti_buf[0] = 5;  
291 - memcpy(&s->ti_buf[16], "QEMU CDROM ", 16);  
292 - } else {  
293 - s->ti_buf[0] = 0;  
294 - memcpy(&s->ti_buf[16], "QEMU HARDDISK ", 16);  
295 - }  
296 - memcpy(&s->ti_buf[8], "QEMU ", 8);  
297 - s->ti_buf[2] = 1;  
298 - s->ti_buf[3] = 2;  
299 - s->ti_buf[4] = 32;  
300 - s->ti_dir = 1;  
301 - s->ti_size = 36;  
302 - break;  
303 - case 0x1a:  
304 - DPRINTF("Mode Sense(6) (page %d, len %d)\n", buf[3], buf[5]);  
305 - break;  
306 - case 0x25:  
307 - DPRINTF("Read Capacity (len %d)\n", buf[5]);  
308 - memset(s->ti_buf, 0, 8);  
309 - bdrv_get_geometry(s->bd[target], &nb_sectors);  
310 - s->ti_buf[0] = (nb_sectors >> 24) & 0xff;  
311 - s->ti_buf[1] = (nb_sectors >> 16) & 0xff;  
312 - s->ti_buf[2] = (nb_sectors >> 8) & 0xff;  
313 - s->ti_buf[3] = nb_sectors & 0xff;  
314 - s->ti_buf[4] = 0;  
315 - s->ti_buf[5] = 0;  
316 - if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM)  
317 - s->ti_buf[6] = 8; // sector size 2048  
318 - else  
319 - s->ti_buf[6] = 2; // sector size 512  
320 - s->ti_buf[7] = 0;  
321 - s->ti_dir = 1;  
322 - s->ti_size = 8;  
323 - break;  
324 - case 0x28:  
325 - {  
326 - int64_t offset, len;  
327 -  
328 - if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) {  
329 - offset = ((buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6]) * 4;  
330 - len = ((buf[8] << 8) | buf[9]) * 4;  
331 - s->ti_size = len * 2048;  
332 - } else {  
333 - offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];  
334 - len = (buf[8] << 8) | buf[9];  
335 - s->ti_size = len * 512;  
336 - }  
337 - DPRINTF("Read (10) (offset %lld len %lld)\n", offset, len);  
338 - if (s->ti_size > TI_BUFSZ) {  
339 - DPRINTF("size too large %d\n", s->ti_size);  
340 - }  
341 - bdrv_read(s->bd[target], offset, s->ti_buf, len);  
342 - // XXX error handling  
343 - s->ti_dir = 1;  
344 - s->ti_rptr = 0;  
345 - break;  
346 - }  
347 - case 0x2a:  
348 - {  
349 - int64_t offset, len;  
350 -  
351 - if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) {  
352 - offset = ((buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6]) * 4;  
353 - len = ((buf[8] << 8) | buf[9]) * 4;  
354 - s->ti_size = len * 2048;  
355 - } else {  
356 - offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];  
357 - len = (buf[8] << 8) | buf[9];  
358 - s->ti_size = len * 512;  
359 - }  
360 - DPRINTF("Write (10) (offset %lld len %lld)\n", offset, len);  
361 - if (s->ti_size > TI_BUFSZ) {  
362 - DPRINTF("size too large %d\n", s->ti_size);  
363 - }  
364 - s->dma_cb = esp_write_dma_cb;  
365 - s->offset = offset;  
366 - s->len = len;  
367 - s->target = target;  
368 - s->ti_rptr = 0;  
369 - // XXX error handling  
370 - s->ti_dir = 0;  
371 - break;  
372 - }  
373 - case 0x43:  
374 - {  
375 - int start_track, format, msf, len;  
376 -  
377 - msf = buf[2] & 2;  
378 - format = buf[3] & 0xf;  
379 - start_track = buf[7];  
380 - bdrv_get_geometry(s->bd[target], &nb_sectors);  
381 - DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);  
382 - switch(format) {  
383 - case 0:  
384 - len = cdrom_read_toc(nb_sectors, buf, msf, start_track);  
385 - if (len < 0)  
386 - goto error_cmd;  
387 - s->ti_size = len;  
388 - break;  
389 - case 1:  
390 - /* multi session : only a single session defined */  
391 - memset(buf, 0, 12);  
392 - buf[1] = 0x0a;  
393 - buf[2] = 0x01;  
394 - buf[3] = 0x01;  
395 - s->ti_size = 12;  
396 - break;  
397 - case 2:  
398 - len = cdrom_read_toc_raw(nb_sectors, buf, msf, start_track);  
399 - if (len < 0)  
400 - goto error_cmd;  
401 - s->ti_size = len;  
402 - break;  
403 - default:  
404 - error_cmd:  
405 - DPRINTF("Read TOC error\n");  
406 - // XXX error handling  
407 - break;  
408 - }  
409 - s->ti_dir = 1;  
410 - break; 115 + s->current_dev = s->scsi_dev[target];
  116 + datalen = scsi_send_command(s->current_dev, 0, &buf[1]);
  117 + if (datalen == 0) {
  118 + s->ti_size = 0;
  119 + } else {
  120 + s->rregs[4] = STAT_IN | STAT_TC;
  121 + if (datalen > 0) {
  122 + s->rregs[4] |= STAT_DI;
  123 + s->ti_size = datalen;
  124 + } else {
  125 + s->rregs[4] |= STAT_DO;
  126 + s->ti_size = -datalen;
411 } 127 }
412 - default:  
413 - DPRINTF("Unknown SCSI command (%2.2x)\n", buf[1]);  
414 - break;  
415 } 128 }
416 - s->rregs[4] = STAT_IN | STAT_TC | STAT_DI;  
417 s->rregs[5] = INTR_BS | INTR_FC; 129 s->rregs[5] = INTR_BS | INTR_FC;
418 s->rregs[6] = SEQ_CD; 130 s->rregs[6] = SEQ_CD;
419 s->espdmaregs[0] |= DMA_INTR; 131 s->espdmaregs[0] |= DMA_INTR;
@@ -427,7 +139,8 @@ static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len) @@ -427,7 +139,8 @@ static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len)
427 DPRINTF("Transfer status len %d\n", len); 139 DPRINTF("Transfer status len %d\n", len);
428 if (s->dma) { 140 if (s->dma) {
429 dmaptr = iommu_translate(s->espdmaregs[1]); 141 dmaptr = iommu_translate(s->espdmaregs[1]);
430 - DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r'); 142 + DPRINTF("DMA Direction: %c\n",
  143 + s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r');
431 cpu_physical_memory_write(dmaptr, buf, len); 144 cpu_physical_memory_write(dmaptr, buf, len);
432 s->rregs[4] = STAT_IN | STAT_TC | STAT_ST; 145 s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
433 s->rregs[5] = INTR_BS | INTR_FC; 146 s->rregs[5] = INTR_BS | INTR_FC;
@@ -446,10 +159,26 @@ static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len) @@ -446,10 +159,26 @@ static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len)
446 159
447 static const uint8_t okbuf[] = {0, 0}; 160 static const uint8_t okbuf[] = {0, 0};
448 161
  162 +static void esp_command_complete(void *opaque, uint32_t tag, int fail)
  163 +{
  164 + ESPState *s = (ESPState *)opaque;
  165 +
  166 + DPRINTF("SCSI Command complete\n");
  167 + if (s->ti_size != 0)
  168 + DPRINTF("SCSI command completed unexpectedly\n");
  169 + s->ti_size = 0;
  170 + /* ??? Report failures. */
  171 + if (fail)
  172 + DPRINTF("Command failed\n");
  173 + s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
  174 +}
  175 +
449 static void handle_ti(ESPState *s) 176 static void handle_ti(ESPState *s)
450 { 177 {
451 uint32_t dmaptr, dmalen, minlen, len, from, to; 178 uint32_t dmaptr, dmalen, minlen, len, from, to;
452 unsigned int i; 179 unsigned int i;
  180 + int to_device;
  181 + uint8_t buf[TARGET_PAGE_SIZE];
453 182
454 dmalen = s->wregs[0] | (s->wregs[1] << 8); 183 dmalen = s->wregs[0] | (s->wregs[1] << 8);
455 if (dmalen==0) { 184 if (dmalen==0) {
@@ -460,7 +189,10 @@ static void handle_ti(ESPState *s) @@ -460,7 +189,10 @@ static void handle_ti(ESPState *s)
460 DPRINTF("Transfer Information len %d\n", minlen); 189 DPRINTF("Transfer Information len %d\n", minlen);
461 if (s->dma) { 190 if (s->dma) {
462 dmaptr = iommu_translate(s->espdmaregs[1]); 191 dmaptr = iommu_translate(s->espdmaregs[1]);
463 - DPRINTF("DMA Direction: %c, addr 0x%8.8x %08x %d %d\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr, s->ti_size, s->ti_rptr, s->ti_dir); 192 + /* Check if the transfer writes to to reads from the device. */
  193 + to_device = (s->espdmaregs[0] & DMA_WRITE_MEM) == 0;
  194 + DPRINTF("DMA Direction: %c, addr 0x%8.8x %08x\n",
  195 + to_device ? 'r': 'w', dmaptr, s->ti_size);
464 from = s->espdmaregs[1]; 196 from = s->espdmaregs[1];
465 to = from + minlen; 197 to = from + minlen;
466 for (i = 0; i < minlen; i += len, from += len) { 198 for (i = 0; i < minlen; i += len, from += len) {
@@ -471,35 +203,23 @@ static void handle_ti(ESPState *s) @@ -471,35 +203,23 @@ static void handle_ti(ESPState *s)
471 len = to - from; 203 len = to - from;
472 } 204 }
473 DPRINTF("DMA address p %08x v %08x len %08x, from %08x, to %08x\n", dmaptr, s->espdmaregs[1] + i, len, from, to); 205 DPRINTF("DMA address p %08x v %08x len %08x, from %08x, to %08x\n", dmaptr, s->espdmaregs[1] + i, len, from, to);
474 - if (s->ti_dir)  
475 - cpu_physical_memory_write(dmaptr, &s->ti_buf[s->ti_rptr + i], len);  
476 - else  
477 - cpu_physical_memory_read(dmaptr, &s->ti_buf[s->ti_rptr + i], len); 206 + s->ti_size -= len;
  207 + if (to_device) {
  208 + cpu_physical_memory_read(dmaptr, buf, len);
  209 + scsi_write_data(s->current_dev, buf, len);
  210 + } else {
  211 + scsi_read_data(s->current_dev, buf, len);
  212 + cpu_physical_memory_write(dmaptr, buf, len);
  213 + }
478 } 214 }
479 - if (s->dma_cb) {  
480 - s->dma_cb(s, s->espdmaregs[1], minlen);  
481 - }  
482 - if (minlen < s->ti_size) {  
483 - s->rregs[4] = STAT_IN | STAT_TC | (s->ti_dir ? STAT_DO : STAT_DI); 215 + if (s->ti_size) {
  216 + s->rregs[4] = STAT_IN | STAT_TC | (to_device ? STAT_DO : STAT_DI);
484 s->ti_size -= minlen; 217 s->ti_size -= minlen;
485 - s->ti_rptr += minlen;  
486 - } else {  
487 - s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;  
488 - s->dma_cb = NULL;  
489 - s->offset = 0;  
490 - s->len = 0;  
491 - s->target = 0;  
492 - s->ti_rptr = 0;  
493 } 218 }
494 s->rregs[5] = INTR_BS; 219 s->rregs[5] = INTR_BS;
495 s->rregs[6] = 0; 220 s->rregs[6] = 0;
496 s->rregs[7] = 0; 221 s->rregs[7] = 0;
497 s->espdmaregs[0] |= DMA_INTR; 222 s->espdmaregs[0] |= DMA_INTR;
498 - } else {  
499 - s->ti_size = minlen;  
500 - s->ti_rptr = 0;  
501 - s->ti_wptr = 0;  
502 - s->rregs[7] = minlen;  
503 } 223 }
504 pic_set_irq(s->irq, 1); 224 pic_set_irq(s->irq, 1);
505 } 225 }
@@ -514,9 +234,7 @@ static void esp_reset(void *opaque) @@ -514,9 +234,7 @@ static void esp_reset(void *opaque)
514 s->ti_size = 0; 234 s->ti_size = 0;
515 s->ti_rptr = 0; 235 s->ti_rptr = 0;
516 s->ti_wptr = 0; 236 s->ti_wptr = 0;
517 - s->ti_dir = 0;  
518 s->dma = 0; 237 s->dma = 0;
519 - s->dma_cb = NULL;  
520 } 238 }
521 239
522 static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr) 240 static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
@@ -531,7 +249,12 @@ static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr) @@ -531,7 +249,12 @@ static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
531 // FIFO 249 // FIFO
532 if (s->ti_size > 0) { 250 if (s->ti_size > 0) {
533 s->ti_size--; 251 s->ti_size--;
534 - s->rregs[saddr] = s->ti_buf[s->ti_rptr++]; 252 + if ((s->rregs[4] & 6) == 0) {
  253 + /* Data in/out. */
  254 + scsi_read_data(s->current_dev, &s->rregs[2], 0);
  255 + } else {
  256 + s->rregs[2] = s->ti_buf[s->ti_rptr++];
  257 + }
535 pic_set_irq(s->irq, 1); 258 pic_set_irq(s->irq, 1);
536 } 259 }
537 if (s->ti_size == 0) { 260 if (s->ti_size == 0) {
@@ -566,8 +289,15 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) @@ -566,8 +289,15 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
566 break; 289 break;
567 case 2: 290 case 2:
568 // FIFO 291 // FIFO
569 - s->ti_size++;  
570 - s->ti_buf[s->ti_wptr++] = val & 0xff; 292 + if ((s->rregs[4] & 6) == 0) {
  293 + uint8_t buf;
  294 + buf = val & 0xff;
  295 + s->ti_size--;
  296 + scsi_write_data(s->current_dev, &buf, 0);
  297 + } else {
  298 + s->ti_size++;
  299 + s->ti_buf[s->ti_wptr++] = val & 0xff;
  300 + }
571 break; 301 break;
572 case 3: 302 case 3:
573 s->rregs[saddr] = val; 303 s->rregs[saddr] = val;
@@ -723,7 +453,6 @@ static void esp_save(QEMUFile *f, void *opaque) @@ -723,7 +453,6 @@ static void esp_save(QEMUFile *f, void *opaque)
723 qemu_put_be32s(f, &s->ti_size); 453 qemu_put_be32s(f, &s->ti_size);
724 qemu_put_be32s(f, &s->ti_rptr); 454 qemu_put_be32s(f, &s->ti_rptr);
725 qemu_put_be32s(f, &s->ti_wptr); 455 qemu_put_be32s(f, &s->ti_wptr);
726 - qemu_put_be32s(f, &s->ti_dir);  
727 qemu_put_buffer(f, s->ti_buf, TI_BUFSZ); 456 qemu_put_buffer(f, s->ti_buf, TI_BUFSZ);
728 qemu_put_be32s(f, &s->dma); 457 qemu_put_be32s(f, &s->dma);
729 } 458 }
@@ -744,7 +473,6 @@ static int esp_load(QEMUFile *f, void *opaque, int version_id) @@ -744,7 +473,6 @@ static int esp_load(QEMUFile *f, void *opaque, int version_id)
744 qemu_get_be32s(f, &s->ti_size); 473 qemu_get_be32s(f, &s->ti_size);
745 qemu_get_be32s(f, &s->ti_rptr); 474 qemu_get_be32s(f, &s->ti_rptr);
746 qemu_get_be32s(f, &s->ti_wptr); 475 qemu_get_be32s(f, &s->ti_wptr);
747 - qemu_get_be32s(f, &s->ti_dir);  
748 qemu_get_buffer(f, s->ti_buf, TI_BUFSZ); 476 qemu_get_buffer(f, s->ti_buf, TI_BUFSZ);
749 qemu_get_be32s(f, &s->dma); 477 qemu_get_be32s(f, &s->dma);
750 478
@@ -755,6 +483,7 @@ void esp_init(BlockDriverState **bd, int irq, uint32_t espaddr, uint32_t espdadd @@ -755,6 +483,7 @@ void esp_init(BlockDriverState **bd, int irq, uint32_t espaddr, uint32_t espdadd
755 { 483 {
756 ESPState *s; 484 ESPState *s;
757 int esp_io_memory, espdma_io_memory; 485 int esp_io_memory, espdma_io_memory;
  486 + int i;
758 487
759 s = qemu_mallocz(sizeof(ESPState)); 488 s = qemu_mallocz(sizeof(ESPState));
760 if (!s) 489 if (!s)
@@ -773,5 +502,11 @@ void esp_init(BlockDriverState **bd, int irq, uint32_t espaddr, uint32_t espdadd @@ -773,5 +502,11 @@ void esp_init(BlockDriverState **bd, int irq, uint32_t espaddr, uint32_t espdadd
773 502
774 register_savevm("esp", espaddr, 1, esp_save, esp_load, s); 503 register_savevm("esp", espaddr, 1, esp_save, esp_load, s);
775 qemu_register_reset(esp_reset, s); 504 qemu_register_reset(esp_reset, s);
  505 + for (i = 0; i < MAX_DISKS; i++) {
  506 + if (bs_table[i]) {
  507 + s->scsi_dev[i] =
  508 + scsi_disk_init(bs_table[i], esp_command_complete, s);
  509 + }
  510 + }
776 } 511 }
777 512
hw/ide.c
@@ -1082,127 +1082,6 @@ static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors, @@ -1082,127 +1082,6 @@ static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors,
1082 } 1082 }
1083 } 1083 }
1084 1084
1085 -/* same toc as bochs. Return -1 if error or the toc length */  
1086 -/* XXX: check this */  
1087 -static int cdrom_read_toc(IDEState *s, uint8_t *buf, int msf, int start_track)  
1088 -{  
1089 - uint8_t *q;  
1090 - int nb_sectors, len;  
1091 -  
1092 - if (start_track > 1 && start_track != 0xaa)  
1093 - return -1;  
1094 - q = buf + 2;  
1095 - *q++ = 1; /* first session */  
1096 - *q++ = 1; /* last session */  
1097 - if (start_track <= 1) {  
1098 - *q++ = 0; /* reserved */  
1099 - *q++ = 0x14; /* ADR, control */  
1100 - *q++ = 1; /* track number */  
1101 - *q++ = 0; /* reserved */  
1102 - if (msf) {  
1103 - *q++ = 0; /* reserved */  
1104 - lba_to_msf(q, 0);  
1105 - q += 3;  
1106 - } else {  
1107 - /* sector 0 */  
1108 - cpu_to_ube32(q, 0);  
1109 - q += 4;  
1110 - }  
1111 - }  
1112 - /* lead out track */  
1113 - *q++ = 0; /* reserved */  
1114 - *q++ = 0x16; /* ADR, control */  
1115 - *q++ = 0xaa; /* track number */  
1116 - *q++ = 0; /* reserved */  
1117 - nb_sectors = s->nb_sectors >> 2;  
1118 - if (msf) {  
1119 - *q++ = 0; /* reserved */  
1120 - lba_to_msf(q, nb_sectors);  
1121 - q += 3;  
1122 - } else {  
1123 - cpu_to_ube32(q, nb_sectors);  
1124 - q += 4;  
1125 - }  
1126 - len = q - buf;  
1127 - cpu_to_ube16(buf, len - 2);  
1128 - return len;  
1129 -}  
1130 -  
1131 -/* mostly same info as PearPc */  
1132 -static int cdrom_read_toc_raw(IDEState *s, uint8_t *buf, int msf,  
1133 - int session_num)  
1134 -{  
1135 - uint8_t *q;  
1136 - int nb_sectors, len;  
1137 -  
1138 - q = buf + 2;  
1139 - *q++ = 1; /* first session */  
1140 - *q++ = 1; /* last session */  
1141 -  
1142 - *q++ = 1; /* session number */  
1143 - *q++ = 0x14; /* data track */  
1144 - *q++ = 0; /* track number */  
1145 - *q++ = 0xa0; /* lead-in */  
1146 - *q++ = 0; /* min */  
1147 - *q++ = 0; /* sec */  
1148 - *q++ = 0; /* frame */  
1149 - *q++ = 0;  
1150 - *q++ = 1; /* first track */  
1151 - *q++ = 0x00; /* disk type */  
1152 - *q++ = 0x00;  
1153 -  
1154 - *q++ = 1; /* session number */  
1155 - *q++ = 0x14; /* data track */  
1156 - *q++ = 0; /* track number */  
1157 - *q++ = 0xa1;  
1158 - *q++ = 0; /* min */  
1159 - *q++ = 0; /* sec */  
1160 - *q++ = 0; /* frame */  
1161 - *q++ = 0;  
1162 - *q++ = 1; /* last track */  
1163 - *q++ = 0x00;  
1164 - *q++ = 0x00;  
1165 -  
1166 - *q++ = 1; /* session number */  
1167 - *q++ = 0x14; /* data track */  
1168 - *q++ = 0; /* track number */  
1169 - *q++ = 0xa2; /* lead-out */  
1170 - *q++ = 0; /* min */  
1171 - *q++ = 0; /* sec */  
1172 - *q++ = 0; /* frame */  
1173 - nb_sectors = s->nb_sectors >> 2;  
1174 - if (msf) {  
1175 - *q++ = 0; /* reserved */  
1176 - lba_to_msf(q, nb_sectors);  
1177 - q += 3;  
1178 - } else {  
1179 - cpu_to_ube32(q, nb_sectors);  
1180 - q += 4;  
1181 - }  
1182 -  
1183 - *q++ = 1; /* session number */  
1184 - *q++ = 0x14; /* ADR, control */  
1185 - *q++ = 0; /* track number */  
1186 - *q++ = 1; /* point */  
1187 - *q++ = 0; /* min */  
1188 - *q++ = 0; /* sec */  
1189 - *q++ = 0; /* frame */  
1190 - if (msf) {  
1191 - *q++ = 0;  
1192 - lba_to_msf(q, 0);  
1193 - q += 3;  
1194 - } else {  
1195 - *q++ = 0;  
1196 - *q++ = 0;  
1197 - *q++ = 0;  
1198 - *q++ = 0;  
1199 - }  
1200 -  
1201 - len = q - buf;  
1202 - cpu_to_ube16(buf, len - 2);  
1203 - return len;  
1204 -}  
1205 -  
1206 static void ide_atapi_cmd(IDEState *s) 1085 static void ide_atapi_cmd(IDEState *s)
1207 { 1086 {
1208 const uint8_t *packet; 1087 const uint8_t *packet;
@@ -1449,7 +1328,7 @@ static void ide_atapi_cmd(IDEState *s) @@ -1449,7 +1328,7 @@ static void ide_atapi_cmd(IDEState *s)
1449 start_track = packet[6]; 1328 start_track = packet[6];
1450 switch(format) { 1329 switch(format) {
1451 case 0: 1330 case 0:
1452 - len = cdrom_read_toc(s, buf, msf, start_track); 1331 + len = cdrom_read_toc(s->nb_sectors >> 2, buf, msf, start_track);
1453 if (len < 0) 1332 if (len < 0)
1454 goto error_cmd; 1333 goto error_cmd;
1455 ide_atapi_cmd_reply(s, len, max_len); 1334 ide_atapi_cmd_reply(s, len, max_len);
@@ -1463,7 +1342,7 @@ static void ide_atapi_cmd(IDEState *s) @@ -1463,7 +1342,7 @@ static void ide_atapi_cmd(IDEState *s)
1463 ide_atapi_cmd_reply(s, 12, max_len); 1342 ide_atapi_cmd_reply(s, 12, max_len);
1464 break; 1343 break;
1465 case 2: 1344 case 2:
1466 - len = cdrom_read_toc_raw(s, buf, msf, start_track); 1345 + len = cdrom_read_toc_raw(s->nb_sectors >> 2, buf, msf, start_track);
1467 if (len < 0) 1346 if (len < 0)
1468 goto error_cmd; 1347 goto error_cmd;
1469 ide_atapi_cmd_reply(s, len, max_len); 1348 ide_atapi_cmd_reply(s, len, max_len);
hw/scsi-disk.c 0 → 100644
  1 +/*
  2 + * SCSI Device emulation
  3 + *
  4 + * Copyright (c) 2006 CodeSourcery.
  5 + * Based on code by Fabrice Bellard
  6 + *
  7 + * Written by Paul Brook
  8 + *
  9 + * This code is licenced under the LGPL.
  10 + */
  11 +
  12 +//#define DEBUG_SCSI
  13 +
  14 +#ifdef DEBUG_SCSI
  15 +#define DPRINTF(fmt, args...) \
  16 +do { printf("scsi-disk: " fmt , ##args); } while (0)
  17 +#else
  18 +#define DPRINTF(fmt, args...) do {} while(0)
  19 +#endif
  20 +
  21 +#define BADF(fmt, args...) \
  22 +do { fprintf(stderr, "scsi-disk: " fmt , ##args); } while (0)
  23 +
  24 +#include "vl.h"
  25 +
  26 +#define SENSE_NO_SENSE 0
  27 +#define SENSE_ILLEGAL_REQUEST 5
  28 +
  29 +struct SCSIDevice
  30 +{
  31 + int command;
  32 + uint32_t tag;
  33 + BlockDriverState *bdrv;
  34 + int sector_size;
  35 + /* When transfering data buf_pos and buf_len contain a partially
  36 + transferred block of data (or response to a command), and
  37 + sector/sector_count identify any remaining sectors. */
  38 + /* ??? We should probably keep track of whether the data trasfer is
  39 + a read or a write. Currently we rely on the host getting it right. */
  40 + int sector;
  41 + int sector_count;
  42 + int buf_pos;
  43 + int buf_len;
  44 + int sense;
  45 + char buf[2048];
  46 + scsi_completionfn completion;
  47 + void *opaque;
  48 +};
  49 +
  50 +static void scsi_command_complete(SCSIDevice *s, int sense)
  51 +{
  52 + s->sense = sense;
  53 + s->completion(s->opaque, s->tag, sense != SENSE_NO_SENSE);
  54 +}
  55 +
  56 +/* Read data from a scsi device. Returns nonzero on failure. */
  57 +int scsi_read_data(SCSIDevice *s, uint8_t *data, uint32_t len)
  58 +{
  59 + uint32_t n;
  60 +
  61 + DPRINTF("Read %d (%d/%d)\n", len, s->buf_len, s->sector_count);
  62 + if (s->buf_len == 0 && s->sector_count == 0)
  63 + return 1;
  64 +
  65 + if (s->buf_len) {
  66 + n = s->buf_len;
  67 + if (n > len)
  68 + n = len;
  69 + memcpy(data, s->buf + s->buf_pos, n);
  70 + s->buf_pos += n;
  71 + s->buf_len -= n;
  72 + data += n;
  73 + len -= n;
  74 + if (s->buf_len == 0)
  75 + s->buf_pos = 0;
  76 + }
  77 +
  78 + n = len / s->sector_size;
  79 + if (n > s->sector_count)
  80 + n = s->sector_count;
  81 +
  82 + if (n != 0) {
  83 + bdrv_read(s->bdrv, s->sector, data, n);
  84 + data += n * s->sector_size;
  85 + len -= n * s->sector_size;
  86 + s->sector += n;
  87 + s->sector_count -= n;
  88 + }
  89 +
  90 + if (len && s->sector_count) {
  91 + bdrv_read(s->bdrv, s->sector, s->buf, 1);
  92 + s->sector++;
  93 + s->sector_count--;
  94 + s->buf_pos = 0;
  95 + s->buf_len = s->sector_size;
  96 + /* Recurse to complete the partial read. */
  97 + return scsi_read_data(s, data, len);
  98 + }
  99 +
  100 + if (len != 0)
  101 + return 1;
  102 +
  103 + if (s->buf_len == 0 && s->sector_count == 0)
  104 + scsi_command_complete(s, SENSE_NO_SENSE);
  105 +
  106 + return 0;
  107 +}
  108 +
  109 +/* Read data to a scsi device. Returns nonzero on failure. */
  110 +int scsi_write_data(SCSIDevice *s, uint8_t *data, uint32_t len)
  111 +{
  112 + uint32_t n;
  113 +
  114 + DPRINTF("Write %d (%d/%d)\n", len, s->buf_len, s->sector_count);
  115 + if (s->buf_pos != 0) {
  116 + BADF("Bad state on write\n");
  117 + return 1;
  118 + }
  119 +
  120 + if (s->sector_count == 0)
  121 + return 1;
  122 +
  123 + if (s->buf_len != 0 || len < s->sector_size) {
  124 + n = s->sector_size - s->buf_len;
  125 + if (n > len)
  126 + n = len;
  127 +
  128 + memcpy(s->buf + s->buf_len, data, n);
  129 + data += n;
  130 + s->buf_len += n;
  131 + len -= n;
  132 + if (s->buf_len == s->sector_size) {
  133 + /* A full sector has been accumulated. Write it to disk. */
  134 + bdrv_write(s->bdrv, s->sector, s->buf, 1);
  135 + s->buf_len = 0;
  136 + s->sector++;
  137 + s->sector_count--;
  138 + }
  139 + }
  140 +
  141 + n = len / s->sector_size;
  142 + if (n > s->sector_count)
  143 + n = s->sector_count;
  144 +
  145 + if (n != 0) {
  146 + bdrv_write(s->bdrv, s->sector, data, n);
  147 + data += n * s->sector_size;
  148 + len -= n * s->sector_size;
  149 + s->sector += n;
  150 + s->sector_count -= n;
  151 + }
  152 +
  153 + if (len >= s->sector_size)
  154 + return 1;
  155 +
  156 + if (len && s->sector_count) {
  157 + /* Recurse to complete the partial write. */
  158 + return scsi_write_data(s, data, len);
  159 + }
  160 +
  161 + if (len != 0)
  162 + return 1;
  163 +
  164 + if (s->sector_count == 0)
  165 + scsi_command_complete(s, SENSE_NO_SENSE);
  166 +
  167 + return 0;
  168 +}
  169 +
  170 +/* Execute a scsi command. Returns the length of the data expected by the
  171 + command. This will be Positive for data transfers from the device
  172 + (eg. disk reads), negative for transfers to the device (eg. disk writes),
  173 + and zero if the command does not transfer any data. */
  174 +
  175 +int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf)
  176 +{
  177 + int64_t nb_sectors;
  178 + uint32_t lba;
  179 + uint32_t len;
  180 + int cmdlen;
  181 + int is_write;
  182 +
  183 + s->command = buf[0];
  184 + s->tag = tag;
  185 + s->sector_count = 0;
  186 + s->buf_pos = 0;
  187 + s->buf_len = 0;
  188 + is_write = 0;
  189 + DPRINTF("Command: 0x%02x", buf[0]);
  190 + switch (s->command >> 5) {
  191 + case 0:
  192 + lba = buf[3] | (buf[2] << 8) | ((buf[1] & 0x1f) << 16);
  193 + len = buf[4];
  194 + cmdlen = 6;
  195 + break;
  196 + case 1:
  197 + case 2:
  198 + lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
  199 + len = buf[8] | (buf[7] << 8);
  200 + cmdlen = 10;
  201 + break;
  202 + case 4:
  203 + lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
  204 + len = buf[13] | (buf[12] << 8) | (buf[11] << 16) | (buf[10] << 24);
  205 + cmdlen = 16;
  206 + break;
  207 + case 5:
  208 + lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
  209 + len = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24);
  210 + cmdlen = 12;
  211 + break;
  212 + default:
  213 + BADF("Unsupported command length\n");
  214 + goto fail;
  215 + }
  216 +#ifdef DEBUG_SCSI
  217 + {
  218 + int i;
  219 + for (i = 1; i < cmdlen; i++) {
  220 + printf(" 0x%02x", buf[i]);
  221 + }
  222 + printf("\n");
  223 + }
  224 +#endif
  225 + if (buf[1] >> 5) {
  226 + /* Only LUN 0 supported. */
  227 + goto fail;
  228 + }
  229 + switch (s->command) {
  230 + case 0x0:
  231 + DPRINTF("Test Unit Ready\n");
  232 + break;
  233 + case 0x03:
  234 + DPRINTF("Request Sense (len %d)\n", len);
  235 + if (len < 4)
  236 + goto fail;
  237 + memset(buf, 0, 4);
  238 + s->buf[0] = 0xf0;
  239 + s->buf[1] = 0;
  240 + s->buf[2] = s->sense;
  241 + s->buf_len = 4;
  242 + break;
  243 + case 0x12:
  244 + DPRINTF("Inquiry (len %d)\n", len);
  245 + if (len < 36) {
  246 + BADF("Inquiry buffer too small (%d)\n", len);
  247 + }
  248 + memset(s->buf, 0, 36);
  249 + if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
  250 + s->buf[0] = 5;
  251 + s->buf[1] = 0x80;
  252 + memcpy(&s->buf[16], "QEMU CDROM ", 16);
  253 + } else {
  254 + s->buf[0] = 0;
  255 + memcpy(&s->buf[16], "QEMU HARDDISK ", 16);
  256 + }
  257 + memcpy(&s->buf[8], "QEMU ", 8);
  258 + s->buf[2] = 3; /* SCSI-3 */
  259 + s->buf[3] = 2; /* Format 2 */
  260 + s->buf[4] = 32;
  261 + s->buf_len = 36;
  262 + break;
  263 + case 0x16:
  264 + DPRINTF("Reserve(6)\n");
  265 + if (buf[1] & 1)
  266 + goto fail;
  267 + break;
  268 + case 0x17:
  269 + DPRINTF("Release(6)\n");
  270 + if (buf[1] & 1)
  271 + goto fail;
  272 + break;
  273 + case 0x1a:
  274 + DPRINTF("Mode Sense(6) (page %d, len %d)\n", buf[2], len);
  275 + memset(s->buf, 0, 4);
  276 + s->buf[0] = 0x16; /* Mode data length (4 + 0x12). */
  277 + s->buf[1] = 0; /* Default media type. */
  278 + s->buf[2] = 0; /* Write enabled. */
  279 + s->buf[3] = 0; /* Block descriptor length. */
  280 + /* Caching page. */
  281 + s->buf[4 + 0] = 8;
  282 + s->buf[4 + 1] = 0x12;
  283 + s->buf[4 + 2] = 4; /* WCE */
  284 + if (len > 0x16)
  285 + len = 0x16;
  286 + s->buf_len = len;
  287 + break;
  288 + case 0x25:
  289 + DPRINTF("Read Capacity\n");
  290 + /* The normal LEN field for this command is zero. */
  291 + memset(s->buf, 0, 8);
  292 + bdrv_get_geometry(s->bdrv, &nb_sectors);
  293 + s->buf[0] = (nb_sectors >> 24) & 0xff;
  294 + s->buf[1] = (nb_sectors >> 16) & 0xff;
  295 + s->buf[2] = (nb_sectors >> 8) & 0xff;
  296 + s->buf[3] = nb_sectors & 0xff;
  297 + s->buf[4] = 0;
  298 + s->buf[5] = 0;
  299 + s->buf[6] = s->sector_size >> 8;
  300 + s->buf[7] = s->sector_size & 0xff;
  301 + s->buf_len = 8;
  302 + break;
  303 + case 0x08:
  304 + case 0x28:
  305 + DPRINTF("Read (sector %d, count %d)\n", lba, len);
  306 + s->sector = lba;
  307 + s->sector_count = len;
  308 + break;
  309 + case 0x0a:
  310 + case 0x2a:
  311 + DPRINTF("Write (sector %d, count %d)\n", lba, len);
  312 + s->sector = lba;
  313 + s->sector_count = len;
  314 + is_write = 1;
  315 + break;
  316 + case 0x43:
  317 + {
  318 + int start_track, format, msf;
  319 +
  320 + msf = buf[1] & 2;
  321 + format = buf[2] & 0xf;
  322 + start_track = buf[6];
  323 + bdrv_get_geometry(s->bdrv, &nb_sectors);
  324 + DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
  325 + switch(format) {
  326 + case 0:
  327 + len = cdrom_read_toc(nb_sectors, s->buf, msf, start_track);
  328 + if (len < 0)
  329 + goto error_cmd;
  330 + s->buf_len = len;
  331 + break;
  332 + case 1:
  333 + /* multi session : only a single session defined */
  334 + memset(s->buf, 0, 12);
  335 + s->buf[1] = 0x0a;
  336 + s->buf[2] = 0x01;
  337 + s->buf[3] = 0x01;
  338 + s->buf_len = 12;
  339 + break;
  340 + case 2:
  341 + len = cdrom_read_toc_raw(nb_sectors, s->buf, msf, start_track);
  342 + if (len < 0)
  343 + goto error_cmd;
  344 + s->buf_len = len;
  345 + break;
  346 + default:
  347 + error_cmd:
  348 + DPRINTF("Read TOC error\n");
  349 + goto fail;
  350 + }
  351 + break;
  352 + }
  353 + case 0x56:
  354 + DPRINTF("Reserve(10)\n");
  355 + if (buf[1] & 3)
  356 + goto fail;
  357 + break;
  358 + case 0x57:
  359 + DPRINTF("Release(10)\n");
  360 + if (buf[1] & 3)
  361 + goto fail;
  362 + break;
  363 + case 0xa0:
  364 + DPRINTF("Report LUNs (len %d)\n", len);
  365 + if (len < 16)
  366 + goto fail;
  367 + memset(s->buf, 0, 16);
  368 + s->buf[3] = 8;
  369 + s->buf_len = 16;
  370 + break;
  371 + default:
  372 + DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
  373 + fail:
  374 + scsi_command_complete(s, SENSE_ILLEGAL_REQUEST);
  375 + return 0;
  376 + }
  377 + if (s->sector_count == 0 && s->buf_len == 0) {
  378 + scsi_command_complete(s, SENSE_NO_SENSE);
  379 + }
  380 + len = s->sector_count * s->sector_size + s->buf_len;
  381 + return is_write ? -len : len;
  382 +}
  383 +
  384 +void scsi_disk_destroy(SCSIDevice *s)
  385 +{
  386 + bdrv_close(s->bdrv);
  387 + qemu_free(s);
  388 +}
  389 +
  390 +SCSIDevice *scsi_disk_init(BlockDriverState *bdrv,
  391 + scsi_completionfn completion,
  392 + void *opaque)
  393 +{
  394 + SCSIDevice *s;
  395 +
  396 + s = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
  397 + s->bdrv = bdrv;
  398 + s->completion = completion;
  399 + s->opaque = opaque;
  400 + if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
  401 + s->sector_size = 2048;
  402 + } else {
  403 + s->sector_size = 512;
  404 + }
  405 +
  406 + return s;
  407 +}
  408 +
hw/usb-hid.c
@@ -323,10 +323,16 @@ static int usb_tablet_poll(USBMouseState *s, uint8_t *buf, int len) @@ -323,10 +323,16 @@ static int usb_tablet_poll(USBMouseState *s, uint8_t *buf, int len)
323 return l; 323 return l;
324 } 324 }
325 325
326 -static void usb_mouse_handle_reset(USBDevice *dev) 326 +static void usb_mouse_handle_reset(USBDevice *dev, int destroy)
327 { 327 {
328 USBMouseState *s = (USBMouseState *)dev; 328 USBMouseState *s = (USBMouseState *)dev;
329 329
  330 + if (destroy) {
  331 + qemu_add_mouse_event_handler(NULL, NULL, 0);
  332 + qemu_free(s);
  333 + return;
  334 + }
  335 +
330 s->dx = 0; 336 s->dx = 0;
331 s->dy = 0; 337 s->dy = 0;
332 s->dz = 0; 338 s->dz = 0;
hw/usb-hub.c
@@ -199,9 +199,11 @@ static void usb_hub_attach(USBPort *port1, USBDevice *dev) @@ -199,9 +199,11 @@ static void usb_hub_attach(USBPort *port1, USBDevice *dev)
199 } 199 }
200 } 200 }
201 201
202 -static void usb_hub_handle_reset(USBDevice *dev) 202 +static void usb_hub_handle_reset(USBDevice *dev, int destroy)
203 { 203 {
204 /* XXX: do it */ 204 /* XXX: do it */
  205 + if (destroy)
  206 + qemu_free(dev);
205 } 207 }
206 208
207 static int usb_hub_handle_control(USBDevice *dev, int request, int value, 209 static int usb_hub_handle_control(USBDevice *dev, int request, int value,
hw/usb-msd.c 0 → 100644
  1 +/*
  2 + * USB Mass Storage Device emulation
  3 + *
  4 + * Copyright (c) 2006 CodeSourcery.
  5 + * Written by Paul Brook
  6 + *
  7 + * This code is licenced under the LGPL.
  8 + */
  9 +
  10 +#include "vl.h"
  11 +
  12 +//#define DEBUG_MSD
  13 +
  14 +#ifdef DEBUG_MSD
  15 +#define DPRINTF(fmt, args...) \
  16 +do { printf("usb-msd: " fmt , ##args); } while (0)
  17 +#else
  18 +#define DPRINTF(fmt, args...) do {} while(0)
  19 +#endif
  20 +
  21 +/* USB requests. */
  22 +#define MassStorageReset 0xff
  23 +#define GetMaxLun 0xfe
  24 +
  25 +enum USBMSDMode {
  26 + USB_MSDM_CBW, /* Command Block. */
  27 + USB_MSDM_DATAOUT, /* Tranfer data to device. */
  28 + USB_MSDM_DATAIN, /* Transfer data from device. */
  29 + USB_MSDM_CSW /* Command Status. */
  30 +};
  31 +
  32 +typedef struct {
  33 + USBDevice dev;
  34 + enum USBMSDMode mode;
  35 + uint32_t data_len;
  36 + uint32_t tag;
  37 + SCSIDevice *scsi_dev;
  38 + int result;
  39 +} MSDState;
  40 +
  41 +static const uint8_t qemu_msd_dev_descriptor[] = {
  42 + 0x12, /* u8 bLength; */
  43 + 0x01, /* u8 bDescriptorType; Device */
  44 + 0x10, 0x00, /* u16 bcdUSB; v1.0 */
  45 +
  46 + 0x00, /* u8 bDeviceClass; */
  47 + 0x00, /* u8 bDeviceSubClass; */
  48 + 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
  49 + 0x08, /* u8 bMaxPacketSize0; 8 Bytes */
  50 +
  51 + /* Vendor and product id are arbitrary. */
  52 + 0x00, 0x00, /* u16 idVendor; */
  53 + 0x00, 0x00, /* u16 idProduct; */
  54 + 0x00, 0x00, /* u16 bcdDevice */
  55 +
  56 + 0x01, /* u8 iManufacturer; */
  57 + 0x02, /* u8 iProduct; */
  58 + 0x03, /* u8 iSerialNumber; */
  59 + 0x01 /* u8 bNumConfigurations; */
  60 +};
  61 +
  62 +static const uint8_t qemu_msd_config_descriptor[] = {
  63 +
  64 + /* one configuration */
  65 + 0x09, /* u8 bLength; */
  66 + 0x02, /* u8 bDescriptorType; Configuration */
  67 + 0x20, 0x00, /* u16 wTotalLength; */
  68 + 0x01, /* u8 bNumInterfaces; (1) */
  69 + 0x01, /* u8 bConfigurationValue; */
  70 + 0x00, /* u8 iConfiguration; */
  71 + 0xc0, /* u8 bmAttributes;
  72 + Bit 7: must be set,
  73 + 6: Self-powered,
  74 + 5: Remote wakeup,
  75 + 4..0: resvd */
  76 + 0x00, /* u8 MaxPower; */
  77 +
  78 + /* one interface */
  79 + 0x09, /* u8 if_bLength; */
  80 + 0x04, /* u8 if_bDescriptorType; Interface */
  81 + 0x00, /* u8 if_bInterfaceNumber; */
  82 + 0x00, /* u8 if_bAlternateSetting; */
  83 + 0x02, /* u8 if_bNumEndpoints; */
  84 + 0x08, /* u8 if_bInterfaceClass; MASS STORAGE */
  85 + 0x06, /* u8 if_bInterfaceSubClass; SCSI */
  86 + 0x50, /* u8 if_bInterfaceProtocol; Bulk Only */
  87 + 0x00, /* u8 if_iInterface; */
  88 +
  89 + /* Bulk-In endpoint */
  90 + 0x07, /* u8 ep_bLength; */
  91 + 0x05, /* u8 ep_bDescriptorType; Endpoint */
  92 + 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
  93 + 0x02, /* u8 ep_bmAttributes; Bulk */
  94 + 0x40, 0x00, /* u16 ep_wMaxPacketSize; */
  95 + 0x00, /* u8 ep_bInterval; */
  96 +
  97 + /* Bulk-Out endpoint */
  98 + 0x07, /* u8 ep_bLength; */
  99 + 0x05, /* u8 ep_bDescriptorType; Endpoint */
  100 + 0x02, /* u8 ep_bEndpointAddress; OUT Endpoint 2 */
  101 + 0x02, /* u8 ep_bmAttributes; Bulk */
  102 + 0x40, 0x00, /* u16 ep_wMaxPacketSize; */
  103 + 0x00 /* u8 ep_bInterval; */
  104 +};
  105 +
  106 +static void usb_msd_command_complete(void *opaque, uint32_t tag, int fail)
  107 +{
  108 + MSDState *s = (MSDState *)opaque;
  109 +
  110 + DPRINTF("Command complete\n");
  111 + s->result = fail;
  112 + s->mode = USB_MSDM_CSW;
  113 +}
  114 +
  115 +static void usb_msd_handle_reset(USBDevice *dev, int destroy)
  116 +{
  117 + MSDState *s = (MSDState *)dev;
  118 +
  119 + DPRINTF("Reset\n");
  120 + s->mode = USB_MSDM_CBW;
  121 + if (destroy) {
  122 + scsi_disk_destroy(s->scsi_dev);
  123 + qemu_free(s);
  124 + }
  125 +}
  126 +
  127 +static int usb_msd_handle_control(USBDevice *dev, int request, int value,
  128 + int index, int length, uint8_t *data)
  129 +{
  130 + MSDState *s = (MSDState *)dev;
  131 + int ret = 0;
  132 +
  133 + switch (request) {
  134 + case DeviceRequest | USB_REQ_GET_STATUS:
  135 + data[0] = (1 << USB_DEVICE_SELF_POWERED) |
  136 + (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
  137 + data[1] = 0x00;
  138 + ret = 2;
  139 + break;
  140 + case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
  141 + if (value == USB_DEVICE_REMOTE_WAKEUP) {
  142 + dev->remote_wakeup = 0;
  143 + } else {
  144 + goto fail;
  145 + }
  146 + ret = 0;
  147 + break;
  148 + case DeviceOutRequest | USB_REQ_SET_FEATURE:
  149 + if (value == USB_DEVICE_REMOTE_WAKEUP) {
  150 + dev->remote_wakeup = 1;
  151 + } else {
  152 + goto fail;
  153 + }
  154 + ret = 0;
  155 + break;
  156 + case DeviceOutRequest | USB_REQ_SET_ADDRESS:
  157 + dev->addr = value;
  158 + ret = 0;
  159 + break;
  160 + case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
  161 + switch(value >> 8) {
  162 + case USB_DT_DEVICE:
  163 + memcpy(data, qemu_msd_dev_descriptor,
  164 + sizeof(qemu_msd_dev_descriptor));
  165 + ret = sizeof(qemu_msd_dev_descriptor);
  166 + break;
  167 + case USB_DT_CONFIG:
  168 + memcpy(data, qemu_msd_config_descriptor,
  169 + sizeof(qemu_msd_config_descriptor));
  170 + ret = sizeof(qemu_msd_config_descriptor);
  171 + break;
  172 + case USB_DT_STRING:
  173 + switch(value & 0xff) {
  174 + case 0:
  175 + /* language ids */
  176 + data[0] = 4;
  177 + data[1] = 3;
  178 + data[2] = 0x09;
  179 + data[3] = 0x04;
  180 + ret = 4;
  181 + break;
  182 + case 1:
  183 + /* vendor description */
  184 + ret = set_usb_string(data, "QEMU " QEMU_VERSION);
  185 + break;
  186 + case 2:
  187 + /* product description */
  188 + ret = set_usb_string(data, "QEMU USB HARDDRIVE");
  189 + break;
  190 + case 3:
  191 + /* serial number */
  192 + ret = set_usb_string(data, "1");
  193 + break;
  194 + default:
  195 + goto fail;
  196 + }
  197 + break;
  198 + default:
  199 + goto fail;
  200 + }
  201 + break;
  202 + case DeviceRequest | USB_REQ_GET_CONFIGURATION:
  203 + data[0] = 1;
  204 + ret = 1;
  205 + break;
  206 + case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
  207 + ret = 0;
  208 + break;
  209 + case DeviceRequest | USB_REQ_GET_INTERFACE:
  210 + data[0] = 0;
  211 + ret = 1;
  212 + break;
  213 + case DeviceOutRequest | USB_REQ_SET_INTERFACE:
  214 + ret = 0;
  215 + break;
  216 + case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
  217 + if (value == 0 && index != 0x81) { /* clear ep halt */
  218 + goto fail;
  219 + }
  220 + ret = 0;
  221 + break;
  222 + /* Class specific requests. */
  223 + case MassStorageReset:
  224 + /* Reset state ready for the next CBW. */
  225 + s->mode = USB_MSDM_CBW;
  226 + ret = 0;
  227 + break;
  228 + case GetMaxLun:
  229 + data[0] = 0;
  230 + ret = 1;
  231 + break;
  232 + default:
  233 + fail:
  234 + ret = USB_RET_STALL;
  235 + break;
  236 + }
  237 + return ret;
  238 +}
  239 +
  240 +struct usb_msd_cbw {
  241 + uint32_t sig;
  242 + uint32_t tag;
  243 + uint32_t data_len;
  244 + uint8_t flags;
  245 + uint8_t lun;
  246 + uint8_t cmd_len;
  247 + uint8_t cmd[16];
  248 +};
  249 +
  250 +struct usb_msd_csw {
  251 + uint32_t sig;
  252 + uint32_t tag;
  253 + uint32_t residue;
  254 + uint8_t status;
  255 +};
  256 +
  257 +static int usb_msd_handle_data(USBDevice *dev, int pid, uint8_t devep,
  258 + uint8_t *data, int len)
  259 +{
  260 + MSDState *s = (MSDState *)dev;
  261 + int ret = 0;
  262 + struct usb_msd_cbw cbw;
  263 + struct usb_msd_csw csw;
  264 +
  265 + switch (pid) {
  266 + case USB_TOKEN_OUT:
  267 + if (devep != 2)
  268 + goto fail;
  269 +
  270 + switch (s->mode) {
  271 + case USB_MSDM_CBW:
  272 + if (len != 31) {
  273 + fprintf(stderr, "usb-msd: Bad CBW size");
  274 + goto fail;
  275 + }
  276 + memcpy(&cbw, data, 31);
  277 + if (le32_to_cpu(cbw.sig) != 0x43425355) {
  278 + fprintf(stderr, "usb-msd: Bad signature %08x\n",
  279 + le32_to_cpu(cbw.sig));
  280 + goto fail;
  281 + }
  282 + DPRINTF("Command on LUN %d\n", cbw.lun);
  283 + if (cbw.lun != 0) {
  284 + fprintf(stderr, "usb-msd: Bad LUN %d\n", cbw.lun);
  285 + goto fail;
  286 + }
  287 + s->tag = le32_to_cpu(cbw.tag);
  288 + s->data_len = le32_to_cpu(cbw.data_len);
  289 + if (s->data_len == 0) {
  290 + s->mode = USB_MSDM_CSW;
  291 + } else if (cbw.flags & 0x80) {
  292 + s->mode = USB_MSDM_DATAIN;
  293 + } else {
  294 + s->mode = USB_MSDM_DATAOUT;
  295 + }
  296 + DPRINTF("Command tag 0x%x flags %08x len %d data %d\n",
  297 + s->tag, cbw.flags, cbw.cmd_len, s->data_len);
  298 + scsi_send_command(s->scsi_dev, s->tag, cbw.cmd);
  299 + ret = len;
  300 + break;
  301 +
  302 + case USB_MSDM_DATAOUT:
  303 + DPRINTF("Data out %d/%d\n", len, s->data_len);
  304 + if (len > s->data_len)
  305 + goto fail;
  306 +
  307 + if (scsi_write_data(s->scsi_dev, data, len))
  308 + goto fail;
  309 +
  310 + s->data_len -= len;
  311 + if (s->data_len == 0)
  312 + s->mode = USB_MSDM_CSW;
  313 + ret = len;
  314 + break;
  315 +
  316 + default:
  317 + DPRINTF("Unexpected write (len %d)\n", len);
  318 + goto fail;
  319 + }
  320 + break;
  321 +
  322 + case USB_TOKEN_IN:
  323 + if (devep != 1)
  324 + goto fail;
  325 +
  326 + switch (s->mode) {
  327 + case USB_MSDM_CSW:
  328 + DPRINTF("Command status %d tag 0x%x, len %d\n",
  329 + s->result, s->tag, len);
  330 + if (len < 13)
  331 + goto fail;
  332 +
  333 + csw.sig = cpu_to_le32(0x53425355);
  334 + csw.tag = cpu_to_le32(s->tag);
  335 + csw.residue = 0;
  336 + csw.status = s->result;
  337 + memcpy(data, &csw, 13);
  338 + ret = 13;
  339 + s->mode = USB_MSDM_CBW;
  340 + break;
  341 +
  342 + case USB_MSDM_DATAIN:
  343 + DPRINTF("Data in %d/%d\n", len, s->data_len);
  344 + if (len > s->data_len)
  345 + len = s->data_len;
  346 +
  347 + if (scsi_read_data(s->scsi_dev, data, len))
  348 + goto fail;
  349 +
  350 + s->data_len -= len;
  351 + if (s->data_len == 0)
  352 + s->mode = USB_MSDM_CSW;
  353 + ret = len;
  354 + break;
  355 +
  356 + default:
  357 + DPRINTF("Unexpected read (len %d)\n", len);
  358 + goto fail;
  359 + }
  360 + break;
  361 +
  362 + default:
  363 + DPRINTF("Bad token\n");
  364 + fail:
  365 + ret = USB_RET_STALL;
  366 + break;
  367 + }
  368 +
  369 + return ret;
  370 +}
  371 +
  372 +
  373 +USBDevice *usb_msd_init(const char *filename)
  374 +{
  375 + MSDState *s;
  376 + BlockDriverState *bdrv;
  377 +
  378 + s = qemu_mallocz(sizeof(MSDState));
  379 + if (!s)
  380 + return NULL;
  381 +
  382 + bdrv = bdrv_new("usb");
  383 + bdrv_open(bdrv, filename, 0);
  384 +
  385 + s->dev.speed = USB_SPEED_FULL;
  386 + s->dev.handle_packet = usb_generic_handle_packet;
  387 +
  388 + s->dev.handle_reset = usb_msd_handle_reset;
  389 + s->dev.handle_control = usb_msd_handle_control;
  390 + s->dev.handle_data = usb_msd_handle_data;
  391 +
  392 + s->scsi_dev = scsi_disk_init(bdrv, usb_msd_command_complete, s);
  393 + usb_msd_handle_reset((USBDevice *)s, 0);
  394 + return (USBDevice *)s;
  395 +}
hw/usb.c
@@ -55,7 +55,10 @@ int usb_generic_handle_packet(USBDevice *s, int pid, @@ -55,7 +55,10 @@ int usb_generic_handle_packet(USBDevice *s, int pid,
55 s->remote_wakeup = 0; 55 s->remote_wakeup = 0;
56 s->addr = 0; 56 s->addr = 0;
57 s->state = USB_STATE_DEFAULT; 57 s->state = USB_STATE_DEFAULT;
58 - s->handle_reset(s); 58 + s->handle_reset(s, 0);
  59 + break;
  60 + case USB_MSG_DESTROY:
  61 + s->handle_reset(s, 1);
59 break; 62 break;
60 case USB_TOKEN_SETUP: 63 case USB_TOKEN_SETUP:
61 if (s->state < USB_STATE_DEFAULT || devaddr != s->addr) 64 if (s->state < USB_STATE_DEFAULT || devaddr != s->addr)
hw/usb.h
@@ -29,6 +29,7 @@ @@ -29,6 +29,7 @@
29 #define USB_MSG_ATTACH 0x100 29 #define USB_MSG_ATTACH 0x100
30 #define USB_MSG_DETACH 0x101 30 #define USB_MSG_DETACH 0x101
31 #define USB_MSG_RESET 0x102 31 #define USB_MSG_RESET 0x102
  32 +#define USB_MSG_DESTROY 0x103
32 33
33 #define USB_RET_NODEV (-1) 34 #define USB_RET_NODEV (-1)
34 #define USB_RET_NAK (-2) 35 #define USB_RET_NAK (-2)
@@ -121,7 +122,7 @@ struct USBDevice { @@ -121,7 +122,7 @@ struct USBDevice {
121 /* The following fields are used by the generic USB device 122 /* The following fields are used by the generic USB device
122 layer. They are here just to avoid creating a new structure for 123 layer. They are here just to avoid creating a new structure for
123 them. */ 124 them. */
124 - void (*handle_reset)(USBDevice *dev); 125 + void (*handle_reset)(USBDevice *dev, int destroy);
125 int (*handle_control)(USBDevice *dev, int request, int value, 126 int (*handle_control)(USBDevice *dev, int request, int value,
126 int index, int length, uint8_t *data); 127 int index, int length, uint8_t *data);
127 int (*handle_data)(USBDevice *dev, int pid, uint8_t devep, 128 int (*handle_data)(USBDevice *dev, int pid, uint8_t devep,
@@ -170,3 +171,6 @@ void usb_host_info(void); @@ -170,3 +171,6 @@ void usb_host_info(void);
170 /* usb-hid.c */ 171 /* usb-hid.c */
171 USBDevice *usb_mouse_init(void); 172 USBDevice *usb_mouse_init(void);
172 USBDevice *usb_tablet_init(void); 173 USBDevice *usb_tablet_init(void);
  174 +
  175 +/* usb-msd.c */
  176 +USBDevice *usb_msd_init(const char *filename);
usb-linux.c
@@ -55,7 +55,7 @@ typedef struct USBHostDevice { @@ -55,7 +55,7 @@ typedef struct USBHostDevice {
55 int fd; 55 int fd;
56 } USBHostDevice; 56 } USBHostDevice;
57 57
58 -static void usb_host_handle_reset(USBDevice *dev) 58 +static void usb_host_handle_reset(USBDevice *dev, int destroy)
59 { 59 {
60 #if 0 60 #if 0
61 USBHostDevice *s = (USBHostDevice *)dev; 61 USBHostDevice *s = (USBHostDevice *)dev;
@@ -3279,6 +3279,8 @@ static int usb_device_add(const char *devname) @@ -3279,6 +3279,8 @@ static int usb_device_add(const char *devname)
3279 dev = usb_mouse_init(); 3279 dev = usb_mouse_init();
3280 } else if (!strcmp(devname, "tablet")) { 3280 } else if (!strcmp(devname, "tablet")) {
3281 dev = usb_tablet_init(); 3281 dev = usb_tablet_init();
  3282 + } else if (strstart(devname, "disk:", &p)) {
  3283 + dev = usb_msd_init(p);
3282 } else { 3284 } else {
3283 return -1; 3285 return -1;
3284 } 3286 }
@@ -761,6 +761,10 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn); @@ -761,6 +761,10 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn);
761 int pmac_ide_init (BlockDriverState **hd_table, 761 int pmac_ide_init (BlockDriverState **hd_table,
762 SetIRQFunc *set_irq, void *irq_opaque, int irq); 762 SetIRQFunc *set_irq, void *irq_opaque, int irq);
763 763
  764 +/* cdrom.c */
  765 +int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);
  766 +int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num);
  767 +
764 /* es1370.c */ 768 /* es1370.c */
765 int es1370_init (PCIBus *bus, AudioState *s); 769 int es1370_init (PCIBus *bus, AudioState *s);
766 770
@@ -1031,6 +1035,19 @@ void do_usb_add(const char *devname); @@ -1031,6 +1035,19 @@ void do_usb_add(const char *devname);
1031 void do_usb_del(const char *devname); 1035 void do_usb_del(const char *devname);
1032 void usb_info(void); 1036 void usb_info(void);
1033 1037
  1038 +/* scsi-disk.c */
  1039 +typedef struct SCSIDevice SCSIDevice;
  1040 +typedef void (*scsi_completionfn)(void *, uint32_t, int);
  1041 +
  1042 +SCSIDevice *scsi_disk_init(BlockDriverState *bdrv,
  1043 + scsi_completionfn completion,
  1044 + void *opaque);
  1045 +void scsi_disk_destroy(SCSIDevice *s);
  1046 +
  1047 +int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf);
  1048 +int scsi_read_data(SCSIDevice *s, uint8_t *data, uint32_t len);
  1049 +int scsi_write_data(SCSIDevice *s, uint8_t *data, uint32_t len);
  1050 +
1034 /* integratorcp.c */ 1051 /* integratorcp.c */
1035 extern QEMUMachine integratorcp926_machine; 1052 extern QEMUMachine integratorcp926_machine;
1036 extern QEMUMachine integratorcp1026_machine; 1053 extern QEMUMachine integratorcp1026_machine;