Commit 4f6200f03b32d1cb166c2b85c97e857109dd8f9d

Authored by bellard
1 parent aea3ce4c

ESP PIO mode, 2k CDROM sector size (Blue Swirl)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1577 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 143 additions and 39 deletions
hw/esp.c
... ... @@ -36,6 +36,9 @@ do { printf("ESP: " fmt , ##args); } while (0)
36 36 #define ESPDMA_REGS 4
37 37 #define ESPDMA_MAXADDR (ESPDMA_REGS * 4 - 1)
38 38 #define ESP_MAXREG 0x3f
  39 +#define TI_BUFSZ 65536
  40 +#define DMA_VER 0xa0000000
  41 +#define DMA_LOADED 0x04000000
39 42  
40 43 typedef struct ESPState {
41 44 BlockDriverState **bd;
... ... @@ -44,8 +47,10 @@ typedef struct ESPState {
44 47 int irq;
45 48 uint32_t espdmaregs[ESPDMA_REGS];
46 49 uint32_t ti_size;
  50 + uint32_t ti_rptr, ti_wptr;
47 51 int ti_dir;
48   - uint8_t ti_buf[65536];
  52 + uint8_t ti_buf[TI_BUFSZ];
  53 + int dma;
49 54 } ESPState;
50 55  
51 56 #define STAT_DO 0x00
... ... @@ -73,17 +78,25 @@ static void handle_satn(ESPState *s)
73 78 int64_t nb_sectors;
74 79 int target;
75 80  
76   - dmaptr = iommu_translate(s->espdmaregs[1]);
77 81 dmalen = s->wregs[0] | (s->wregs[1] << 8);
78   - DPRINTF("Select with ATN at %8.8x len %d\n", dmaptr, dmalen);
79   - DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r');
80   - cpu_physical_memory_read(dmaptr, buf, dmalen);
  82 + target = s->wregs[4] & 7;
  83 + DPRINTF("Select with ATN len %d target %d\n", dmalen, target);
  84 + if (s->dma) {
  85 + dmaptr = iommu_translate(s->espdmaregs[1]);
  86 + DPRINTF("DMA Direction: %c, addr 0x%8.8x\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr);
  87 + cpu_physical_memory_read(dmaptr, buf, dmalen);
  88 + } else {
  89 + buf[0] = 0;
  90 + memcpy(&buf[1], s->ti_buf, dmalen);
  91 + dmalen++;
  92 + }
81 93 for (i = 0; i < dmalen; i++) {
82 94 DPRINTF("Command %2.2x\n", buf[i]);
83 95 }
84 96 s->ti_dir = 0;
85 97 s->ti_size = 0;
86   - target = s->wregs[4] & 7;
  98 + s->ti_rptr = 0;
  99 + s->ti_wptr = 0;
87 100  
88 101 if (target > 4 || !s->bd[target]) { // No such drive
89 102 s->rregs[4] = STAT_IN;
... ... @@ -126,7 +139,10 @@ static void handle_satn(ESPState *s)
126 139 s->ti_buf[3] = nb_sectors & 0xff;
127 140 s->ti_buf[4] = 0;
128 141 s->ti_buf[5] = 0;
129   - s->ti_buf[6] = 2;
  142 + if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM)
  143 + s->ti_buf[6] = 8; // sector size 2048
  144 + else
  145 + s->ti_buf[6] = 2; // sector size 512
130 146 s->ti_buf[7] = 0;
131 147 s->ti_dir = 1;
132 148 s->ti_size = 8;
... ... @@ -135,28 +151,42 @@ static void handle_satn(ESPState *s)
135 151 {
136 152 int64_t offset, len;
137 153  
138   - offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];
139   - len = (buf[8] << 8) | buf[9];
  154 + if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) {
  155 + offset = ((buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6]) * 4;
  156 + len = ((buf[8] << 8) | buf[9]) * 4;
  157 + s->ti_size = len * 2048;
  158 + } else {
  159 + offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];
  160 + len = (buf[8] << 8) | buf[9];
  161 + s->ti_size = len * 512;
  162 + }
140 163 DPRINTF("Read (10) (offset %lld len %lld)\n", offset, len);
141 164 bdrv_read(s->bd[target], offset, s->ti_buf, len);
  165 + // XXX error handling
142 166 s->ti_dir = 1;
143   - s->ti_size = len * 512;
144 167 break;
145 168 }
146 169 case 0x2a:
147 170 {
148 171 int64_t offset, len;
149 172  
150   - offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];
151   - len = (buf[8] << 8) | buf[9];
  173 + if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) {
  174 + offset = ((buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6]) * 4;
  175 + len = ((buf[8] << 8) | buf[9]) * 4;
  176 + s->ti_size = len * 2048;
  177 + } else {
  178 + offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];
  179 + len = (buf[8] << 8) | buf[9];
  180 + s->ti_size = len * 512;
  181 + }
