Commit db59203d104bcd26d21218d817399b6a98eb49f5

Authored by pbrook
1 parent 1c46d713

ESP DMA fix.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1926 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 50 additions and 20 deletions
hw/esp.c
@@ -229,12 +229,17 @@ static int esp_write_dma_cb(ESPState *s, @@ -229,12 +229,17 @@ static int esp_write_dma_cb(ESPState *s,
229 target_phys_addr_t phys_addr, 229 target_phys_addr_t phys_addr,
230 int transfer_size1) 230 int transfer_size1)
231 { 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 + }
232 DPRINTF("Write callback (offset %lld len %lld size %d trans_size %d)\n", 238 DPRINTF("Write callback (offset %lld len %lld size %d trans_size %d)\n",
233 s->offset, s->len, s->ti_size, transfer_size1); 239 s->offset, s->len, s->ti_size, transfer_size1);
234 - bdrv_write(s->bd[s->target], s->offset, s->ti_buf, s->len);  
235 - s->offset = 0;  
236 - s->len = 0;  
237 - s->target = 0; 240 +
  241 + bdrv_write(s->bd[s->target], s->offset, s->ti_buf+s->ti_rptr, len);
  242 + s->offset+=len;
238 return 0; 243 return 0;
239 } 244 }
240 245
@@ -336,6 +341,7 @@ static void handle_satn(ESPState *s) @@ -336,6 +341,7 @@ static void handle_satn(ESPState *s)
336 bdrv_read(s->bd[target], offset, s->ti_buf, len); 341 bdrv_read(s->bd[target], offset, s->ti_buf, len);
337 // XXX error handling 342 // XXX error handling
338 s->ti_dir = 1; 343 s->ti_dir = 1;
  344 + s->ti_rptr = 0;
339 break; 345 break;
340 } 346 }
341 case 0x2a: 347 case 0x2a:
@@ -359,6 +365,7 @@ static void handle_satn(ESPState *s) @@ -359,6 +365,7 @@ static void handle_satn(ESPState *s)
359 s->offset = offset; 365 s->offset = offset;
360 s->len = len; 366 s->len = len;
361 s->target = target; 367 s->target = target;
  368 + s->ti_rptr = 0;
