Commit 4e9aec746e8d87fbe8805b881d6dae898a75372b
1 parent
56b19403
Sparcf ESP dma fixes (Blue Swirl).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1776 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
46 additions
and
5 deletions
hw/esp.c
| 1 | 1 | /* |
| 2 | 2 | * QEMU ESP emulation |
| 3 | 3 | * |
| 4 | - * Copyright (c) 2005 Fabrice Bellard | |
| 4 | + * Copyright (c) 2005-2006 Fabrice Bellard | |
| 5 | 5 | * |
| 6 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
| 7 | 7 | * of this software and associated documentation files (the "Software"), to deal |
| ... | ... | @@ -38,13 +38,18 @@ do { printf("ESP: set_irq(%d): %d\n", (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 65536 | |
| 41 | +#define TI_BUFSZ 1024*1024 // XXX | |
| 42 | 42 | #define DMA_VER 0xa0000000 |
| 43 | 43 | #define DMA_INTR 1 |
| 44 | 44 | #define DMA_INTREN 0x10 |
| 45 | 45 | #define DMA_LOADED 0x04000000 |
| 46 | +typedef struct ESPState ESPState; | |
| 46 | 47 | |
| 47 | -typedef struct ESPState { | |
| 48 | +typedef int ESPDMAFunc(ESPState *s, | |
| 49 | + target_phys_addr_t phys_addr, | |
| 50 | + int transfer_size1); | |
| 51 | + | |
| 52 | +struct ESPState { | |
| 48 | 53 | BlockDriverState **bd; |
| 49 | 54 | uint8_t rregs[ESP_MAXREG]; |
| 50 | 55 | uint8_t wregs[ESP_MAXREG]; |
| ... | ... | @@ -55,7 +60,10 @@ typedef struct ESPState { |
| 55 | 60 | int ti_dir; |
| 56 | 61 | uint8_t ti_buf[TI_BUFSZ]; |
| 57 | 62 | int dma; |
| 58 | -} ESPState; | |
| 63 | + ESPDMAFunc *dma_cb; | |
| 64 | + int64_t offset, len; | |
| 65 | + int target; | |
| 66 | +}; | |
| 59 | 67 | |
| 60 | 68 | #define STAT_DO 0x00 |
| 61 | 69 | #define STAT_DI 0x01 |
| ... | ... | @@ -217,6 +225,19 @@ static int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, |
| 217 | 225 | return len; |
| 218 | 226 | } |
| 219 | 227 | |
| 228 | +static int esp_write_dma_cb(ESPState *s, | |
| 229 | + target_phys_addr_t phys_addr, | |
| 230 | + int transfer_size1) | |
| 231 | +{ | |
| 232 | + DPRINTF("Write callback (offset %lld len %lld size %d trans_size %d)\n", | |
| 233 | + 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; | |
| 238 | + return 0; | |
| 239 | +} | |
| 240 | + | |
| 220 | 241 | static void handle_satn(ESPState *s) |
| 221 | 242 | { |
| 222 | 243 | uint8_t buf[32]; |
| ... | ... | @@ -309,6 +330,9 @@ static void handle_satn(ESPState *s) |
| 309 | 330 | s->ti_size = len * 512; |
| 310 | 331 | } |
| 311 | 332 | DPRINTF("Read (10) (offset %lld len %lld)\n", offset, len); |
| 333 | + if (s->ti_size > TI_BUFSZ) { | |
| 334 | + DPRINTF("size too large %d\n", s->ti_size); | |
| 335 | + } | |
| 312 | 336 | bdrv_read(s->bd[target], offset, s->ti_buf, len); |
| 313 | 337 | // XXX error handling |
| 314 | 338 | s->ti_dir = 1; |
| ... | ... | @@ -328,7 +352,13 @@ static void handle_satn(ESPState *s) |
| 328 | 352 | s->ti_size = len * 512; |
| 329 | 353 | } |
| 330 | 354 | DPRINTF("Write (10) (offset %lld len %lld)\n", offset, len); |
| 331 | - bdrv_write(s->bd[target], offset, s->ti_buf, len); | |
| 355 | + if (s->ti_size > TI_BUFSZ) { | |
| 356 | + DPRINTF("size too large %d\n", s->ti_size); | |
| 357 | + } | |
| 358 | + s->dma_cb = esp_write_dma_cb; | |
| 359 | + s->offset = offset; | |
| 360 | + s->len = len; | |
| 361 | + s->target = target; | |
| 332 | 362 | // XXX error handling |
| 333 | 363 | s->ti_dir = 0; |
| 334 | 364 | break; |
| ... | ... | @@ -427,6 +457,10 @@ static void handle_ti(ESPState *s) |
| 427 | 457 | else |
| 428 | 458 | cpu_physical_memory_read(dmaptr, &s->ti_buf[i], 1); |
| 429 | 459 | } |
| 460 | + if (s->dma_cb) { | |
| 461 | + s->dma_cb(s, s->espdmaregs[1], dmalen); | |
| 462 | + s->dma_cb = NULL; | |
| 463 | + } | |
| 430 | 464 | s->rregs[4] = STAT_IN | STAT_TC | STAT_ST; |
| 431 | 465 | s->rregs[5] = INTR_BS; |
| 432 | 466 | s->rregs[6] = 0; |
| ... | ... | @@ -444,8 +478,15 @@ static void esp_reset(void *opaque) |
| 444 | 478 | { |
| 445 | 479 | ESPState *s = opaque; |
| 446 | 480 | memset(s->rregs, 0, ESP_MAXREG); |
| 481 | + memset(s->wregs, 0, ESP_MAXREG); | |
| 447 | 482 | s->rregs[0x0e] = 0x4; // Indicate fas100a |
| 448 | 483 | memset(s->espdmaregs, 0, ESPDMA_REGS * 4); |
| 484 | + s->ti_size = 0; | |
| 485 | + s->ti_rptr = 0; | |
| 486 | + s->ti_wptr = 0; | |
| 487 | + s->ti_dir = 0; | |
| 488 | + s->dma = 0; | |
| 489 | + s->dma_cb = NULL; | |
| 449 | 490 | } |
| 450 | 491 | |
| 451 | 492 | static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr) | ... | ... |