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