152 182 DPRINTF("Write (10) (offset %lld len %lld)\n", offset, len);
153 183 bdrv_write(s->bd[target], offset, s->ti_buf, len);
  184 + // XXX error handling
154 185 s->ti_dir = 0;
155   - s->ti_size = len * 512;
156 186 break;
157 187 }
158 188 default:
159   - DPRINTF("Unknown command (%2.2x)\n", buf[1]);
  189 + DPRINTF("Unknown SCSI command (%2.2x)\n", buf[1]);
160 190 break;
161 191 }
162 192 s->rregs[4] = STAT_IN | STAT_TC | STAT_DI;
... ... @@ -170,17 +200,26 @@ static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len)
170 200 {
171 201 uint32_t dmaptr, dmalen;
172 202  
173   - dmaptr = iommu_translate(s->espdmaregs[1]);
174 203 dmalen = s->wregs[0] | (s->wregs[1] << 8);
175   - DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r');
176   - cpu_physical_memory_write(dmaptr, buf, len);
177   - s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
178   - s->rregs[5] = INTR_BS | INTR_FC;
179   - s->rregs[6] = SEQ_CD;
180   - s->espdmaregs[0] |= 1;
  204 + DPRINTF("Transfer status len %d\n", dmalen);
  205 + if (s->dma) {
  206 + dmaptr = iommu_translate(s->espdmaregs[1]);
  207 + DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r');
  208 + cpu_physical_memory_write(dmaptr, buf, len);
  209 + s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
  210 + s->rregs[5] = INTR_BS | INTR_FC;
  211 + s->rregs[6] = SEQ_CD;
  212 + s->espdmaregs[0] |= 1;
  213 + } else {
  214 + memcpy(s->ti_buf, buf, len);
  215 + s->ti_size = dmalen;
  216 + s->ti_rptr = 0;
  217 + s->ti_wptr = 0;
  218 + }
181 219 pic_set_irq(s->irq, 1);
182 220  
183 221 }
  222 +
184 223 static const uint8_t okbuf[] = {0, 0};
185 224  
186 225 static void handle_ti(ESPState *s)
... ... @@ -188,21 +227,27 @@ static void handle_ti(ESPState *s)
188 227 uint32_t dmaptr, dmalen;
189 228 unsigned int i;
190 229  
191   - dmaptr = iommu_translate(s->espdmaregs[1]);
192 230 dmalen = s->wregs[0] | (s->wregs[1] << 8);
193   - DPRINTF("Transfer Information at %8.8x len %d\n", dmaptr, dmalen);
194   - DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r');
195   - for (i = 0; i < s->ti_size; i++) {
196   - dmaptr = iommu_translate(s->espdmaregs[1] + i);
197   - if (s->ti_dir)
198   - cpu_physical_memory_write(dmaptr, &s->ti_buf[i], 1);
199   - else
200   - cpu_physical_memory_read(dmaptr, &s->ti_buf[i], 1);
201   - }
202   - s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
203   - s->rregs[5] = INTR_BS;
204   - s->rregs[6] = 0;
205   - s->espdmaregs[0] |= 1;
  231 + DPRINTF("Transfer Information len %d\n", dmalen);
  232 + if (s->dma) {
  233 + dmaptr = iommu_translate(s->espdmaregs[1]);
  234 + DPRINTF("DMA Direction: %c, addr 0x%8.8x\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr);
  235 + for (i = 0; i < s->ti_size; i++) {
  236 + dmaptr = iommu_translate(s->espdmaregs[1] + i);
  237 + if (s->ti_dir)
  238 + cpu_physical_memory_write(dmaptr, &s->ti_buf[i], 1);
  239 + else
  240 + cpu_physical_memory_read(dmaptr, &s->ti_buf[i], 1);
  241 + }
  242 + s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
  243 + s->rregs[5] = INTR_BS;
  244 + s->rregs[6] = 0;
  245 + s->espdmaregs[0] |= 1;
  246 + } else {
  247 + s->ti_size = dmalen;
  248 + s->ti_rptr = 0;
  249 + s->ti_wptr = 0;
  250 + }
206 251 pic_set_irq(s->irq, 1);
207 252 }
208 253  
... ... @@ -221,10 +266,23 @@ static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
221 266  
222 267 saddr = (addr & ESP_MAXREG) >> 2;
223 268 switch (saddr) {
  269 + case 2:
  270 + // FIFO
  271 + if (s->ti_size > 0) {
  272 + s->ti_size--;
  273 + s->rregs[saddr] = s->ti_buf[s->ti_rptr++];
  274 + pic_set_irq(s->irq, 1);
  275 + }
  276 + if (s->ti_size == 0) {
  277 + s->ti_rptr = 0;
  278 + s->ti_wptr = 0;
  279 + }
  280 + break;
224 281 default:
225 282 break;
226 283 }
227 284 DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
  285 +
