# HG changeset patch # User Paul Boddie # Date 1708035489 -3600 # Node ID 902a8354a7b38b2a0ad53b1932dfb516bc7557e2 # Parent 4d650147531136ded5488c06d46ba1b71706162c Added some support for multiple block MMC/SD transfers. diff -r 4d6501475311 -r 902a8354a7b3 pkg/devices/lib/msc/include/msc-common.h --- a/pkg/devices/lib/msc/include/msc-common.h Thu Feb 15 23:15:30 2024 +0100 +++ b/pkg/devices/lib/msc/include/msc-common.h Thu Feb 15 23:18:09 2024 +0100 @@ -144,7 +144,8 @@ uint32_t get_status(); - uint32_t read_block(uint8_t card, l4re_dma_space_dma_addr_t paddr); + uint32_t read_blocks(uint8_t card, l4re_dma_space_dma_addr_t paddr, + uint32_t block_address, uint32_t block_count); }; diff -r 4d6501475311 -r 902a8354a7b3 pkg/devices/lib/msc/include/msc-jz4780.h --- a/pkg/devices/lib/msc/include/msc-jz4780.h Thu Feb 15 23:15:30 2024 +0100 +++ b/pkg/devices/lib/msc/include/msc-jz4780.h Thu Feb 15 23:18:09 2024 +0100 @@ -83,7 +83,8 @@ void jz4780_msc_enable(void *msc_channel); -uint32_t jz4780_msc_read_block(void *msc_channel, uint8_t card, - l4re_dma_space_dma_addr_t paddr); +uint32_t jz4780_msc_read_blocks(void *msc_channel, uint8_t card, + l4re_dma_space_dma_addr_t paddr, + uint32_t block_address, uint32_t block_count); EXTERN_C_END diff -r 4d6501475311 -r 902a8354a7b3 pkg/devices/lib/msc/include/msc-x1600.h --- a/pkg/devices/lib/msc/include/msc-x1600.h Thu Feb 15 23:15:30 2024 +0100 +++ b/pkg/devices/lib/msc/include/msc-x1600.h Thu Feb 15 23:18:09 2024 +0100 @@ -81,7 +81,8 @@ void x1600_msc_enable(void *msc_channel); -uint32_t x1600_msc_read_block(void *msc_channel, uint8_t card, - l4re_dma_space_dma_addr_t paddr); +uint32_t x1600_msc_read_blocks(void *msc_channel, uint8_t card, + l4re_dma_space_dma_addr_t paddr, + uint32_t block_address, uint32_t block_count); EXTERN_C_END diff -r 4d6501475311 -r 902a8354a7b3 pkg/devices/lib/msc/src/common.cc --- a/pkg/devices/lib/msc/src/common.cc Thu Feb 15 23:15:30 2024 +0100 +++ b/pkg/devices/lib/msc/src/common.cc Thu Feb 15 23:18:09 2024 +0100 @@ -914,9 +914,11 @@ // Determine whether a timeout occurred. - bool have_response = !(_regs[Msc_interrupt_flag] & Int_response_timeout); + bool have_response = !((_regs[Msc_interrupt_flag] & Int_response_timeout) || + (_regs[Msc_status] & Status_response_crc_error) || + (_regs[Msc_status] & Status_timeout_response)); - // Acknowledge the interrupts and return the status. + // Acknowledge the response interrupts and return the status. ack_irq(flags); return have_response; @@ -1190,24 +1192,51 @@ uint32_t Msc_channel::recv_data(l4re_dma_space_dma_addr_t paddr, uint32_t count) { - return transfer(_msc_start + Msc_recv_data_fifo, paddr, true, count); + uint32_t flags = Int_data_transfer_done; + + unmask_irq(flags); + + uint32_t to_transfer = transfer(_msc_start + Msc_recv_data_fifo, paddr, true, count); + + wait_for_irq(flags); + ack_irq(flags); + + if (!to_transfer || + (_regs[Msc_status] & Status_read_crc_error) || + (_regs[Msc_status] & Status_timeout_read)) + return 0; + + return to_transfer; } uint32_t Msc_channel::send_data(l4re_dma_space_dma_addr_t paddr, uint32_t count) { - return transfer(paddr, _msc_start + Msc_trans_data_fifo, false, count); + uint32_t flags = Int_data_transfer_done; + + unmask_irq(flags); + + uint32_t to_transfer = transfer(paddr, _msc_start + Msc_trans_data_fifo, false, count); + + wait_for_irq(flags); + ack_irq(flags); + + if (!to_transfer || + (_regs[Msc_status] & Status_write_crc_error_data) || + (_regs[Msc_status] & Status_write_crc_error_no_status)) + return 0; + + return to_transfer; } uint32_t -Msc_channel::read_block(uint8_t card, l4re_dma_space_dma_addr_t paddr) +Msc_channel::read_blocks(uint8_t card, l4re_dma_space_dma_addr_t paddr, + uint32_t block_address, uint32_t block_count) { uint32_t block_size = 1 << _csd[card].read_blocklen; uint16_t buffer[Response_size_R1]; struct R1 *r = (struct R1 *) buffer; - //printf("read_block: card %d -> %d\n", card, _rca[card]); - // Select the requested card. if (_current_rca != _rca[card]) @@ -1245,15 +1274,18 @@ if (r->status & R1_status_error_mask) return 0; + // NOTE: Consider issuing a predefined block count command to any multiple + // NOTE: block operation, at least for cards that support it. + // Apply block count and size properties to the issued command. - _regs[Msc_block_count] = 1; + _regs[Msc_block_count] = block_count; _regs[Msc_block_length] = block_size; - // NOTE: Support an actual address. // NOTE: Where CCS = 0, byte addressing is used. Otherwise, block addressing is used. - if (!send_command(Command_read_single_block, 0)) + if (!send_command(block_count == 1 ? Command_read_single_block + : Command_read_multiple_block, block_address)) return 0; read_response(buffer, Response_size_R1); @@ -1261,7 +1293,14 @@ if (r->status & R1_status_error_mask) return 0; - return recv_data(paddr, block_size); + // NOTE: Use Msc_block_success_count instead. + + uint32_t transferred = recv_data(paddr, block_size * block_count); + + if (block_count > 1) + send_command(Command_stop_transmission, 0); + + return transferred; } // Wait indefinitely for an interrupt request, returning true if one was delivered. diff -r 4d6501475311 -r 902a8354a7b3 pkg/devices/lib/msc/src/jz4780.cc --- a/pkg/devices/lib/msc/src/jz4780.cc Thu Feb 15 23:15:30 2024 +0100 +++ b/pkg/devices/lib/msc/src/jz4780.cc Thu Feb 15 23:18:09 2024 +0100 @@ -50,7 +50,7 @@ } // Request the transfer of the indicated number of bytes between two physical -// addresses in the indicated direction, returning the number of bytes +// addresses in the indicated direction, returning the number of bytes to be // transferred. // NOTE: To be consolidated into a generic method that uses generic request types. @@ -70,7 +70,7 @@ 4, 4, unit_size, recv ? _request_type_in : _request_type_out); - return to_transfer - _dma->wait() * unit_size; + return to_transfer * unit_size; } @@ -126,8 +126,10 @@ static_cast(msc_channel)->enable(); } -uint32_t jz4780_msc_read_block(void *msc_channel, uint8_t card, - l4re_dma_space_dma_addr_t paddr) +uint32_t jz4780_msc_read_blocks(void *msc_channel, uint8_t card, + l4re_dma_space_dma_addr_t paddr, + uint32_t block_address, uint32_t block_count) { - return static_cast(msc_channel)->read_block(card, paddr); + return static_cast(msc_channel)->read_blocks(card, paddr, + block_address, block_count); } diff -r 4d6501475311 -r 902a8354a7b3 pkg/devices/lib/msc/src/x1600.cc --- a/pkg/devices/lib/msc/src/x1600.cc Thu Feb 15 23:15:30 2024 +0100 +++ b/pkg/devices/lib/msc/src/x1600.cc Thu Feb 15 23:18:09 2024 +0100 @@ -50,7 +50,7 @@ } // Request the transfer of the indicated number of bytes between two physical -// addresses in the indicated direction, returning the number of bytes +// addresses in the indicated direction, returning the number of bytes to be // transferred. // NOTE: To be consolidated into a generic method that uses generic request types. @@ -70,7 +70,7 @@ 4, 4, unit_size, recv ? _request_type_in : _request_type_out); - return to_transfer - _dma->wait() * unit_size; + return to_transfer * unit_size; } @@ -126,8 +126,10 @@ static_cast(msc_channel)->enable(); } -uint32_t x1600_msc_read_block(void *msc_channel, uint8_t card, - l4re_dma_space_dma_addr_t paddr) +uint32_t x1600_msc_read_blocks(void *msc_channel, uint8_t card, + l4re_dma_space_dma_addr_t paddr, + uint32_t block_address, uint32_t block_count) { - return static_cast(msc_channel)->read_block(card, paddr); + return static_cast(msc_channel)->read_blocks(card, paddr, + block_address, block_count); } diff -r 4d6501475311 -r 902a8354a7b3 pkg/landfall-examples/hw_info/common.h --- a/pkg/landfall-examples/hw_info/common.h Thu Feb 15 23:15:30 2024 +0100 +++ b/pkg/landfall-examples/hw_info/common.h Thu Feb 15 23:18:09 2024 +0100 @@ -176,7 +176,9 @@ void msc_enable(void *msc_channel); -uint32_t msc_read_block(void *msc_channel, uint8_t card, l4re_dma_space_dma_addr_t paddr); +uint32_t msc_read_blocks(void *msc_channel, uint8_t card, + l4re_dma_space_dma_addr_t paddr, + uint32_t block_address, uint32_t block_count); diff -r 4d6501475311 -r 902a8354a7b3 pkg/landfall-examples/hw_info/hw_info.c --- a/pkg/landfall-examples/hw_info/hw_info.c Thu Feb 15 23:15:30 2024 +0100 +++ b/pkg/landfall-examples/hw_info/hw_info.c Thu Feb 15 23:18:09 2024 +0100 @@ -497,11 +497,37 @@ return init_irq(0, dma_irq, dma_irq_start, dma_irq_end); } +static void _show_dma_region(struct dma_region *region, uint32_t offset) +{ + unsigned int i; + + printf("size = %d; align = %d; virtual = 0x%lx; physical = 0x%llx\ndata (offset 0x%x) =", + region->size, region->align, region->vaddr, region->paddr, offset); + + for (i = 0; (i < region->size) && (i < 16); i++) + printf(" %02x", *((uint8_t *) region->vaddr + offset + i)); + + printf("\n"); +} + +static void show_dma_region(void) +{ + struct dma_region *region = _get_dma_region(); + uint32_t offset; + + if (region == NULL) + return; + + if (!read_number("Offset", &offset)) + return; + + _show_dma_region(region, offset); +} + static void list_dma_regions(void) { unsigned int num; struct dma_region *region; - unsigned int i; for (num = 0; num < num_dma_regions; num++) { @@ -512,15 +538,7 @@ if (l4_is_invalid_cap(region->mem)) printf("(inactive)\n"); else - { - printf("size = %d; align = %d; virtual = 0x%lx; physical = 0x%llx\ndata =", - region->size, region->align, region->vaddr, region->paddr); - - for (i = 0; (i < region->size) && (i < 16); i++) - printf(" %02x", *((uint8_t *) region->vaddr + i)); - - printf("\n"); - } + _show_dma_region(region, 0); } } @@ -1172,11 +1190,11 @@ msc_enable(channel); } -static void read_block_from_msc(void) +static void read_blocks_from_msc(void) { void *channel = get_channel(num_msc_channels, msc_channels, NULL); struct dma_region *dma_region = NULL; - uint32_t card, transferred; + uint32_t card, transferred, block_address, block_count; if (channel == NULL) return; @@ -1189,9 +1207,24 @@ if (!read_number("Card", &card)) return; + if (!read_number("Block address", &block_address)) + return; + + if (!read_number("Block count", &block_count)) + return; + + /* NOTE: Assuming 512-byte blocks. */ + + if (block_count * 512 > dma_region->size) + { + printf("Too many blocks for region.\n"); + return; + } + l4_cache_inv_data(dma_region->vaddr, dma_region->vaddr + dma_region->size); - transferred = msc_read_block(channel, (uint8_t) card, dma_region->paddr); + transferred = msc_read_blocks(channel, (uint8_t) card, dma_region->paddr, + block_address, block_count); printf("Transferred: %d\n", transferred); } @@ -1642,6 +1675,8 @@ new_dma_channel(dma); else if (!strcmp(token, "r") || !strcmp(token, "region")) new_dma_region(); + else if (!strcmp(token, "R") || !strcmp(token, "show")) + show_dma_region(); else if (!strcmp(token, "s") || !strcmp(token, "set")) set_dma_region(); else if (!strcmp(token, "t") || !strcmp(token, "transfer")) @@ -1725,7 +1760,7 @@ else if (!strcmp(token, "e") || !strcmp(token, "enable")) enable_msc_channel(); else if (!strcmp(token, "r") || !strcmp(token, "read")) - read_block_from_msc(); + read_blocks_from_msc(); else printf("msc channel | enable | read\n"); } diff -r 4d6501475311 -r 902a8354a7b3 pkg/landfall-examples/hw_info/jz4780.c --- a/pkg/landfall-examples/hw_info/jz4780.c Thu Feb 15 23:15:30 2024 +0100 +++ b/pkg/landfall-examples/hw_info/jz4780.c Thu Feb 15 23:18:09 2024 +0100 @@ -359,9 +359,12 @@ jz4780_msc_enable(msc_channel); } -uint32_t msc_read_block(void *msc_channel, uint8_t card, l4re_dma_space_dma_addr_t paddr) +uint32_t msc_read_blocks(void *msc_channel, uint8_t card, + l4re_dma_space_dma_addr_t paddr, + uint32_t block_address, uint32_t block_count) { - return jz4780_msc_read_block(msc_channel, card, paddr); + return jz4780_msc_read_blocks(msc_channel, card, paddr, block_address, + block_count); } diff -r 4d6501475311 -r 902a8354a7b3 pkg/landfall-examples/hw_info/x1600.c --- a/pkg/landfall-examples/hw_info/x1600.c Thu Feb 15 23:15:30 2024 +0100 +++ b/pkg/landfall-examples/hw_info/x1600.c Thu Feb 15 23:18:09 2024 +0100 @@ -348,9 +348,12 @@ return x1600_msc_enable(msc_channel); } -uint32_t msc_read_block(void *msc_channel, uint8_t card, l4re_dma_space_dma_addr_t paddr) +uint32_t msc_read_blocks(void *msc_channel, uint8_t card, + l4re_dma_space_dma_addr_t paddr, + uint32_t block_address, uint32_t block_count) { - return x1600_msc_read_block(msc_channel, card, paddr); + return x1600_msc_read_blocks(msc_channel, card, paddr, block_address, + block_count); }