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 306 SOUND_HW += fmopl.o adlib.o
307 307 endif
308 308  
  309 +# SCSI layer
  310 +VL_OBJS+= scsi-disk.o cdrom.o
  311 +
309 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 315 # PCI network cards
313 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 38 #define ESPDMA_REGS 4
39 39 #define ESPDMA_MAXADDR (ESPDMA_REGS * 4 - 1)
40 40 #define ESP_MAXREG 0x3f
41   -#define TI_BUFSZ 1024*1024 // XXX
  41 +#define TI_BUFSZ 32
42 42 #define DMA_VER 0xa0000000
43 43 #define DMA_INTR 1
44 44 #define DMA_INTREN 0x10
  45 +#define DMA_WRITE_MEM 0x100
45 46 #define DMA_LOADED 0x04000000
46 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 49 struct ESPState {
53 50 BlockDriverState **bd;
54 51 uint8_t rregs[ESP_MAXREG];
... ... @@ -57,12 +54,10 @@ struct ESPState {
57 54 uint32_t espdmaregs[ESPDMA_REGS];
58 55 uint32_t ti_size;
59 56 uint32_t ti_rptr, ti_wptr;
60   - int ti_dir;
61 57 uint8_t ti_buf[TI_BUFSZ];
62 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 63 #define STAT_DO 0x00
... ... @@ -83,195 +78,33 @@ struct ESPState {
83 78 #define SEQ_0 0x0
84 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 81 static void handle_satn(ESPState *s)
247 82 {
248 83 uint8_t buf[32];
249 84 uint32_t dmaptr, dmalen;
250   - unsigned int i;
251   - int64_t nb_sectors;
252 85 int target;
  86 + int32_t datalen;
253 87  
254 88 dmalen = s->wregs[0] | (s->wregs[1] << 8);
255 89 target = s->wregs[4] & 7;
256 90 DPRINTF("Select with ATN len %d target %d\n", dmalen, target);
257 91 if (s->dma) {
258 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 95 cpu_physical_memory_read(dmaptr, buf, dmalen);
261 96 } else {
262 97 buf[0] = 0;
263 98 memcpy(&buf[1], s->ti_buf, dmalen);
264 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 102 s->ti_size = 0;
271 103 s->ti_rptr = 0;
272 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 108 s->rregs[4] = STAT_IN;
276 109 s->rregs[5] = INTR_DC;
277 110 s->rregs[6] = SEQ_0;
... ... @@ -279,141 +112,20 @@ static void handle_satn(ESPState *s)
279 112 pic_set_irq(s->irq, 1);
280 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 129 s->rregs[5] = INTR_BS | INTR_FC;
418 130 s->rregs[6] = SEQ_CD;
419 131 s->espdmaregs[0] |= DMA_INTR;
... ... @@ -427,7 +139,8 @@ static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len)
427 139 DPRINTF("Transfer status len %d\n", len);
428 140 if (s->dma) {
429 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 144 cpu_physical_memory_write(dmaptr, buf, len);
432 145 s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
433 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 159  
447 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 176 static void handle_ti(ESPState *s)
450 177 {
451 178 uint32_t dmaptr, dmalen, minlen, len, from, to;
452 179 unsigned int i;
  180 + int to_device;
  181 + uint8_t buf[TARGET_PAGE_SIZE];
453 182  
454 183 dmalen = s->wregs[0] | (s->wregs[1] << 8);
455 184 if (dmalen==0) {
... ... @@ -460,7 +189,10 @@ static void handle_ti(ESPState *s)
460 189 DPRINTF("Transfer Information len %d\n", minlen);
461 190 if (s->dma) {
462 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 196 from = s->espdmaregs[1];
465 197 to = from + minlen;
466 198 for (i = 0; i < minlen; i += len, from += len) {
... ... @@ -471,35 +203,23 @@ static void handle_ti(ESPState *s)
471 203 len = to - from;
472 204 }
473 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 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 219 s->rregs[5] = INTR_BS;
495 220 s->rregs[6] = 0;
496 221 s->rregs[7] = 0;
497 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 224 pic_set_irq(s->irq, 1);
505 225 }
... ... @@ -514,9 +234,7 @@ static void esp_reset(void *opaque)
514 234 s->ti_size = 0;
515 235 s->ti_rptr = 0;
516 236 s->ti_wptr = 0;
517   - s->ti_dir = 0;
518 237 s->dma = 0;
519   - s->dma_cb = NULL;
520 238 }
521 239  
522 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 249 // FIFO
532 250 if (s->ti_size > 0) {
533 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 258 pic_set_irq(s->irq, 1);
536 259 }
537 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 289 break;
567 290 case 2:
568 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 301 break;
572 302 case 3:
573 303 s->rregs[saddr] = val;
... ... @@ -723,7 +453,6 @@ static void esp_save(QEMUFile *f, void *opaque)
723 453 qemu_put_be32s(f, &s->ti_size);
724 454 qemu_put_be32s(f, &s->ti_rptr);
725 455 qemu_put_be32s(f, &s->ti_wptr);
726   - qemu_put_be32s(f, &s->ti_dir);
727 456 qemu_put_buffer(f, s->ti_buf, TI_BUFSZ);
728 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 473 qemu_get_be32s(f, &s->ti_size);
745 474 qemu_get_be32s(f, &s->ti_rptr);
746 475 qemu_get_be32s(f, &s->ti_wptr);
747   - qemu_get_be32s(f, &s->ti_dir);
748 476 qemu_get_buffer(f, s->ti_buf, TI_BUFSZ);
749 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 483 {
756 484 ESPState *s;
757 485 int esp_io_memory, espdma_io_memory;
  486 + int i;
758 487  
759 488 s = qemu_mallocz(sizeof(ESPState));
760 489 if (!s)
... ... @@ -773,5 +502,11 @@ void esp_init(BlockDriverState **bd, int irq, uint32_t espaddr, uint32_t espdadd
773 502  
774 503 register_savevm("esp", espaddr, 1, esp_save, esp_load, s);
775 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 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 1085 static void ide_atapi_cmd(IDEState *s)
1207 1086 {
1208 1087 const uint8_t *packet;
... ... @@ -1449,7 +1328,7 @@ static void ide_atapi_cmd(IDEState *s)
1449 1328 start_track = packet[6];
1450 1329 switch(format) {
1451 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 1332 if (len < 0)
1454 1333 goto error_cmd;
1455 1334 ide_atapi_cmd_reply(s, len, max_len);
... ... @@ -1463,7 +1342,7 @@ static void ide_atapi_cmd(IDEState *s)
1463 1342 ide_atapi_cmd_reply(s, 12, max_len);
1464 1343 break;
1465 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 1346 if (len < 0)
1468 1347 goto error_cmd;
1469 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 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 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 336 s->dx = 0;
331 337 s->dy = 0;
332 338 s->dz = 0;
... ...
hw/usb-hub.c
... ... @@ -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 204 /* XXX: do it */
  205 + if (destroy)
  206 + qemu_free(dev);
205 207 }
206 208  
207 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 55 s->remote_wakeup = 0;
56 56 s->addr = 0;
57 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 62 break;
60 63 case USB_TOKEN_SETUP:
61 64 if (s->state < USB_STATE_DEFAULT || devaddr != s->addr)
... ...
hw/usb.h
... ... @@ -29,6 +29,7 @@
29 29 #define USB_MSG_ATTACH 0x100
30 30 #define USB_MSG_DETACH 0x101
31 31 #define USB_MSG_RESET 0x102
  32 +#define USB_MSG_DESTROY 0x103
32 33  
33 34 #define USB_RET_NODEV (-1)
34 35 #define USB_RET_NAK (-2)
... ... @@ -121,7 +122,7 @@ struct USBDevice {
121 122 /* The following fields are used by the generic USB device
122 123 layer. They are here just to avoid creating a new structure for
123 124 them. */
124   - void (*handle_reset)(USBDevice *dev);
  125 + void (*handle_reset)(USBDevice *dev, int destroy);
125 126 int (*handle_control)(USBDevice *dev, int request, int value,
126 127 int index, int length, uint8_t *data);
127 128 int (*handle_data)(USBDevice *dev, int pid, uint8_t devep,
... ... @@ -170,3 +171,6 @@ void usb_host_info(void);
170 171 /* usb-hid.c */
171 172 USBDevice *usb_mouse_init(void);
172 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 55 int fd;
56 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 60 #if 0
61 61 USBHostDevice *s = (USBHostDevice *)dev;
... ...
... ... @@ -3279,6 +3279,8 @@ static int usb_device_add(const char *devname)
3279 3279 dev = usb_mouse_init();
3280 3280 } else if (!strcmp(devname, "tablet")) {
3281 3281 dev = usb_tablet_init();
  3282 + } else if (strstart(devname, "disk:", &p)) {
  3283 + dev = usb_msd_init(p);
3282 3284 } else {
3283 3285 return -1;
3284 3286 }
... ...
... ... @@ -761,6 +761,10 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn);
761 761 int pmac_ide_init (BlockDriverState **hd_table,
762 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 768 /* es1370.c */
765 769 int es1370_init (PCIBus *bus, AudioState *s);
766 770  
... ... @@ -1031,6 +1035,19 @@ void do_usb_add(const char *devname);
1031 1035 void do_usb_del(const char *devname);
1032 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 1051 /* integratorcp.c */
1035 1052 extern QEMUMachine integratorcp926_machine;
1036 1053 extern QEMUMachine integratorcp1026_machine;
... ...