# HG changeset patch # User Paul Boddie # Date 1708121485 -3600 # Node ID 18edc9c73263311ff180a612d33aa21a3b9001cf # Parent 408e9bad9e9bc845c2865b3f466bab1d5315598f Exposed the card registry and added support for inspecting partition tables. diff -r 408e9bad9e9b -r 18edc9c73263 pkg/devices/lib/msc/include/msc-common.h --- a/pkg/devices/lib/msc/include/msc-common.h Fri Feb 16 00:55:51 2024 +0100 +++ b/pkg/devices/lib/msc/include/msc-common.h Fri Feb 16 23:11:25 2024 +0100 @@ -21,53 +21,13 @@ #pragma once +#include #include #include #include -/* MMC/SD structures. */ - -struct CID -{ - uint16_t month:4, year:8, reserved:4; - uint32_t serial; - uint8_t revision; - char name[5]; - uint16_t oem; - uint8_t manufacturer; -} __attribute__((packed)); - -struct CSD -{ - uint8_t reserved0:2, format:2, temp_write_prot:1, perm_write_prot:1, copy:1, format_group:1; - uint16_t reserved1:5, write_block_partial:1, write_blocklen:4, write_time_factor:3, - reserved2:2, write_prot_group_enable:1; - uint64_t write_prot_group_size:7, erase_sector_size:7, erase_single_block_enable:1, - device_size_multiplier:3, max_write_current_max:3, max_write_current_min:3, - max_read_current_max:3, max_read_current_min:3, device_size:12, - reserved3:2, dsr_implemented:1, read_block_misalign:1, write_block_misalign:1, - read_block_partial:1, read_blocklen:4, card_command_classes:12; - uint8_t tran_speed, data_read_access_time_2, data_read_access_time_1, - reserved4:6, csd:2; -} __attribute__((packed)); - - - -/* Generic card structure. */ - -struct msc_card -{ - uint16_t rca; - uint32_t ocr; - uint8_t bus_width; - struct CID cid; - struct CSD csd; -}; - - - #ifdef __cplusplus #include @@ -153,7 +113,9 @@ void enable(); - uint32_t get_status(); + msc_card *get_cards(); + + uint8_t num_cards(); uint32_t read_blocks(uint8_t card, l4re_dma_space_dma_addr_t paddr, uint32_t block_address, uint32_t block_count); diff -r 408e9bad9e9b -r 18edc9c73263 pkg/devices/lib/msc/include/msc-jz4780.h --- a/pkg/devices/lib/msc/include/msc-jz4780.h Fri Feb 16 00:55:51 2024 +0100 +++ b/pkg/devices/lib/msc/include/msc-jz4780.h Fri Feb 16 23:11:25 2024 +0100 @@ -21,6 +21,7 @@ #pragma once +#include #include #include #include @@ -30,7 +31,6 @@ #ifdef __cplusplus #include -#include // MMC/SD controller channel. @@ -79,7 +79,9 @@ void *jz4780_msc_get_channel(void *msc, uint8_t channel, l4_cap_idx_t irq, void *dma); -uint32_t jz4780_msc_get_status(void *msc_channel); +struct msc_card *jz4780_msc_get_cards(void *msc_channel); + +uint8_t jz4780_msc_num_cards(void *msc_channel); void jz4780_msc_enable(void *msc_channel); diff -r 408e9bad9e9b -r 18edc9c73263 pkg/devices/lib/msc/include/msc-x1600.h --- a/pkg/devices/lib/msc/include/msc-x1600.h Fri Feb 16 00:55:51 2024 +0100 +++ b/pkg/devices/lib/msc/include/msc-x1600.h Fri Feb 16 23:11:25 2024 +0100 @@ -21,6 +21,7 @@ #pragma once +#include #include #include #include @@ -30,7 +31,6 @@ #ifdef __cplusplus #include -#include // MMC/SD controller channel. @@ -77,7 +77,9 @@ void *x1600_msc_get_channel(void *msc, uint8_t channel, l4_cap_idx_t irq, void *dma); -uint32_t x1600_msc_get_status(void *msc_channel); +struct msc_card *x1600_msc_get_cards(void *msc_channel); + +uint8_t x1600_msc_num_cards(void *msc_channel); void x1600_msc_enable(void *msc_channel); diff -r 408e9bad9e9b -r 18edc9c73263 pkg/devices/lib/msc/include/msc.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/devices/lib/msc/include/msc.h Fri Feb 16 23:11:25 2024 +0100 @@ -0,0 +1,88 @@ +/* + * MSC (MMC/SD controller) structures. + * + * Copyright (C) 2024 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include + + + +/* MMC/SD structures. */ + +struct CID +{ + uint16_t month:4, year:8, reserved:4; + uint32_t serial; + uint8_t revision; + char name[5]; + uint16_t oem; + uint8_t manufacturer; +} __attribute__((packed)); + +struct CSD +{ + uint8_t reserved0:2, + format:2, + temp_write_prot:1, + perm_write_prot:1, + copy:1, + format_group:1; + uint16_t reserved1:5, + write_block_partial:1, + write_blocklen:4, + write_time_factor:3, + reserved2:2, + write_prot_group_enable:1; + uint64_t write_prot_group_size:7, + erase_sector_size:7, + erase_single_block_enable:1, + device_size_multiplier:3, + max_write_current_max:3, + max_write_current_min:3, + max_read_current_max:3, + max_read_current_min:3, + device_size:12, + reserved3:2, + dsr_implemented:1, + read_block_misalign:1, + write_block_misalign:1, + read_block_partial:1, + read_blocklen:4, + card_command_classes:12; + uint8_t tran_speed, + data_read_access_time_2, + data_read_access_time_1, + reserved4:6, + csd:2; +} __attribute__((packed)); + + + +/* Generic card structure. */ + +struct msc_card +{ + uint16_t rca; + uint32_t ocr; + uint8_t bus_width; + struct CID cid; + struct CSD csd; +}; diff -r 408e9bad9e9b -r 18edc9c73263 pkg/devices/lib/msc/src/common.cc --- a/pkg/devices/lib/msc/src/common.cc Fri Feb 16 00:55:51 2024 +0100 +++ b/pkg/devices/lib/msc/src/common.cc Fri Feb 16 23:11:25 2024 +0100 @@ -814,12 +814,6 @@ while (_regs[Msc_status] & Status_clock_enabled); } -uint32_t -Msc_channel::get_status() -{ - return _regs[Msc_status]; -} - // Send an application-specific command. bool @@ -946,45 +940,6 @@ -// Enable the controller and identify cards. - -void -Msc_channel::enable() -{ - // NOTE: X1600 and other recent SoCs only. - - _regs[Msc_low_power_mode] = _regs[Msc_low_power_mode] & ~Low_power_mode_enable; - - stop_clock(); - reset(); - - // Slow the clock for initialisation. - // NOTE: Should use the CPM module to deduce the appropriate divider value. - - set_field(Msc_clock_rate, Clock_rate_field_mask, Clock_rate_field_shift, 7); - - send_command(Command_go_idle_state, 0); - - if (check_sd()) - { - init_sdio(); - init_sdmem(); - } - - init_mmc(); - identify_cards(); - query_cards(); - - // Restore the clock. - // NOTE: Should use the CPM module to deduce the appropriate divider value. - - set_field(Msc_clock_rate, Clock_rate_field_mask, Clock_rate_field_shift, 1); - - // Initially, no card is selected. - - _card = -1; -} - // Check the voltage range of the SD card, potentially establishing that it is // a high capacity card. Return false if the voltage range is incompatible. @@ -1173,37 +1128,39 @@ _cards[card].csd = r2.payload.csd; + struct CSD *csd = &_cards[card].csd; + printf("card: %d\n", card); - printf("csd: %d\n", r2.payload.csd.csd); - printf("copy: %s\n", r2.payload.csd.copy ? "copied" : "original"); - printf("card command classes: %03x\n", r2.payload.csd.card_command_classes); - printf("device (size multiplier): %d %d\n", r2.payload.csd.device_size + 1, - 1 << (r2.payload.csd.device_size_multiplier + 2)); - printf("device size: %d\n", (1 << r2.payload.csd.read_blocklen) * - (r2.payload.csd.device_size + 1) * - (1 << (r2.payload.csd.device_size_multiplier + 2))); - printf("transfer speed: %d MHz\n", r2.payload.csd.tran_speed == 0x32 ? 25 : 50); - printf("format group: %d %d\n", r2.payload.csd.format, r2.payload.csd.format_group); - printf("write time factor: %d\n", 1 << r2.payload.csd.write_time_factor); - printf("write protect (temp perm): %s %s\n", r2.payload.csd.temp_write_prot ? "yes" : "no", - r2.payload.csd.perm_write_prot ? "yes" : "no"); - printf("write protect group (enable size): %s %d\n", r2.payload.csd.write_prot_group_enable ? "yes" : "no", - r2.payload.csd.write_prot_group_size + 1); - printf("write block (partial length): %s %d\n", r2.payload.csd.write_block_partial ? "yes" : "no", - 1 << r2.payload.csd.write_blocklen); - printf("read block (partial length): %s %d\n", r2.payload.csd.read_block_partial ? "yes" : "no", - 1 << r2.payload.csd.read_blocklen); - printf("erase: sector single: %d %s\n", r2.payload.csd.erase_sector_size + 1, - r2.payload.csd.erase_single_block_enable ? "yes" : "no"); - printf("misalign: read write: %s %s\n", r2.payload.csd.read_block_misalign ? "yes" : "no", - r2.payload.csd.write_block_misalign ? "yes" : "no"); - printf("max read current (min max): %d %d\n", r2.payload.csd.max_read_current_min, - r2.payload.csd.max_read_current_max); - printf("max write current (min max): %d %d\n", r2.payload.csd.max_write_current_min, - r2.payload.csd.max_write_current_max); - printf("read access time (1 2): %d %d\n", r2.payload.csd.data_read_access_time_1, - r2.payload.csd.data_read_access_time_2); - printf("DSR: %s\n", r2.payload.csd.dsr_implemented ? "yes" : "no"); + printf("csd: %d\n", csd->csd); + printf("copy: %s\n", csd->copy ? "copied" : "original"); + printf("card command classes: %03x\n", csd->card_command_classes); + printf("device (size multiplier): %d %d\n", csd->device_size + 1, + 1 << (csd->device_size_multiplier + 2)); + printf("device size: %d\n", (1 << csd->read_blocklen) * + (csd->device_size + 1) * + (1 << (csd->device_size_multiplier + 2))); + printf("transfer speed: %d MHz\n", csd->tran_speed == 0x32 ? 25 : 50); + printf("format group: %d %d\n", csd->format, r2.payload.csd.format_group); + printf("write time factor: %d\n", 1 << csd->write_time_factor); + printf("write protect (temp perm): %s %s\n", csd->temp_write_prot ? "yes" : "no", + csd->perm_write_prot ? "yes" : "no"); + printf("write protect group (enable size): %s %d\n", csd->write_prot_group_enable ? "yes" : "no", + csd->write_prot_group_size + 1); + printf("write block (partial length): %s %d\n", csd->write_block_partial ? "yes" : "no", + 1 << csd->write_blocklen); + printf("read block (partial length): %s %d\n", csd->read_block_partial ? "yes" : "no", + 1 << csd->read_blocklen); + printf("erase: sector single: %d %s\n", csd->erase_sector_size + 1, + csd->erase_single_block_enable ? "yes" : "no"); + printf("misalign: read write: %s %s\n", csd->read_block_misalign ? "yes" : "no", + csd->write_block_misalign ? "yes" : "no"); + printf("max read current (min max): %d %d\n", csd->max_read_current_min, + csd->max_read_current_max); + printf("max write current (min max): %d %d\n", csd->max_write_current_min, + csd->max_write_current_max); + printf("read access time (1 2): %d %d\n", csd->data_read_access_time_1, + csd->data_read_access_time_2); + printf("DSR: %s\n", csd->dsr_implemented ? "yes" : "no"); // Query the OCR again now that we can associate it with a specific card. @@ -1218,6 +1175,61 @@ +// Enable the controller and identify cards. + +void +Msc_channel::enable() +{ + // NOTE: X1600 and other recent SoCs only. + + _regs[Msc_low_power_mode] = _regs[Msc_low_power_mode] & ~Low_power_mode_enable; + + stop_clock(); + reset(); + + // Slow the clock for initialisation. + // NOTE: Should use the CPM module to deduce the appropriate divider value. + + set_field(Msc_clock_rate, Clock_rate_field_mask, Clock_rate_field_shift, 7); + + send_command(Command_go_idle_state, 0); + + if (check_sd()) + { + init_sdio(); + init_sdmem(); + } + + init_mmc(); + identify_cards(); + query_cards(); + + // Restore the clock. + // NOTE: Should use the CPM module to deduce the appropriate divider value. + + set_field(Msc_clock_rate, Clock_rate_field_mask, Clock_rate_field_shift, 1); + + // Initially, no card is selected. + + _card = -1; +} + +// Obtain the card details. + +struct msc_card * +Msc_channel::get_cards() +{ + return _cards; +} + +// Return the number of active cards. + +uint8_t +Msc_channel::num_cards() +{ + return _num_cards; +} + // Receive data from the selected card. uint32_t @@ -1314,10 +1326,17 @@ _regs[Msc_block_count] = block_count; _regs[Msc_block_length] = block_size; - // NOTE: Where CCS = 0, byte addressing is used. Otherwise, block addressing is used. + // Where CCS = 0, byte addressing is used. Otherwise, block addressing is used. + + uint32_t address; + + if (_cards[card].ocr & Ocr_high_capacity_storage) + address = block_address; + else + address = block_address * block_size; if (!send_command(block_count == 1 ? Command_read_single_block - : Command_read_multiple_block, block_address)) + : Command_read_multiple_block, address)) return 0; read_response((uint16_t *) &r1, Response_size_R1); diff -r 408e9bad9e9b -r 18edc9c73263 pkg/devices/lib/msc/src/jz4780.cc --- a/pkg/devices/lib/msc/src/jz4780.cc Fri Feb 16 00:55:51 2024 +0100 +++ b/pkg/devices/lib/msc/src/jz4780.cc Fri Feb 16 23:11:25 2024 +0100 @@ -116,9 +116,14 @@ static_cast(dma)); } -uint32_t jz4780_msc_get_status(void *msc_channel) +struct msc_card *jz4780_msc_get_cards(void *msc_channel) { - return static_cast(msc_channel)->get_status(); + return static_cast(msc_channel)->get_cards(); +} + +uint8_t jz4780_msc_num_cards(void *msc_channel) +{ + return static_cast(msc_channel)->num_cards(); } void jz4780_msc_enable(void *msc_channel) diff -r 408e9bad9e9b -r 18edc9c73263 pkg/devices/lib/msc/src/x1600.cc --- a/pkg/devices/lib/msc/src/x1600.cc Fri Feb 16 00:55:51 2024 +0100 +++ b/pkg/devices/lib/msc/src/x1600.cc Fri Feb 16 23:11:25 2024 +0100 @@ -116,9 +116,14 @@ static_cast(dma)); } -uint32_t x1600_msc_get_status(void *msc_channel) +struct msc_card *x1600_msc_get_cards(void *msc_channel) { - return static_cast(msc_channel)->get_status(); + return static_cast(msc_channel)->get_cards(); +} + +uint8_t x1600_msc_num_cards(void *msc_channel) +{ + return static_cast(msc_channel)->num_cards(); } void x1600_msc_enable(void *msc_channel) diff -r 408e9bad9e9b -r 18edc9c73263 pkg/devices/util/include/boot.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/devices/util/include/boot.h Fri Feb 16 23:11:25 2024 +0100 @@ -0,0 +1,47 @@ +/* + * Boot-related utilities. + * + * Copyright (C) 2024 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include +#include + +struct chs_address +{ + uint8_t head; + uint16_t sector:6, cylinder:10; +} __attribute__((packed)); + +struct partition_table_entry +{ + uint8_t status; + struct chs_address chs_first_sector; + uint8_t partition_type; + struct chs_address chs_last_sector; + uint32_t lba_first_sector; + uint32_t num_sectors; +} __attribute__((packed)); + +EXTERN_C_BEGIN + +struct partition_table_entry *get_partition_table(uint8_t *data); + +EXTERN_C_END diff -r 408e9bad9e9b -r 18edc9c73263 pkg/devices/util/src/Makefile --- a/pkg/devices/util/src/Makefile Fri Feb 16 00:55:51 2024 +0100 +++ b/pkg/devices/util/src/Makefile Fri Feb 16 23:11:25 2024 +0100 @@ -4,7 +4,7 @@ TARGET = libdevice_util.o.a libdevice_util.o.so PC_FILENAME := libdevice-util -SRC_CC := byteorder.cc dataspace.cc dl.cc dma.cc event-loop.cc memory.cc +SRC_CC := boot.cc byteorder.cc dataspace.cc dl.cc dma.cc event-loop.cc memory.cc PRIVATE_INCDIR += $(PKGDIR)/util/include diff -r 408e9bad9e9b -r 18edc9c73263 pkg/devices/util/src/boot.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/devices/util/src/boot.cc Fri Feb 16 23:11:25 2024 +0100 @@ -0,0 +1,37 @@ +/* + * Boot-related utilities. + * + * Copyright (C) 2024 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include + +#include "boot.h" + + + +// Return a pointer to any partition table in the provided data or NULL if the +// data appears not to contain such a table. + +struct partition_table_entry *get_partition_table(uint8_t *data) +{ + if ((data[0x1fe] != 0x55) || (data[0x1ff] != 0xaa)) + return NULL; + + return (struct partition_table_entry *) &data[0x1be]; +} diff -r 408e9bad9e9b -r 18edc9c73263 pkg/landfall-examples/hw_info/common.h --- a/pkg/landfall-examples/hw_info/common.h Fri Feb 16 00:55:51 2024 +0100 +++ b/pkg/landfall-examples/hw_info/common.h Fri Feb 16 23:11:25 2024 +0100 @@ -172,7 +172,9 @@ void *msc_get_channel(void *msc, uint8_t channel, l4_cap_idx_t irq, void *dma); -uint32_t msc_get_status(void *msc_channel); +struct msc_card *msc_get_cards(void *msc_channel); + +uint8_t msc_num_cards(void *msc_channel); void msc_enable(void *msc_channel); diff -r 408e9bad9e9b -r 18edc9c73263 pkg/landfall-examples/hw_info/hw_info.c --- a/pkg/landfall-examples/hw_info/hw_info.c Fri Feb 16 00:55:51 2024 +0100 +++ b/pkg/landfall-examples/hw_info/hw_info.c Fri Feb 16 23:11:25 2024 +0100 @@ -22,8 +22,10 @@ #include "common.h" #include "defs.h" +#include #include #include +#include #include #include @@ -1136,13 +1138,94 @@ /* MSC operations. */ +static void list_msc_cards(void) +{ + void *channel = get_channel(num_msc_channels, msc_channels, NULL); + struct msc_card *cards; + struct CSD *csd; + uint8_t num; + + if (channel == NULL) + return; + + cards = msc_get_cards(channel); + + printf("Card RCA Bits Size\n"); + printf("---- ---- ---- --------------\n"); + + for (num = 0; num < msc_num_cards(channel); num++) + { + csd = &cards[num].csd; + + printf("%d %04x %d %d\n", num, cards[num].rca, cards[num].bus_width, + (1 << csd->read_blocklen) * + (csd->device_size + 1) * + (1 << (csd->device_size_multiplier + 2))); + } +} + +static void list_msc_card_partitions(void) +{ + void *channel = get_channel(num_msc_channels, msc_channels, NULL); + struct dma_region *dma_region; + struct partition_table_entry *entry; + uint32_t card, transferred; + uint8_t num; + + if (channel == NULL) + return; + + dma_region = _get_dma_region(); + + if (dma_region == NULL) + return; + + if (!read_number("Card", &card)) + return; + + l4_cache_inv_data(dma_region->vaddr, dma_region->vaddr + dma_region->size); + + transferred = msc_read_blocks(channel, (uint8_t) card, dma_region->paddr, 0, 1); + + if (!transferred) + { + printf("Could not read partitions.\n"); + return; + } + + entry = get_partition_table((uint8_t *) dma_region->vaddr); + + if (entry == NULL) + { + printf("Invalid partition table.\n"); + return; + } + + printf("Partition Status Type Start End Address Sectors\n"); + printf("--------- ------ ---- --------- --------- -------- --------\n"); + + for (num = 0; num < 4; num++, entry++) + { + printf("%d %02x %02x %03x %02x %02x %03x %02x %02x %08x %08x\n", + num, entry->status, entry->partition_type, + entry->chs_first_sector.cylinder, + entry->chs_first_sector.head, + entry->chs_first_sector.sector, + entry->chs_last_sector.cylinder, + entry->chs_last_sector.head, + entry->chs_last_sector.sector, + entry->lba_first_sector, + entry->num_sectors); + } +} + static void list_msc_channels(void) { unsigned int num; void *channel; - printf("Channel Status\n"); - printf("------- --------\n"); + printf("Channel Cards\n"); + printf("------- -----\n"); for (num = 0; num < num_msc_channels; num++) { @@ -1153,7 +1236,7 @@ if (channel == NULL) printf("inactive\n"); else - printf("%08x\n", msc_get_status(channel)); + printf("%d\n", msc_num_cards(channel)); } } @@ -1193,7 +1276,7 @@ static void read_blocks_from_msc(void) { void *channel = get_channel(num_msc_channels, msc_channels, NULL); - struct dma_region *dma_region = NULL; + struct dma_region *dma_region; uint32_t card, transferred, block_address, block_count; if (channel == NULL) @@ -1755,14 +1838,18 @@ { if (!strcmp(token, "l") || !strcmp(token, "list")) list_msc_channels(); + else if (!strcmp(token, "C") || !strcmp(token, "cards")) + list_msc_cards(); else if (!strcmp(token, "c") || !strcmp(token, "channel")) new_msc_channel(msc); else if (!strcmp(token, "e") || !strcmp(token, "enable")) enable_msc_channel(); + else if (!strcmp(token, "p") || !strcmp(token, "partitions")) + list_msc_card_partitions(); else if (!strcmp(token, "r") || !strcmp(token, "read")) read_blocks_from_msc(); else - printf("msc channel | enable | read\n"); + printf("msc cards | channel | enable | partitions | read\n"); } else list_msc_channels(); diff -r 408e9bad9e9b -r 18edc9c73263 pkg/landfall-examples/hw_info/jz4780.c --- a/pkg/landfall-examples/hw_info/jz4780.c Fri Feb 16 00:55:51 2024 +0100 +++ b/pkg/landfall-examples/hw_info/jz4780.c Fri Feb 16 23:11:25 2024 +0100 @@ -349,9 +349,14 @@ return jz4780_msc_get_channel(msc, channel, irq, dma); } -uint32_t msc_get_status(void *msc_channel) +struct msc_card *msc_get_cards(void *msc_channel) { - return jz4780_msc_get_status(msc_channel); + return jz4780_msc_get_cards(msc_channel); +} + +uint8_t msc_num_cards(void *msc_channel) +{ + return jz4780_msc_num_cards(msc_channel); } void msc_enable(void *msc_channel) diff -r 408e9bad9e9b -r 18edc9c73263 pkg/landfall-examples/hw_info/x1600.c --- a/pkg/landfall-examples/hw_info/x1600.c Fri Feb 16 00:55:51 2024 +0100 +++ b/pkg/landfall-examples/hw_info/x1600.c Fri Feb 16 23:11:25 2024 +0100 @@ -338,9 +338,14 @@ return x1600_msc_get_channel(msc, channel, irq, dma); } -uint32_t msc_get_status(void *msc_channel) +struct msc_card *msc_get_cards(void *msc_channel) { - return x1600_msc_get_status(msc_channel); + return x1600_msc_get_cards(msc_channel); +} + +uint8_t msc_num_cards(void *msc_channel) +{ + return x1600_msc_num_cards(msc_channel); } void msc_enable(void *msc_channel)