Commit b42ec42d4306e6da1e72a32167262343025116ed
1 parent
927e3a4e
DB-DMA cleanup
Signed-off-by: Laurent Vivier <Laurent@vivier.eu> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6676 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
133 additions
and
164 deletions
hw/ide.c
| ... | ... | @@ -3429,71 +3429,69 @@ void pci_piix4_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn, |
| 3429 | 3429 | |
| 3430 | 3430 | typedef struct MACIOIDEState { |
| 3431 | 3431 | IDEState ide_if[2]; |
| 3432 | - void *dbdma; | |
| 3433 | 3432 | int stream_index; |
| 3434 | 3433 | } MACIOIDEState; |
| 3435 | 3434 | |
| 3436 | -static int pmac_atapi_read(DBDMA_transfer *info, DBDMA_transfer_cb cb) | |
| 3435 | +static void pmac_atapi_read(DBDMA_io *io) | |
| 3437 | 3436 | { |
| 3438 | - MACIOIDEState *m = info->opaque; | |
| 3437 | + MACIOIDEState *m = io->opaque; | |
| 3439 | 3438 | IDEState *s = m->ide_if->cur_drive; |
| 3440 | - int ret; | |
| 3441 | - | |
| 3442 | - if (s->lba == -1) | |
| 3443 | - return 0; | |
| 3444 | - | |
| 3445 | - info->buf_pos = 0; | |
| 3439 | + int ret, len; | |
| 3446 | 3440 | |
| 3447 | - while (info->buf_pos < info->len && s->packet_transfer_size > 0) { | |
| 3441 | + while (io->len > 0 && | |
| 3442 | + s->packet_transfer_size > 0) { | |
| 3448 | 3443 | |
| 3449 | - ret = cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size); | |
| 3444 | + len = s->cd_sector_size; | |
| 3445 | + ret = cd_read_sector(s->bs, s->lba, s->io_buffer, len); | |
| 3450 | 3446 | if (ret < 0) { |
| 3447 | + io->dma_end(io); | |
| 3451 | 3448 | ide_transfer_stop(s); |
| 3452 | 3449 | ide_atapi_io_error(s, ret); |
| 3453 | - return info->buf_pos; | |
| 3450 | + return; | |
| 3454 | 3451 | } |
| 3455 | 3452 | |
| 3456 | - info->buf = s->io_buffer + m->stream_index; | |
| 3457 | - | |
| 3458 | - info->buf_len = s->cd_sector_size; | |
| 3459 | - if (info->buf_pos + info->buf_len > info->len) | |
| 3460 | - info->buf_len = info->len - info->buf_pos; | |
| 3453 | + if (len > io->len) | |
| 3454 | + len = io->len; | |
| 3461 | 3455 | |
| 3462 | - cb(info); | |
| 3456 | + cpu_physical_memory_write(io->addr, | |
| 3457 | + s->io_buffer + m->stream_index, len); | |
| 3463 | 3458 | |
| 3464 | 3459 | /* db-dma can ask for 512 bytes whereas block size is 2048... */ |
| 3465 | 3460 | |
| 3466 | - m->stream_index += info->buf_len; | |
| 3461 | + m->stream_index += len; | |
| 3467 | 3462 | s->lba += m->stream_index / s->cd_sector_size; |
| 3468 | 3463 | m->stream_index %= s->cd_sector_size; |
| 3469 | 3464 | |
| 3470 | - info->buf_pos += info->buf_len; | |
| 3471 | - s->packet_transfer_size -= info->buf_len; | |
| 3465 | + io->len -= len; | |
| 3466 | + io->addr += len; | |
| 3467 | + s->packet_transfer_size -= len; | |
| 3472 | 3468 | } |
| 3469 | + | |
| 3470 | + if (io->len <= 0) | |
| 3471 | + io->dma_end(io); | |
| 3472 | + | |
| 3473 | 3473 | if (s->packet_transfer_size <= 0) { |
| 3474 | 3474 | s->status = READY_STAT | SEEK_STAT; |
| 3475 | 3475 | s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO |
| 3476 | 3476 | | ATAPI_INT_REASON_CD; |
| 3477 | 3477 | ide_set_irq(s); |
| 3478 | 3478 | } |
| 3479 | - | |
| 3480 | - return info->buf_pos; | |
| 3481 | 3479 | } |
| 3482 | 3480 | |
| 3483 | -static int pmac_ide_transfer(DBDMA_transfer *info, | |
| 3484 | - DBDMA_transfer_cb cb) | |
| 3481 | +static void pmac_ide_transfer(DBDMA_io *io) | |
| 3485 | 3482 | { |
| 3486 | - MACIOIDEState *m = info->opaque; | |
| 3483 | + MACIOIDEState *m = io->opaque; | |
| 3487 | 3484 | IDEState *s = m->ide_if->cur_drive; |
| 3488 | 3485 | int64_t sector_num; |
| 3489 | 3486 | int ret, n; |
| 3487 | + int len; | |
| 3490 | 3488 | |
| 3491 | - if (s->is_cdrom) | |
| 3492 | - return pmac_atapi_read(info, cb); | |
| 3489 | + if (s->is_cdrom) { | |
| 3490 | + pmac_atapi_read(io); | |
| 3491 | + return; | |
| 3492 | + } | |
| 3493 | 3493 | |
| 3494 | - info->buf = s->io_buffer; | |
| 3495 | - info->buf_pos = 0; | |
| 3496 | - while (info->buf_pos < info->len && s->nsector > 0) { | |
| 3494 | + while (io->len > 0 && s->nsector > 0) { | |
| 3497 | 3495 | |
| 3498 | 3496 | sector_num = ide_get_sector(s); |
| 3499 | 3497 | |
| ... | ... | @@ -3501,36 +3499,40 @@ static int pmac_ide_transfer(DBDMA_transfer *info, |
| 3501 | 3499 | if (n > IDE_DMA_BUF_SECTORS) |
| 3502 | 3500 | n = IDE_DMA_BUF_SECTORS; |
| 3503 | 3501 | |
| 3504 | - info->buf_len = n << 9; | |
| 3505 | - if (info->buf_pos + info->buf_len > info->len) | |
| 3506 | - info->buf_len = info->len - info->buf_pos; | |
| 3507 | - n = info->buf_len >> 9; | |
| 3502 | + len = n << 9; | |
| 3503 | + if (len > io->len) | |
| 3504 | + len = io->len; | |
| 3505 | + n = (len + 511) >> 9; | |
| 3508 | 3506 | |
| 3509 | 3507 | if (s->is_read) { |
| 3510 | 3508 | ret = bdrv_read(s->bs, sector_num, s->io_buffer, n); |
| 3511 | - if (ret == 0) | |
| 3512 | - cb(info); | |
| 3509 | + cpu_physical_memory_write(io->addr, s->io_buffer, len); | |
| 3513 | 3510 | } else { |
| 3514 | - cb(info); | |
| 3511 | + cpu_physical_memory_read(io->addr, s->io_buffer, len); | |
| 3515 | 3512 | ret = bdrv_write(s->bs, sector_num, s->io_buffer, n); |
| 3516 | 3513 | } |
| 3517 | 3514 | |
| 3518 | 3515 | if (ret != 0) { |
| 3516 | + io->dma_end(io); | |
| 3519 | 3517 | ide_rw_error(s); |
| 3520 | - return info->buf_pos; | |
| 3518 | + return; | |
| 3521 | 3519 | } |
| 3522 | 3520 | |
| 3523 | - info->buf_pos += n << 9; | |
| 3521 | + io->len -= len; | |
| 3522 | + io->addr += len; | |
| 3524 | 3523 | ide_set_sector(s, sector_num + n); |
| 3525 | 3524 | s->nsector -= n; |
| 3526 | 3525 | } |
| 3527 | 3526 | |
| 3527 | + if (io->len <= 0) | |
| 3528 | + io->dma_end(io); | |
| 3529 | + | |
| 3528 | 3530 | if (s->nsector <= 0) { |
| 3529 | 3531 | s->status = READY_STAT | SEEK_STAT; |
| 3530 | 3532 | ide_set_irq(s); |
| 3531 | 3533 | } |
| 3532 | 3534 | |
| 3533 | - return info->buf_pos; | |
| 3535 | + return; | |
| 3534 | 3536 | } |
| 3535 | 3537 | |
| 3536 | 3538 | /* PowerMac IDE memory IO */ |
| ... | ... | @@ -3709,10 +3711,8 @@ int pmac_ide_init (BlockDriverState **hd_table, qemu_irq irq, |
| 3709 | 3711 | d = qemu_mallocz(sizeof(MACIOIDEState)); |
| 3710 | 3712 | ide_init2(d->ide_if, hd_table[0], hd_table[1], irq); |
| 3711 | 3713 | |
| 3712 | - if (dbdma) { | |
| 3713 | - d->dbdma = dbdma; | |
| 3714 | + if (dbdma) | |
| 3714 | 3715 | DBDMA_register_channel(dbdma, channel, dma_irq, pmac_ide_transfer, d); |
| 3715 | - } | |
| 3716 | 3716 | |
| 3717 | 3717 | pmac_ide_memory = cpu_register_io_memory(0, pmac_ide_read, |
| 3718 | 3718 | pmac_ide_write, d); | ... | ... |
hw/mac_dbdma.c
| ... | ... | @@ -158,9 +158,10 @@ typedef struct DBDMA_channel { |
| 158 | 158 | int channel; |
| 159 | 159 | uint32_t regs[DBDMA_REGS]; |
| 160 | 160 | qemu_irq irq; |
| 161 | - DBDMA_transfer io; | |
| 162 | - DBDMA_transfer_handler transfer_handler; | |
| 161 | + DBDMA_io io; | |
| 162 | + DBDMA_rw rw; | |
| 163 | 163 | dbdma_cmd current; |
| 164 | + int processing; | |
| 164 | 165 | } DBDMA_channel; |
| 165 | 166 | |
| 166 | 167 | #ifdef DEBUG_DBDMA |
| ... | ... | @@ -218,7 +219,7 @@ static void conditional_interrupt(DBDMA_channel *ch) |
| 218 | 219 | |
| 219 | 220 | DBDMA_DPRINTF("conditional_interrupt\n"); |
| 220 | 221 | |
| 221 | - intr = be16_to_cpu(current->command) & INTR_MASK; | |
| 222 | + intr = le16_to_cpu(current->command) & INTR_MASK; | |
| 222 | 223 | |
| 223 | 224 | switch(intr) { |
| 224 | 225 | case INTR_NEVER: /* don't interrupt */ |
| ... | ... | @@ -257,7 +258,7 @@ static int conditional_wait(DBDMA_channel *ch) |
| 257 | 258 | |
| 258 | 259 | DBDMA_DPRINTF("conditional_wait\n"); |
| 259 | 260 | |
| 260 | - wait = be16_to_cpu(current->command) & WAIT_MASK; | |
| 261 | + wait = le16_to_cpu(current->command) & WAIT_MASK; | |
| 261 | 262 | |
| 262 | 263 | switch(wait) { |
| 263 | 264 | case WAIT_NEVER: /* don't wait */ |
| ... | ... | @@ -318,7 +319,7 @@ static void conditional_branch(DBDMA_channel *ch) |
| 318 | 319 | |
| 319 | 320 | /* check if we must branch */ |
| 320 | 321 | |
| 321 | - br = be16_to_cpu(current->command) & BR_MASK; | |
| 322 | + br = le16_to_cpu(current->command) & BR_MASK; | |
| 322 | 323 | |
| 323 | 324 | switch(br) { |
| 324 | 325 | case BR_NEVER: /* don't branch */ |
| ... | ... | @@ -352,38 +353,35 @@ static void conditional_branch(DBDMA_channel *ch) |
| 352 | 353 | } |
| 353 | 354 | } |
| 354 | 355 | |
| 355 | -static int dbdma_read_memory(DBDMA_transfer *io) | |
| 356 | -{ | |
| 357 | - DBDMA_channel *ch = io->channel; | |
| 358 | - dbdma_cmd *current = &ch->current; | |
| 359 | - | |
| 360 | - DBDMA_DPRINTF("DBDMA_read_memory\n"); | |
| 361 | - | |
| 362 | - cpu_physical_memory_read(le32_to_cpu(current->phy_addr) + io->buf_pos, | |
| 363 | - io->buf, io->buf_len); | |
| 364 | - | |
| 365 | - return io->buf_len; | |
| 366 | -} | |
| 356 | +static QEMUBH *dbdma_bh; | |
| 357 | +static void channel_run(DBDMA_channel *ch); | |
| 367 | 358 | |
| 368 | -static int dbdma_write_memory(DBDMA_transfer *io) | |
| 359 | +static void dbdma_end(DBDMA_io *io) | |
| 369 | 360 | { |
| 370 | 361 | DBDMA_channel *ch = io->channel; |
| 371 | 362 | dbdma_cmd *current = &ch->current; |
| 372 | 363 | |
| 373 | - DBDMA_DPRINTF("DBDMA_write_memory\n"); | |
| 364 | + if (conditional_wait(ch)) | |
| 365 | + goto wait; | |
| 374 | 366 | |
| 375 | - cpu_physical_memory_write(le32_to_cpu(current->phy_addr) + io->buf_pos, | |
| 376 | - io->buf, io->buf_len); | |
| 367 | + current->xfer_status = cpu_to_le16(be32_to_cpu(ch->regs[DBDMA_STATUS])); | |
| 368 | + current->res_count = cpu_to_le16(be32_to_cpu(io->len)); | |
| 369 | + dbdma_cmdptr_save(ch); | |
| 370 | + ch->regs[DBDMA_STATUS] &= cpu_to_be32(~FLUSH); | |
| 371 | + | |
| 372 | + conditional_interrupt(ch); | |
| 373 | + conditional_branch(ch); | |
| 377 | 374 | |
| 378 | - return io->buf_len; | |
| 375 | +wait: | |
| 376 | + ch->processing = 0; | |
| 377 | + if ((ch->regs[DBDMA_STATUS] & cpu_to_be32(RUN)) && | |
| 378 | + (ch->regs[DBDMA_STATUS] & cpu_to_be32(ACTIVE))) | |
| 379 | + channel_run(ch); | |
| 379 | 380 | } |
| 380 | 381 | |
| 381 | -static int start_output(DBDMA_channel *ch, int key, uint32_t addr, | |
| 382 | +static void start_output(DBDMA_channel *ch, int key, uint32_t addr, | |
| 382 | 383 | uint16_t req_count, int is_last) |
| 383 | 384 | { |
| 384 | - dbdma_cmd *current = &ch->current; | |
| 385 | - uint32_t n; | |
| 386 | - | |
| 387 | 385 | DBDMA_DPRINTF("start_output\n"); |
| 388 | 386 | |
| 389 | 387 | /* KEY_REGS, KEY_DEVICE and KEY_STREAM |
| ... | ... | @@ -393,35 +391,21 @@ static int start_output(DBDMA_channel *ch, int key, uint32_t addr, |
| 393 | 391 | DBDMA_DPRINTF("addr 0x%x key 0x%x\n", addr, key); |
| 394 | 392 | if (!addr || key > KEY_STREAM3) { |
| 395 | 393 | kill_channel(ch); |
| 396 | - return 0; | |
| 394 | + return; | |
| 397 | 395 | } |
| 398 | 396 | |
| 399 | - ch->io.buf = NULL; | |
| 400 | - ch->io.buf_pos = 0; | |
| 401 | - ch->io.buf_len = 0; | |
| 397 | + ch->io.addr = addr; | |
| 402 | 398 | ch->io.len = req_count; |
| 403 | 399 | ch->io.is_last = is_last; |
| 404 | - n = ch->transfer_handler(&ch->io, dbdma_read_memory); | |
| 405 | - | |
| 406 | - if (conditional_wait(ch)) | |
| 407 | - return 1; | |
| 408 | - | |
| 409 | - current->xfer_status = cpu_to_le16(be32_to_cpu(ch->regs[DBDMA_STATUS])); | |
| 410 | - current->res_count = cpu_to_le16(0); | |
| 411 | - dbdma_cmdptr_save(ch); | |
| 412 | - | |
| 413 | - conditional_interrupt(ch); | |
| 414 | - conditional_branch(ch); | |
| 415 | - | |
| 416 | - return 1; | |
| 400 | + ch->io.dma_end = dbdma_end; | |
| 401 | + ch->io.is_dma_out = 1; | |
| 402 | + ch->processing = 1; | |
| 403 | + ch->rw(&ch->io); | |
| 417 | 404 | } |
| 418 | 405 | |
| 419 | -static int start_input(DBDMA_channel *ch, int key, uint32_t addr, | |
| 406 | +static void start_input(DBDMA_channel *ch, int key, uint32_t addr, | |
| 420 | 407 | uint16_t req_count, int is_last) |
| 421 | 408 | { |
| 422 | - dbdma_cmd *current = &ch->current; | |
| 423 | - uint32_t n; | |
| 424 | - | |
| 425 | 409 | DBDMA_DPRINTF("start_input\n"); |
| 426 | 410 | |
| 427 | 411 | /* KEY_REGS, KEY_DEVICE and KEY_STREAM |
| ... | ... | @@ -430,30 +414,19 @@ static int start_input(DBDMA_channel *ch, int key, uint32_t addr, |
| 430 | 414 | |
| 431 | 415 | if (!addr || key > KEY_STREAM3) { |
| 432 | 416 | kill_channel(ch); |
| 433 | - return 0; | |
| 417 | + return; | |
| 434 | 418 | } |
| 435 | 419 | |
| 436 | - ch->io.buf = NULL; | |
| 437 | - ch->io.buf_pos = 0; | |
| 438 | - ch->io.buf_len = 0; | |
| 420 | + ch->io.addr = addr; | |
| 439 | 421 | ch->io.len = req_count; |
| 440 | 422 | ch->io.is_last = is_last; |
| 441 | - n = ch->transfer_handler(&ch->io, dbdma_write_memory); | |
| 442 | - | |
| 443 | - if (conditional_wait(ch)) | |
| 444 | - return 1; | |
| 445 | - | |
| 446 | - current->xfer_status = cpu_to_le16(be32_to_cpu(ch->regs[DBDMA_STATUS])); | |
| 447 | - current->res_count = cpu_to_le16(0); | |
| 448 | - dbdma_cmdptr_save(ch); | |
| 449 | - | |
| 450 | - conditional_interrupt(ch); | |
| 451 | - conditional_branch(ch); | |
| 452 | - | |
| 453 | - return 1; | |
| 423 | + ch->io.dma_end = dbdma_end; | |
| 424 | + ch->io.is_dma_out = 0; | |
| 425 | + ch->processing = 1; | |
| 426 | + ch->rw(&ch->io); | |
| 454 | 427 | } |
| 455 | 428 | |
| 456 | -static int load_word(DBDMA_channel *ch, int key, uint32_t addr, | |
| 429 | +static void load_word(DBDMA_channel *ch, int key, uint32_t addr, | |
| 457 | 430 | uint16_t len) |
| 458 | 431 | { |
| 459 | 432 | dbdma_cmd *current = &ch->current; |
| ... | ... | @@ -466,7 +439,7 @@ static int load_word(DBDMA_channel *ch, int key, uint32_t addr, |
| 466 | 439 | if (key != KEY_SYSTEM) { |
| 467 | 440 | printf("DBDMA: LOAD_WORD, unimplemented key %x\n", key); |
| 468 | 441 | kill_channel(ch); |
| 469 | - return 0; | |
| 442 | + return; | |
| 470 | 443 | } |
| 471 | 444 | |
| 472 | 445 | cpu_physical_memory_read(addr, (uint8_t*)&val, len); |
| ... | ... | @@ -479,18 +452,20 @@ static int load_word(DBDMA_channel *ch, int key, uint32_t addr, |
| 479 | 452 | current->cmd_dep = val; |
| 480 | 453 | |
| 481 | 454 | if (conditional_wait(ch)) |
| 482 | - return 1; | |
| 455 | + goto wait; | |
| 483 | 456 | |
| 484 | 457 | current->xfer_status = cpu_to_le16(be32_to_cpu(ch->regs[DBDMA_STATUS])); |
| 485 | 458 | dbdma_cmdptr_save(ch); |
| 459 | + ch->regs[DBDMA_STATUS] &= cpu_to_be32(~FLUSH); | |
| 486 | 460 | |
| 487 | 461 | conditional_interrupt(ch); |
| 488 | 462 | next(ch); |
| 489 | 463 | |
| 490 | - return 1; | |
| 464 | +wait: | |
| 465 | + qemu_bh_schedule(dbdma_bh); | |
| 491 | 466 | } |
| 492 | 467 | |
| 493 | -static int store_word(DBDMA_channel *ch, int key, uint32_t addr, | |
| 468 | +static void store_word(DBDMA_channel *ch, int key, uint32_t addr, | |
| 494 | 469 | uint16_t len) |
| 495 | 470 | { |
| 496 | 471 | dbdma_cmd *current = &ch->current; |
| ... | ... | @@ -503,7 +478,7 @@ static int store_word(DBDMA_channel *ch, int key, uint32_t addr, |
| 503 | 478 | if (key != KEY_SYSTEM) { |
| 504 | 479 | printf("DBDMA: STORE_WORD, unimplemented key %x\n", key); |
| 505 | 480 | kill_channel(ch); |
| 506 | - return 0; | |
| 481 | + return; | |
| 507 | 482 | } |
| 508 | 483 | |
| 509 | 484 | val = current->cmd_dep; |
| ... | ... | @@ -515,23 +490,25 @@ static int store_word(DBDMA_channel *ch, int key, uint32_t addr, |
| 515 | 490 | cpu_physical_memory_write(addr, (uint8_t*)&val, len); |
| 516 | 491 | |
| 517 | 492 | if (conditional_wait(ch)) |
| 518 | - return 1; | |
| 493 | + goto wait; | |
| 519 | 494 | |
| 520 | 495 | current->xfer_status = cpu_to_le16(be32_to_cpu(ch->regs[DBDMA_STATUS])); |
| 521 | 496 | dbdma_cmdptr_save(ch); |
| 497 | + ch->regs[DBDMA_STATUS] &= cpu_to_be32(~FLUSH); | |
| 522 | 498 | |
| 523 | 499 | conditional_interrupt(ch); |
| 524 | 500 | next(ch); |
| 525 | 501 | |
| 526 | - return 1; | |
| 502 | +wait: | |
| 503 | + qemu_bh_schedule(dbdma_bh); | |
| 527 | 504 | } |
| 528 | 505 | |
| 529 | -static int nop(DBDMA_channel *ch) | |
| 506 | +static void nop(DBDMA_channel *ch) | |
| 530 | 507 | { |
| 531 | 508 | dbdma_cmd *current = &ch->current; |
| 532 | 509 | |
| 533 | 510 | if (conditional_wait(ch)) |
| 534 | - return 1; | |
| 511 | + goto wait; | |
| 535 | 512 | |
| 536 | 513 | current->xfer_status = cpu_to_le16(be32_to_cpu(ch->regs[DBDMA_STATUS])); |
| 537 | 514 | dbdma_cmdptr_save(ch); |
| ... | ... | @@ -539,19 +516,18 @@ static int nop(DBDMA_channel *ch) |
| 539 | 516 | conditional_interrupt(ch); |
| 540 | 517 | conditional_branch(ch); |
| 541 | 518 | |
| 542 | - return 1; | |
| 519 | +wait: | |
| 520 | + qemu_bh_schedule(dbdma_bh); | |
| 543 | 521 | } |
| 544 | 522 | |
| 545 | -static int stop(DBDMA_channel *ch) | |
| 523 | +static void stop(DBDMA_channel *ch) | |
| 546 | 524 | { |
| 547 | - ch->regs[DBDMA_STATUS] &= cpu_to_be32(~(ACTIVE|DEAD)); | |
| 525 | + ch->regs[DBDMA_STATUS] &= cpu_to_be32(~(ACTIVE|DEAD|FLUSH)); | |
| 548 | 526 | |
| 549 | 527 | /* the stop command does not increment command pointer */ |
| 550 | - | |
| 551 | - return 0; | |
| 552 | 528 | } |
| 553 | 529 | |
| 554 | -static int channel_run(DBDMA_channel *ch) | |
| 530 | +static void channel_run(DBDMA_channel *ch) | |
| 555 | 531 | { |
| 556 | 532 | dbdma_cmd *current = &ch->current; |
| 557 | 533 | uint16_t cmd, key; |
| ... | ... | @@ -569,10 +545,12 @@ static int channel_run(DBDMA_channel *ch) |
| 569 | 545 | |
| 570 | 546 | switch (cmd) { |
| 571 | 547 | case DBDMA_NOP: |
| 572 | - return nop(ch); | |
| 548 | + nop(ch); | |
| 549 | + return; | |
| 573 | 550 | |
| 574 | 551 | case DBDMA_STOP: |
| 575 | - return stop(ch); | |
| 552 | + stop(ch); | |
| 553 | + return; | |
| 576 | 554 | } |
| 577 | 555 | |
| 578 | 556 | key = le16_to_cpu(current->command) & 0x0700; |
| ... | ... | @@ -582,21 +560,25 @@ static int channel_run(DBDMA_channel *ch) |
| 582 | 560 | if (key == KEY_STREAM4) { |
| 583 | 561 | printf("command %x, invalid key 4\n", cmd); |
| 584 | 562 | kill_channel(ch); |
| 585 | - return 0; | |
| 563 | + return; | |
| 586 | 564 | } |
| 587 | 565 | |
| 588 | 566 | switch (cmd) { |
| 589 | 567 | case OUTPUT_MORE: |
| 590 | - return start_output(ch, key, phy_addr, req_count, 0); | |
| 568 | + start_output(ch, key, phy_addr, req_count, 0); | |
| 569 | + return; | |
| 591 | 570 | |
| 592 | 571 | case OUTPUT_LAST: |
| 593 | - return start_output(ch, key, phy_addr, req_count, 1); | |
| 572 | + start_output(ch, key, phy_addr, req_count, 1); | |
| 573 | + return; | |
| 594 | 574 | |
| 595 | 575 | case INPUT_MORE: |
| 596 | - return start_input(ch, key, phy_addr, req_count, 0); | |
| 576 | + start_input(ch, key, phy_addr, req_count, 0); | |
| 577 | + return; | |
| 597 | 578 | |
| 598 | 579 | case INPUT_LAST: |
| 599 | - return start_input(ch, key, phy_addr, req_count, 1); | |
| 580 | + start_input(ch, key, phy_addr, req_count, 1); | |
| 581 | + return; | |
| 600 | 582 | } |
| 601 | 583 | |
| 602 | 584 | if (key < KEY_REGS) { |
| ... | ... | @@ -620,35 +602,24 @@ static int channel_run(DBDMA_channel *ch) |
| 620 | 602 | |
| 621 | 603 | switch (cmd) { |
| 622 | 604 | case LOAD_WORD: |
| 623 | - return load_word(ch, key, phy_addr, req_count); | |
| 605 | + load_word(ch, key, phy_addr, req_count); | |
| 606 | + return; | |
| 624 | 607 | |
| 625 | 608 | case STORE_WORD: |
| 626 | - return store_word(ch, key, phy_addr, req_count); | |
| 609 | + store_word(ch, key, phy_addr, req_count); | |
| 610 | + return; | |
| 627 | 611 | } |
| 628 | - | |
| 629 | - return 0; | |
| 630 | 612 | } |
| 631 | 613 | |
| 632 | -static QEMUBH *dbdma_bh; | |
| 633 | - | |
| 634 | 614 | static void DBDMA_run (DBDMA_channel *ch) |
| 635 | 615 | { |
| 636 | 616 | int channel; |
| 637 | - int rearm = 0; | |
| 638 | 617 | |
| 639 | 618 | for (channel = 0; channel < DBDMA_CHANNELS; channel++, ch++) { |
| 640 | 619 | uint32_t status = be32_to_cpu(ch->regs[DBDMA_STATUS]); |
| 641 | - if ((status & RUN) && (status & ACTIVE)) { | |
| 642 | - if (status & FLUSH) | |
| 643 | - while (channel_run(ch)); | |
| 644 | - else if (channel_run(ch)) | |
| 645 | - rearm = 1; | |
| 646 | - } | |
| 647 | - ch->regs[DBDMA_STATUS] &= cpu_to_be32(~FLUSH); | |
| 620 | + if (!ch->processing && (status & RUN) && (status & ACTIVE)) | |
| 621 | + channel_run(ch); | |
| 648 | 622 | } |
| 649 | - | |
| 650 | - if (rearm) | |
| 651 | - qemu_bh_schedule_idle(dbdma_bh); | |
| 652 | 623 | } |
| 653 | 624 | |
| 654 | 625 | static void DBDMA_run_bh(void *opaque) |
| ... | ... | @@ -661,7 +632,7 @@ static void DBDMA_run_bh(void *opaque) |
| 661 | 632 | } |
| 662 | 633 | |
| 663 | 634 | void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq, |
| 664 | - DBDMA_transfer_handler transfer_handler, | |
| 635 | + DBDMA_rw rw, | |
| 665 | 636 | void *opaque) |
| 666 | 637 | { |
| 667 | 638 | DBDMA_channel *ch = ( DBDMA_channel *)dbdma + nchan; |
| ... | ... | @@ -670,7 +641,7 @@ void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq, |
| 670 | 641 | |
| 671 | 642 | ch->irq = irq; |
| 672 | 643 | ch->channel = nchan; |
| 673 | - ch->transfer_handler = transfer_handler; | |
| 644 | + ch->rw = rw; | |
| 674 | 645 | ch->io.opaque = opaque; |
| 675 | 646 | ch->io.channel = ch; |
| 676 | 647 | } |
| ... | ... | @@ -714,11 +685,8 @@ dbdma_control_write(DBDMA_channel *ch) |
| 714 | 685 | |
| 715 | 686 | ch->regs[DBDMA_STATUS] = cpu_to_be32(status); |
| 716 | 687 | |
| 717 | - if (status & ACTIVE) { | |
| 718 | - qemu_bh_schedule_idle(dbdma_bh); | |
| 719 | - if (status & FLUSH) | |
| 720 | - DBDMA_schedule(); | |
| 721 | - } | |
| 688 | + if (status & ACTIVE) | |
| 689 | + qemu_bh_schedule(dbdma_bh); | |
| 722 | 690 | } |
| 723 | 691 | |
| 724 | 692 | static void dbdma_writel (void *opaque, | ... | ... |
hw/mac_dbdma.h
| ... | ... | @@ -20,22 +20,23 @@ |
| 20 | 20 | * THE SOFTWARE. |
| 21 | 21 | */ |
| 22 | 22 | |
| 23 | -typedef struct { | |
| 23 | +typedef struct DBDMA_io DBDMA_io; | |
| 24 | + | |
| 25 | +typedef void (*DBDMA_rw)(DBDMA_io *io); | |
| 26 | +typedef void (*DBDMA_end)(DBDMA_io *io); | |
| 27 | +struct DBDMA_io { | |
| 24 | 28 | void *opaque; |
| 25 | 29 | void *channel; |
| 30 | + target_phys_addr_t addr; | |
| 26 | 31 | int len; |
| 27 | 32 | int is_last; |
| 28 | - void *buf; | |
| 29 | - int buf_pos; | |
| 30 | - int buf_len; | |
| 31 | -} DBDMA_transfer; | |
| 33 | + int is_dma_out; | |
| 34 | + DBDMA_end dma_end; | |
| 35 | +}; | |
| 32 | 36 | |
| 33 | -typedef int (*DBDMA_transfer_cb)(DBDMA_transfer *info); | |
| 34 | -typedef int (*DBDMA_transfer_handler)(DBDMA_transfer *info, | |
| 35 | - DBDMA_transfer_cb cb); | |
| 36 | 37 | |
| 37 | 38 | void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq, |
| 38 | - DBDMA_transfer_handler transfer_handler, | |
| 39 | + DBDMA_rw rw, | |
| 39 | 40 | void *opaque); |
| 40 | 41 | void DBDMA_schedule(void); |
| 41 | 42 | void* DBDMA_init (int *dbdma_mem_index); | ... | ... |