Revision b42ec42d
b/hw/ide.c | ||
---|---|---|
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 | 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 | 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); |
b/hw/mac_dbdma.c | ||
---|---|---|
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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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, |
b/hw/mac_dbdma.h | ||
---|---|---|
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); |
Also available in: Unified diff