228 286 return s->rregs[saddr];
229 287 }
230 288  
... ... @@ -236,8 +294,23 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
236 294 saddr = (addr & ESP_MAXREG) >> 2;
237 295 DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr], val);
238 296 switch (saddr) {
  297 + case 0:
  298 + case 1:
  299 + s->rregs[saddr] = val;
  300 + break;
  301 + case 2:
  302 + // FIFO
  303 + s->ti_size++;
  304 + s->ti_buf[s->ti_wptr++] = val & 0xff;
  305 + break;
239 306 case 3:
  307 + s->rregs[saddr] = val;
240 308 // Command
  309 + if (val & 0x80) {
  310 + s->dma = 1;
  311 + } else {
  312 + s->dma = 0;
  313 + }
241 314 switch(val & 0x7f) {
242 315 case 0:
243 316 DPRINTF("NOP (%2.2x)\n", val);
... ... @@ -278,13 +351,20 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
278 351 handle_satn(s);
279 352 break;
280 353 default:
281   - DPRINTF("Unhandled command (%2.2x)\n", val);
  354 + DPRINTF("Unhandled ESP command (%2.2x)\n", val);
282 355 break;
283 356 }
284 357 break;
285 358 case 4 ... 7:
286   - case 9 ... 0xf:
287 359 break;
  360 + case 8:
  361 + s->rregs[saddr] = val;
  362 + break;
  363 + case 9 ... 10:
  364 + break;
  365 + case 11 ... 15:
  366 + s->rregs[saddr] = val;
  367 + break;
288 368 default:
289 369 break;
290 370 }
... ... @@ -309,7 +389,8 @@ static uint32_t espdma_mem_readl(void *opaque, target_phys_addr_t addr)
309 389 uint32_t saddr;
310 390  
311 391 saddr = (addr & ESPDMA_MAXADDR) >> 2;
312   - DPRINTF("read dmareg[%d]: 0x%2.2x\n", saddr, s->espdmaregs[saddr]);
  392 + DPRINTF("read dmareg[%d]: 0x%8.8x\n", saddr, s->espdmaregs[saddr]);
  393 +
313 394 return s->espdmaregs[saddr];
314 395 }
315 396  
... ... @@ -319,12 +400,23 @@ static void espdma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t va
319 400 uint32_t saddr;
320 401  
321 402 saddr = (addr & ESPDMA_MAXADDR) >> 2;
322   - DPRINTF("write dmareg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->espdmaregs[saddr], val);
  403 + DPRINTF("write dmareg[%d]: 0x%8.8x -> 0x%8.8x\n", saddr, s->espdmaregs[saddr], val);
323 404 switch (saddr) {
324 405 case 0:
325 406 if (!(val & 0x10))
326 407 pic_set_irq(s->irq, 0);
  408 + if (val & 0x80) {
  409 + esp_reset(s);
  410 + } else if (val & 0x40) {
  411 + val &= ~0x40;
  412 + } else if (val == 0)
  413 + val = 0x40;
  414 + val &= 0x0fffffff;
  415 + val |= DMA_VER;
327 416 break;
  417 + case 1:
  418 + s->espdmaregs[0] = DMA_LOADED;
  419 + break;
328 420 default:
329 421 break;
330 422 }
... ... @@ -353,6 +445,12 @@ static void esp_save(QEMUFile *f, void *opaque)
353 445 qemu_put_be32s(f, &s->irq);
354 446 for (i = 0; i < ESPDMA_REGS; i++)
355 447 qemu_put_be32s(f, &s->espdmaregs[i]);
  448 + qemu_put_be32s(f, &s->ti_size);
  449 + qemu_put_be32s(f, &s->ti_rptr);
  450 + qemu_put_be32s(f, &s->ti_wptr);
  451 + qemu_put_be32s(f, &s->ti_dir);
  452 + qemu_put_buffer(f, s->ti_buf, TI_BUFSZ);
  453 + qemu_put_be32s(f, &s->dma);
356 454 }
357 455  
358 456 static int esp_load(QEMUFile *f, void *opaque, int version_id)
... ... @@ -368,6 +466,12 @@ static int esp_load(QEMUFile *f, void *opaque, int version_id)
368 466 qemu_get_be32s(f, &s->irq);
369 467 for (i = 0; i < ESPDMA_REGS; i++)
370 468 qemu_get_be32s(f, &s->espdmaregs[i]);
  469 + qemu_get_be32s(f, &s->ti_size);
  470 + qemu_get_be32s(f, &s->ti_rptr);
  471 + qemu_get_be32s(f, &s->ti_wptr);
  472 + qemu_get_be32s(f, &s->ti_dir);
  473 + qemu_get_buffer(f, s->ti_buf, TI_BUFSZ);
  474 + qemu_get_be32s(f, &s->dma);
371 475  
372 476 return 0;
373 477 }
... ...