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); |