362 // XXX error handling 369 // XXX error handling
363 s->ti_dir = 0; 370 s->ti_dir = 0;
364 break; 371 break;
@@ -415,10 +422,9 @@ static void handle_satn(ESPState *s) @@ -415,10 +422,9 @@ static void handle_satn(ESPState *s)
415 422
416 static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len) 423 static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len)
417 { 424 {
418 - uint32_t dmaptr, dmalen; 425 + uint32_t dmaptr;
419 426
420 - dmalen = s->wregs[0] | (s->wregs[1] << 8);  
421 - DPRINTF("Transfer status len %d\n", dmalen); 427 + DPRINTF("Transfer status len %d\n", len);
422 if (s->dma) { 428 if (s->dma) {
423 dmaptr = iommu_translate(s->espdmaregs[1]); 429 dmaptr = iommu_translate(s->espdmaregs[1]);
424 DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r'); 430 DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r');
@@ -428,10 +434,10 @@ static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len) @@ -428,10 +434,10 @@ static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len)
428 s->rregs[6] = SEQ_CD; 434 s->rregs[6] = SEQ_CD;
429 } else { 435 } else {
430 memcpy(s->ti_buf, buf, len); 436 memcpy(s->ti_buf, buf, len);
431 - s->ti_size = dmalen; 437 + s->ti_size = len;
432 s->ti_rptr = 0; 438 s->ti_rptr = 0;
433 s->ti_wptr = 0; 439 s->ti_wptr = 0;
434 - s->rregs[7] = dmalen; 440 + s->rregs[7] = len;
435 } 441 }
436 s->espdmaregs[0] |= DMA_INTR; 442 s->espdmaregs[0] |= DMA_INTR;
437 pic_set_irq(s->irq, 1); 443 pic_set_irq(s->irq, 1);
@@ -442,34 +448,58 @@ static const uint8_t okbuf[] = {0, 0}; @@ -442,34 +448,58 @@ static const uint8_t okbuf[] = {0, 0};
442 448
443 static void handle_ti(ESPState *s) 449 static void handle_ti(ESPState *s)
444 { 450 {
445 - uint32_t dmaptr, dmalen; 451 + uint32_t dmaptr, dmalen, minlen, len, from, to;
446 unsigned int i; 452 unsigned int i;
447 453
448 dmalen = s->wregs[0] | (s->wregs[1] << 8); 454 dmalen = s->wregs[0] | (s->wregs[1] << 8);
449 - DPRINTF("Transfer Information len %d\n", dmalen); 455 + if (dmalen==0) {
  456 + dmalen=0x10000;
  457 + }
  458 +
  459 + minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
  460 + DPRINTF("Transfer Information len %d\n", minlen);
450 if (s->dma) { 461 if (s->dma) {
451 dmaptr = iommu_translate(s->espdmaregs[1]); 462 dmaptr = iommu_translate(s->espdmaregs[1]);
452 - DPRINTF("DMA Direction: %c, addr 0x%8.8x\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr);  
453 - for (i = 0; i < s->ti_size; i++) { 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);
  464 + from = s->espdmaregs[1];
  465 + to = from + minlen;
  466 + for (i = 0; i < minlen; i += len, from += len) {
454 dmaptr = iommu_translate(s->espdmaregs[1] + i); 467 dmaptr = iommu_translate(s->espdmaregs[1] + i);
  468 + if ((from & TARGET_PAGE_MASK) != (to & TARGET_PAGE_MASK)) {
  469 + len = TARGET_PAGE_SIZE - (from & ~TARGET_PAGE_MASK);
  470 + } else {
  471 + len = to - from;
  472 + }
  473 + DPRINTF("DMA address p %08x v %08x len %08x, from %08x, to %08x\n", dmaptr, s->espdmaregs[1] + i, len, from, to);
455 if (s->ti_dir) 474 if (s->ti_dir)
456 - cpu_physical_memory_write(dmaptr, &s->ti_buf[i], 1); 475 + cpu_physical_memory_write(dmaptr, &s->ti_buf[s->ti_rptr + i], len);
457 else 476 else
458 - cpu_physical_memory_read(dmaptr, &s->ti_buf[i], 1); 477 + cpu_physical_memory_read(dmaptr, &s->ti_buf[s->ti_rptr + i], len);
459 } 478 }
460 if (s->dma_cb) { 479 if (s->dma_cb) {
461 - s->dma_cb(s, s->espdmaregs[1], dmalen); 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);
  484 + s->ti_size -= minlen;
  485 + s->ti_rptr += minlen;
  486 + } else {
  487 + s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
462 s->dma_cb = NULL; 488 s->dma_cb = NULL;
  489 + s->offset = 0;
  490 + s->len = 0;
  491 + s->target = 0;
  492 + s->ti_rptr = 0;
463 } 493 }
464 - s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;  
465 - s->rregs[5] = INTR_BS; 494 + s->rregs[5] = INTR_BS;
466 s->rregs[6] = 0; 495 s->rregs[6] = 0;
  496 + s->rregs[7] = 0;
467 s->espdmaregs[0] |= DMA_INTR; 497 s->espdmaregs[0] |= DMA_INTR;
468 } else { 498 } else {
469 - s->ti_size = dmalen; 499 + s->ti_size = minlen;
470 s->ti_rptr = 0; 500 s->ti_rptr = 0;
471 s->ti_wptr = 0; 501 s->ti_wptr = 0;
472 - s->rregs[7] = dmalen; 502 + s->rregs[7] = minlen;
473 } 503 }
474 pic_set_irq(s->irq, 1); 504 pic_set_irq(s->irq, 1);
475 } 505 }