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,71 +3429,69 @@ void pci_piix4_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn, | ||
| 3429 | 3429 | ||
| 3430 | typedef struct MACIOIDEState { | 3430 | typedef struct MACIOIDEState { |
| 3431 | IDEState ide_if[2]; | 3431 | IDEState ide_if[2]; |
| 3432 | - void *dbdma; | ||
| 3433 | int stream_index; | 3432 | int stream_index; |
| 3434 | } MACIOIDEState; | 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 | IDEState *s = m->ide_if->cur_drive; | 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 | if (ret < 0) { | 3446 | if (ret < 0) { |
| 3447 | + io->dma_end(io); | ||
| 3451 | ide_transfer_stop(s); | 3448 | ide_transfer_stop(s); |
| 3452 | ide_atapi_io_error(s, ret); | 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 | /* db-dma can ask for 512 bytes whereas block size is 2048... */ | 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 | s->lba += m->stream_index / s->cd_sector_size; | 3462 | s->lba += m->stream_index / s->cd_sector_size; |
| 3468 | m->stream_index %= s->cd_sector_size; | 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 | if (s->packet_transfer_size <= 0) { | 3473 | if (s->packet_transfer_size <= 0) { |
| 3474 | s->status = READY_STAT | SEEK_STAT; | 3474 | s->status = READY_STAT | SEEK_STAT; |
| 3475 | s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | 3475 | s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO |
| 3476 | | ATAPI_INT_REASON_CD; | 3476 | | ATAPI_INT_REASON_CD; |
| 3477 | ide_set_irq(s); | 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 | IDEState *s = m->ide_if->cur_drive; | 3484 | IDEState *s = m->ide_if->cur_drive; |
| 3488 | int64_t sector_num; | 3485 | int64_t sector_num; |
| 3489 | int ret, n; | 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 | sector_num = ide_get_sector(s); | 3496 | sector_num = ide_get_sector(s); |
| 3499 | 3497 | ||
| @@ -3501,36 +3499,40 @@ static int pmac_ide_transfer(DBDMA_transfer *info, | @@ -3501,36 +3499,40 @@ static int pmac_ide_transfer(DBDMA_transfer *info, | ||
| 3501 | if (n > IDE_DMA_BUF_SECTORS) | 3499 | if (n > IDE_DMA_BUF_SECTORS) |
| 3502 | n = IDE_DMA_BUF_SECTORS; | 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 | if (s->is_read) { | 3507 | if (s->is_read) { |
| 3510 | ret = bdrv_read(s->bs, sector_num, s->io_buffer, n); | 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 | } else { | 3510 | } else { |
| 3514 | - cb(info); | 3511 | + cpu_physical_memory_read(io->addr, s->io_buffer, len); |
| 3515 | ret = bdrv_write(s->bs, sector_num, s->io_buffer, n); | 3512 | ret = bdrv_write(s->bs, sector_num, s->io_buffer, n); |
| 3516 | } | 3513 | } |
| 3517 | 3514 | ||
| 3518 | if (ret != 0) { | 3515 | if (ret != 0) { |
| 3516 | + io->dma_end(io); | ||
| 3519 | ide_rw_error(s); | 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 | ide_set_sector(s, sector_num + n); | 3523 | ide_set_sector(s, sector_num + n); |
| 3525 | s->nsector -= n; | 3524 | s->nsector -= n; |
| 3526 | } | 3525 | } |
| 3527 | 3526 | ||
| 3527 | + if (io->len <= 0) | ||
| 3528 | + io->dma_end(io); | ||
| 3529 | + | ||
| 3528 | if (s->nsector <= 0) { | 3530 | if (s->nsector <= 0) { |
| 3529 | s->status = READY_STAT | SEEK_STAT; | 3531 | s->status = READY_STAT | SEEK_STAT; |
| 3530 | ide_set_irq(s); | 3532 | ide_set_irq(s); |
| 3531 | } | 3533 | } |
| 3532 | 3534 | ||
| 3533 | - return info->buf_pos; | 3535 | + return; |
| 3534 | } | 3536 | } |
| 3535 | 3537 | ||
| 3536 | /* PowerMac IDE memory IO */ | 3538 | /* PowerMac IDE memory IO */ |
| @@ -3709,10 +3711,8 @@ int pmac_ide_init (BlockDriverState **hd_table, qemu_irq irq, | @@ -3709,10 +3711,8 @@ int pmac_ide_init (BlockDriverState **hd_table, qemu_irq irq, | ||
| 3709 | d = qemu_mallocz(sizeof(MACIOIDEState)); | 3711 | d = qemu_mallocz(sizeof(MACIOIDEState)); |
| 3710 | ide_init2(d->ide_if, hd_table[0], hd_table[1], irq); | 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 | DBDMA_register_channel(dbdma, channel, dma_irq, pmac_ide_transfer, d); | 3715 | DBDMA_register_channel(dbdma, channel, dma_irq, pmac_ide_transfer, d); |
| 3715 | - } | ||
| 3716 | 3716 | ||
| 3717 | pmac_ide_memory = cpu_register_io_memory(0, pmac_ide_read, | 3717 | pmac_ide_memory = cpu_register_io_memory(0, pmac_ide_read, |
| 3718 | pmac_ide_write, d); | 3718 | pmac_ide_write, d); |
hw/mac_dbdma.c
| @@ -158,9 +158,10 @@ typedef struct DBDMA_channel { | @@ -158,9 +158,10 @@ typedef struct DBDMA_channel { | ||
| 158 | int channel; | 158 | int channel; |
| 159 | uint32_t regs[DBDMA_REGS]; | 159 | uint32_t regs[DBDMA_REGS]; |
| 160 | qemu_irq irq; | 160 | qemu_irq irq; |
| 161 | - DBDMA_transfer io; | ||
| 162 | - DBDMA_transfer_handler transfer_handler; | 161 | + DBDMA_io io; |
| 162 | + DBDMA_rw rw; | ||
| 163 | dbdma_cmd current; | 163 | dbdma_cmd current; |
| 164 | + int processing; | ||
| 164 | } DBDMA_channel; | 165 | } DBDMA_channel; |
| 165 | 166 | ||
| 166 | #ifdef DEBUG_DBDMA | 167 | #ifdef DEBUG_DBDMA |
| @@ -218,7 +219,7 @@ static void conditional_interrupt(DBDMA_channel *ch) | @@ -218,7 +219,7 @@ static void conditional_interrupt(DBDMA_channel *ch) | ||
| 218 | 219 | ||
| 219 | DBDMA_DPRINTF("conditional_interrupt\n"); | 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 | switch(intr) { | 224 | switch(intr) { |
| 224 | case INTR_NEVER: /* don't interrupt */ | 225 | case INTR_NEVER: /* don't interrupt */ |
| @@ -257,7 +258,7 @@ static int conditional_wait(DBDMA_channel *ch) | @@ -257,7 +258,7 @@ static int conditional_wait(DBDMA_channel *ch) | ||
| 257 | 258 | ||
| 258 | DBDMA_DPRINTF("conditional_wait\n"); | 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 | switch(wait) { | 263 | switch(wait) { |
| 263 | case WAIT_NEVER: /* don't wait */ | 264 | case WAIT_NEVER: /* don't wait */ |
| @@ -318,7 +319,7 @@ static void conditional_branch(DBDMA_channel *ch) | @@ -318,7 +319,7 @@ static void conditional_branch(DBDMA_channel *ch) | ||
| 318 | 319 | ||
| 319 | /* check if we must branch */ | 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 | switch(br) { | 324 | switch(br) { |
| 324 | case BR_NEVER: /* don't branch */ | 325 | case BR_NEVER: /* don't branch */ |
| @@ -352,38 +353,35 @@ static void conditional_branch(DBDMA_channel *ch) | @@ -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 | DBDMA_channel *ch = io->channel; | 361 | DBDMA_channel *ch = io->channel; |
| 371 | dbdma_cmd *current = &ch->current; | 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 | uint16_t req_count, int is_last) | 383 | uint16_t req_count, int is_last) |
| 383 | { | 384 | { |
| 384 | - dbdma_cmd *current = &ch->current; | ||
| 385 | - uint32_t n; | ||
| 386 | - | ||
| 387 | DBDMA_DPRINTF("start_output\n"); | 385 | DBDMA_DPRINTF("start_output\n"); |
| 388 | 386 | ||
| 389 | /* KEY_REGS, KEY_DEVICE and KEY_STREAM | 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,35 +391,21 @@ static int start_output(DBDMA_channel *ch, int key, uint32_t addr, | ||
| 393 | DBDMA_DPRINTF("addr 0x%x key 0x%x\n", addr, key); | 391 | DBDMA_DPRINTF("addr 0x%x key 0x%x\n", addr, key); |
| 394 | if (!addr || key > KEY_STREAM3) { | 392 | if (!addr || key > KEY_STREAM3) { |
| 395 | kill_channel(ch); | 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 | ch->io.len = req_count; | 398 | ch->io.len = req_count; |
| 403 | ch->io.is_last = is_last; | 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 | uint16_t req_count, int is_last) | 407 | uint16_t req_count, int is_last) |
| 421 | { | 408 | { |
| 422 | - dbdma_cmd *current = &ch->current; | ||
| 423 | - uint32_t n; | ||
| 424 | - | ||
| 425 | DBDMA_DPRINTF("start_input\n"); | 409 | DBDMA_DPRINTF("start_input\n"); |
| 426 | 410 | ||
| 427 | /* KEY_REGS, KEY_DEVICE and KEY_STREAM | 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,30 +414,19 @@ static int start_input(DBDMA_channel *ch, int key, uint32_t addr, | ||
| 430 | 414 | ||
| 431 | if (!addr || key > KEY_STREAM3) { | 415 | if (!addr || key > KEY_STREAM3) { |
| 432 | kill_channel(ch); | 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 | ch->io.len = req_count; | 421 | ch->io.len = req_count; |
| 440 | ch->io.is_last = is_last; | 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 | uint16_t len) | 430 | uint16_t len) |
| 458 | { | 431 | { |
| 459 | dbdma_cmd *current = &ch->current; | 432 | dbdma_cmd *current = &ch->current; |
| @@ -466,7 +439,7 @@ static int load_word(DBDMA_channel *ch, int key, uint32_t addr, | @@ -466,7 +439,7 @@ static int load_word(DBDMA_channel *ch, int key, uint32_t addr, | ||
| 466 | if (key != KEY_SYSTEM) { | 439 | if (key != KEY_SYSTEM) { |
| 467 | printf("DBDMA: LOAD_WORD, unimplemented key %x\n", key); | 440 | printf("DBDMA: LOAD_WORD, unimplemented key %x\n", key); |
| 468 | kill_channel(ch); | 441 | kill_channel(ch); |
| 469 | - return 0; | 442 | + return; |
| 470 | } | 443 | } |
| 471 | 444 | ||
| 472 | cpu_physical_memory_read(addr, (uint8_t*)&val, len); | 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,18 +452,20 @@ static int load_word(DBDMA_channel *ch, int key, uint32_t addr, | ||
| 479 | current->cmd_dep = val; | 452 | current->cmd_dep = val; |
| 480 | 453 | ||
| 481 | if (conditional_wait(ch)) | 454 | if (conditional_wait(ch)) |
| 482 | - return 1; | 455 | + goto wait; |
| 483 | 456 | ||
| 484 | current->xfer_status = cpu_to_le16(be32_to_cpu(ch->regs[DBDMA_STATUS])); | 457 | current->xfer_status = cpu_to_le16(be32_to_cpu(ch->regs[DBDMA_STATUS])); |
| 485 | dbdma_cmdptr_save(ch); | 458 | dbdma_cmdptr_save(ch); |
| 459 | + ch->regs[DBDMA_STATUS] &= cpu_to_be32(~FLUSH); | ||
| 486 | 460 | ||
| 487 | conditional_interrupt(ch); | 461 | conditional_interrupt(ch); |
| 488 | next(ch); | 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 | uint16_t len) | 469 | uint16_t len) |
| 495 | { | 470 | { |
| 496 | dbdma_cmd *current = &ch->current; | 471 | dbdma_cmd *current = &ch->current; |
| @@ -503,7 +478,7 @@ static int store_word(DBDMA_channel *ch, int key, uint32_t addr, | @@ -503,7 +478,7 @@ static int store_word(DBDMA_channel *ch, int key, uint32_t addr, | ||
| 503 | if (key != KEY_SYSTEM) { | 478 | if (key != KEY_SYSTEM) { |
| 504 | printf("DBDMA: STORE_WORD, unimplemented key %x\n", key); | 479 | printf("DBDMA: STORE_WORD, unimplemented key %x\n", key); |
| 505 | kill_channel(ch); | 480 | kill_channel(ch); |
| 506 | - return 0; | 481 | + return; |
| 507 | } | 482 | } |
| 508 | 483 | ||
| 509 | val = current->cmd_dep; | 484 | val = current->cmd_dep; |
| @@ -515,23 +490,25 @@ static int store_word(DBDMA_channel *ch, int key, uint32_t addr, | @@ -515,23 +490,25 @@ static int store_word(DBDMA_channel *ch, int key, uint32_t addr, | ||
| 515 | cpu_physical_memory_write(addr, (uint8_t*)&val, len); | 490 | cpu_physical_memory_write(addr, (uint8_t*)&val, len); |
| 516 | 491 | ||
| 517 | if (conditional_wait(ch)) | 492 | if (conditional_wait(ch)) |
| 518 | - return 1; | 493 | + goto wait; |
| 519 | 494 | ||
| 520 | current->xfer_status = cpu_to_le16(be32_to_cpu(ch->regs[DBDMA_STATUS])); | 495 | current->xfer_status = cpu_to_le16(be32_to_cpu(ch->regs[DBDMA_STATUS])); |
| 521 | dbdma_cmdptr_save(ch); | 496 | dbdma_cmdptr_save(ch); |
| 497 | + ch->regs[DBDMA_STATUS] &= cpu_to_be32(~FLUSH); | ||
| 522 | 498 | ||
| 523 | conditional_interrupt(ch); | 499 | conditional_interrupt(ch); |
| 524 | next(ch); | 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 | dbdma_cmd *current = &ch->current; | 508 | dbdma_cmd *current = &ch->current; |
| 532 | 509 | ||
| 533 | if (conditional_wait(ch)) | 510 | if (conditional_wait(ch)) |
| 534 | - return 1; | 511 | + goto wait; |
| 535 | 512 | ||
| 536 | current->xfer_status = cpu_to_le16(be32_to_cpu(ch->regs[DBDMA_STATUS])); | 513 | current->xfer_status = cpu_to_le16(be32_to_cpu(ch->regs[DBDMA_STATUS])); |
| 537 | dbdma_cmdptr_save(ch); | 514 | dbdma_cmdptr_save(ch); |
| @@ -539,19 +516,18 @@ static int nop(DBDMA_channel *ch) | @@ -539,19 +516,18 @@ static int nop(DBDMA_channel *ch) | ||
| 539 | conditional_interrupt(ch); | 516 | conditional_interrupt(ch); |
| 540 | conditional_branch(ch); | 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 | /* the stop command does not increment command pointer */ | 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 | dbdma_cmd *current = &ch->current; | 532 | dbdma_cmd *current = &ch->current; |
| 557 | uint16_t cmd, key; | 533 | uint16_t cmd, key; |
| @@ -569,10 +545,12 @@ static int channel_run(DBDMA_channel *ch) | @@ -569,10 +545,12 @@ static int channel_run(DBDMA_channel *ch) | ||
| 569 | 545 | ||
| 570 | switch (cmd) { | 546 | switch (cmd) { |
| 571 | case DBDMA_NOP: | 547 | case DBDMA_NOP: |
| 572 | - return nop(ch); | 548 | + nop(ch); |
| 549 | + return; | ||
| 573 | 550 | ||
| 574 | case DBDMA_STOP: | 551 | case DBDMA_STOP: |
| 575 | - return stop(ch); | 552 | + stop(ch); |
| 553 | + return; | ||
| 576 | } | 554 | } |
| 577 | 555 | ||
| 578 | key = le16_to_cpu(current->command) & 0x0700; | 556 | key = le16_to_cpu(current->command) & 0x0700; |
| @@ -582,21 +560,25 @@ static int channel_run(DBDMA_channel *ch) | @@ -582,21 +560,25 @@ static int channel_run(DBDMA_channel *ch) | ||
| 582 | if (key == KEY_STREAM4) { | 560 | if (key == KEY_STREAM4) { |
| 583 | printf("command %x, invalid key 4\n", cmd); | 561 | printf("command %x, invalid key 4\n", cmd); |
| 584 | kill_channel(ch); | 562 | kill_channel(ch); |
| 585 | - return 0; | 563 | + return; |
| 586 | } | 564 | } |
| 587 | 565 | ||
| 588 | switch (cmd) { | 566 | switch (cmd) { |
| 589 | case OUTPUT_MORE: | 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 | case OUTPUT_LAST: | 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 | case INPUT_MORE: | 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 | case INPUT_LAST: | 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 | if (key < KEY_REGS) { | 584 | if (key < KEY_REGS) { |
| @@ -620,35 +602,24 @@ static int channel_run(DBDMA_channel *ch) | @@ -620,35 +602,24 @@ static int channel_run(DBDMA_channel *ch) | ||
| 620 | 602 | ||
| 621 | switch (cmd) { | 603 | switch (cmd) { |
| 622 | case LOAD_WORD: | 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 | case STORE_WORD: | 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 | static void DBDMA_run (DBDMA_channel *ch) | 614 | static void DBDMA_run (DBDMA_channel *ch) |
| 635 | { | 615 | { |
| 636 | int channel; | 616 | int channel; |
| 637 | - int rearm = 0; | ||
| 638 | 617 | ||
| 639 | for (channel = 0; channel < DBDMA_CHANNELS; channel++, ch++) { | 618 | for (channel = 0; channel < DBDMA_CHANNELS; channel++, ch++) { |
| 640 | uint32_t status = be32_to_cpu(ch->regs[DBDMA_STATUS]); | 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 | static void DBDMA_run_bh(void *opaque) | 625 | static void DBDMA_run_bh(void *opaque) |
| @@ -661,7 +632,7 @@ static void DBDMA_run_bh(void *opaque) | @@ -661,7 +632,7 @@ static void DBDMA_run_bh(void *opaque) | ||
| 661 | } | 632 | } |
| 662 | 633 | ||
| 663 | void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq, | 634 | void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq, |
| 664 | - DBDMA_transfer_handler transfer_handler, | 635 | + DBDMA_rw rw, |
| 665 | void *opaque) | 636 | void *opaque) |
| 666 | { | 637 | { |
| 667 | DBDMA_channel *ch = ( DBDMA_channel *)dbdma + nchan; | 638 | DBDMA_channel *ch = ( DBDMA_channel *)dbdma + nchan; |
| @@ -670,7 +641,7 @@ void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq, | @@ -670,7 +641,7 @@ void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq, | ||
| 670 | 641 | ||
| 671 | ch->irq = irq; | 642 | ch->irq = irq; |
| 672 | ch->channel = nchan; | 643 | ch->channel = nchan; |
| 673 | - ch->transfer_handler = transfer_handler; | 644 | + ch->rw = rw; |
| 674 | ch->io.opaque = opaque; | 645 | ch->io.opaque = opaque; |
| 675 | ch->io.channel = ch; | 646 | ch->io.channel = ch; |
| 676 | } | 647 | } |
| @@ -714,11 +685,8 @@ dbdma_control_write(DBDMA_channel *ch) | @@ -714,11 +685,8 @@ dbdma_control_write(DBDMA_channel *ch) | ||
| 714 | 685 | ||
| 715 | ch->regs[DBDMA_STATUS] = cpu_to_be32(status); | 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 | static void dbdma_writel (void *opaque, | 692 | static void dbdma_writel (void *opaque, |
hw/mac_dbdma.h
| @@ -20,22 +20,23 @@ | @@ -20,22 +20,23 @@ | ||
| 20 | * THE SOFTWARE. | 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 | void *opaque; | 28 | void *opaque; |
| 25 | void *channel; | 29 | void *channel; |
| 30 | + target_phys_addr_t addr; | ||
| 26 | int len; | 31 | int len; |
| 27 | int is_last; | 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 | void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq, | 38 | void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq, |
| 38 | - DBDMA_transfer_handler transfer_handler, | 39 | + DBDMA_rw rw, |
| 39 | void *opaque); | 40 | void *opaque); |
| 40 | void DBDMA_schedule(void); | 41 | void DBDMA_schedule(void); |
| 41 | void* DBDMA_init (int *dbdma_mem_index); | 42 | void* DBDMA_init (int *dbdma_mem_index); |