1.1 --- a/pkg/devices/lib/msc/include/msc-common.h Fri Feb 16 00:55:51 2024 +0100 1.2 +++ b/pkg/devices/lib/msc/include/msc-common.h Fri Feb 16 23:11:25 2024 +0100 1.3 @@ -21,53 +21,13 @@ 1.4 1.5 #pragma once 1.6 1.7 +#include <l4/devices/msc.h> 1.8 #include <l4/re/c/dma_space.h> 1.9 #include <l4/sys/types.h> 1.10 #include <stdint.h> 1.11 1.12 1.13 1.14 -/* MMC/SD structures. */ 1.15 - 1.16 -struct CID 1.17 -{ 1.18 - uint16_t month:4, year:8, reserved:4; 1.19 - uint32_t serial; 1.20 - uint8_t revision; 1.21 - char name[5]; 1.22 - uint16_t oem; 1.23 - uint8_t manufacturer; 1.24 -} __attribute__((packed)); 1.25 - 1.26 -struct CSD 1.27 -{ 1.28 - uint8_t reserved0:2, format:2, temp_write_prot:1, perm_write_prot:1, copy:1, format_group:1; 1.29 - uint16_t reserved1:5, write_block_partial:1, write_blocklen:4, write_time_factor:3, 1.30 - reserved2:2, write_prot_group_enable:1; 1.31 - uint64_t write_prot_group_size:7, erase_sector_size:7, erase_single_block_enable:1, 1.32 - device_size_multiplier:3, max_write_current_max:3, max_write_current_min:3, 1.33 - max_read_current_max:3, max_read_current_min:3, device_size:12, 1.34 - reserved3:2, dsr_implemented:1, read_block_misalign:1, write_block_misalign:1, 1.35 - read_block_partial:1, read_blocklen:4, card_command_classes:12; 1.36 - uint8_t tran_speed, data_read_access_time_2, data_read_access_time_1, 1.37 - reserved4:6, csd:2; 1.38 -} __attribute__((packed)); 1.39 - 1.40 - 1.41 - 1.42 -/* Generic card structure. */ 1.43 - 1.44 -struct msc_card 1.45 -{ 1.46 - uint16_t rca; 1.47 - uint32_t ocr; 1.48 - uint8_t bus_width; 1.49 - struct CID cid; 1.50 - struct CSD csd; 1.51 -}; 1.52 - 1.53 - 1.54 - 1.55 #ifdef __cplusplus 1.56 1.57 #include <l4/devices/hw_mmio_register_block.h> 1.58 @@ -153,7 +113,9 @@ 1.59 1.60 void enable(); 1.61 1.62 - uint32_t get_status(); 1.63 + msc_card *get_cards(); 1.64 + 1.65 + uint8_t num_cards(); 1.66 1.67 uint32_t read_blocks(uint8_t card, l4re_dma_space_dma_addr_t paddr, 1.68 uint32_t block_address, uint32_t block_count);
2.1 --- a/pkg/devices/lib/msc/include/msc-jz4780.h Fri Feb 16 00:55:51 2024 +0100 2.2 +++ b/pkg/devices/lib/msc/include/msc-jz4780.h Fri Feb 16 23:11:25 2024 +0100 2.3 @@ -21,6 +21,7 @@ 2.4 2.5 #pragma once 2.6 2.7 +#include <l4/devices/msc-common.h> 2.8 #include <l4/re/c/dma_space.h> 2.9 #include <l4/sys/types.h> 2.10 #include <stdint.h> 2.11 @@ -30,7 +31,6 @@ 2.12 #ifdef __cplusplus 2.13 2.14 #include <l4/devices/dma-jz4780.h> 2.15 -#include <l4/devices/msc-common.h> 2.16 2.17 // MMC/SD controller channel. 2.18 2.19 @@ -79,7 +79,9 @@ 2.20 void *jz4780_msc_get_channel(void *msc, uint8_t channel, l4_cap_idx_t irq, 2.21 void *dma); 2.22 2.23 -uint32_t jz4780_msc_get_status(void *msc_channel); 2.24 +struct msc_card *jz4780_msc_get_cards(void *msc_channel); 2.25 + 2.26 +uint8_t jz4780_msc_num_cards(void *msc_channel); 2.27 2.28 void jz4780_msc_enable(void *msc_channel); 2.29
3.1 --- a/pkg/devices/lib/msc/include/msc-x1600.h Fri Feb 16 00:55:51 2024 +0100 3.2 +++ b/pkg/devices/lib/msc/include/msc-x1600.h Fri Feb 16 23:11:25 2024 +0100 3.3 @@ -21,6 +21,7 @@ 3.4 3.5 #pragma once 3.6 3.7 +#include <l4/devices/msc-common.h> 3.8 #include <l4/re/c/dma_space.h> 3.9 #include <l4/sys/types.h> 3.10 #include <stdint.h> 3.11 @@ -30,7 +31,6 @@ 3.12 #ifdef __cplusplus 3.13 3.14 #include <l4/devices/dma-x1600.h> 3.15 -#include <l4/devices/msc-common.h> 3.16 3.17 // MMC/SD controller channel. 3.18 3.19 @@ -77,7 +77,9 @@ 3.20 void *x1600_msc_get_channel(void *msc, uint8_t channel, l4_cap_idx_t irq, 3.21 void *dma); 3.22 3.23 -uint32_t x1600_msc_get_status(void *msc_channel); 3.24 +struct msc_card *x1600_msc_get_cards(void *msc_channel); 3.25 + 3.26 +uint8_t x1600_msc_num_cards(void *msc_channel); 3.27 3.28 void x1600_msc_enable(void *msc_channel); 3.29
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/pkg/devices/lib/msc/include/msc.h Fri Feb 16 23:11:25 2024 +0100 4.3 @@ -0,0 +1,88 @@ 4.4 +/* 4.5 + * MSC (MMC/SD controller) structures. 4.6 + * 4.7 + * Copyright (C) 2024 Paul Boddie <paul@boddie.org.uk> 4.8 + * 4.9 + * This program is free software; you can redistribute it and/or 4.10 + * modify it under the terms of the GNU General Public License as 4.11 + * published by the Free Software Foundation; either version 2 of 4.12 + * the License, or (at your option) any later version. 4.13 + * 4.14 + * This program is distributed in the hope that it will be useful, 4.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 4.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 4.17 + * GNU General Public License for more details. 4.18 + * 4.19 + * You should have received a copy of the GNU General Public License 4.20 + * along with this program; if not, write to the Free Software 4.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 4.22 + * Boston, MA 02110-1301, USA 4.23 + */ 4.24 + 4.25 +#pragma once 4.26 + 4.27 +#include <stdint.h> 4.28 + 4.29 + 4.30 + 4.31 +/* MMC/SD structures. */ 4.32 + 4.33 +struct CID 4.34 +{ 4.35 + uint16_t month:4, year:8, reserved:4; 4.36 + uint32_t serial; 4.37 + uint8_t revision; 4.38 + char name[5]; 4.39 + uint16_t oem; 4.40 + uint8_t manufacturer; 4.41 +} __attribute__((packed)); 4.42 + 4.43 +struct CSD 4.44 +{ 4.45 + uint8_t reserved0:2, 4.46 + format:2, 4.47 + temp_write_prot:1, 4.48 + perm_write_prot:1, 4.49 + copy:1, 4.50 + format_group:1; 4.51 + uint16_t reserved1:5, 4.52 + write_block_partial:1, 4.53 + write_blocklen:4, 4.54 + write_time_factor:3, 4.55 + reserved2:2, 4.56 + write_prot_group_enable:1; 4.57 + uint64_t write_prot_group_size:7, 4.58 + erase_sector_size:7, 4.59 + erase_single_block_enable:1, 4.60 + device_size_multiplier:3, 4.61 + max_write_current_max:3, 4.62 + max_write_current_min:3, 4.63 + max_read_current_max:3, 4.64 + max_read_current_min:3, 4.65 + device_size:12, 4.66 + reserved3:2, 4.67 + dsr_implemented:1, 4.68 + read_block_misalign:1, 4.69 + write_block_misalign:1, 4.70 + read_block_partial:1, 4.71 + read_blocklen:4, 4.72 + card_command_classes:12; 4.73 + uint8_t tran_speed, 4.74 + data_read_access_time_2, 4.75 + data_read_access_time_1, 4.76 + reserved4:6, 4.77 + csd:2; 4.78 +} __attribute__((packed)); 4.79 + 4.80 + 4.81 + 4.82 +/* Generic card structure. */ 4.83 + 4.84 +struct msc_card 4.85 +{ 4.86 + uint16_t rca; 4.87 + uint32_t ocr; 4.88 + uint8_t bus_width; 4.89 + struct CID cid; 4.90 + struct CSD csd; 4.91 +};
5.1 --- a/pkg/devices/lib/msc/src/common.cc Fri Feb 16 00:55:51 2024 +0100 5.2 +++ b/pkg/devices/lib/msc/src/common.cc Fri Feb 16 23:11:25 2024 +0100 5.3 @@ -814,12 +814,6 @@ 5.4 while (_regs[Msc_status] & Status_clock_enabled); 5.5 } 5.6 5.7 -uint32_t 5.8 -Msc_channel::get_status() 5.9 -{ 5.10 - return _regs[Msc_status]; 5.11 -} 5.12 - 5.13 // Send an application-specific command. 5.14 5.15 bool 5.16 @@ -946,45 +940,6 @@ 5.17 5.18 5.19 5.20 -// Enable the controller and identify cards. 5.21 - 5.22 -void 5.23 -Msc_channel::enable() 5.24 -{ 5.25 - // NOTE: X1600 and other recent SoCs only. 5.26 - 5.27 - _regs[Msc_low_power_mode] = _regs[Msc_low_power_mode] & ~Low_power_mode_enable; 5.28 - 5.29 - stop_clock(); 5.30 - reset(); 5.31 - 5.32 - // Slow the clock for initialisation. 5.33 - // NOTE: Should use the CPM module to deduce the appropriate divider value. 5.34 - 5.35 - set_field(Msc_clock_rate, Clock_rate_field_mask, Clock_rate_field_shift, 7); 5.36 - 5.37 - send_command(Command_go_idle_state, 0); 5.38 - 5.39 - if (check_sd()) 5.40 - { 5.41 - init_sdio(); 5.42 - init_sdmem(); 5.43 - } 5.44 - 5.45 - init_mmc(); 5.46 - identify_cards(); 5.47 - query_cards(); 5.48 - 5.49 - // Restore the clock. 5.50 - // NOTE: Should use the CPM module to deduce the appropriate divider value. 5.51 - 5.52 - set_field(Msc_clock_rate, Clock_rate_field_mask, Clock_rate_field_shift, 1); 5.53 - 5.54 - // Initially, no card is selected. 5.55 - 5.56 - _card = -1; 5.57 -} 5.58 - 5.59 // Check the voltage range of the SD card, potentially establishing that it is 5.60 // a high capacity card. Return false if the voltage range is incompatible. 5.61 5.62 @@ -1173,37 +1128,39 @@ 5.63 5.64 _cards[card].csd = r2.payload.csd; 5.65 5.66 + struct CSD *csd = &_cards[card].csd; 5.67 + 5.68 printf("card: %d\n", card); 5.69 - printf("csd: %d\n", r2.payload.csd.csd); 5.70 - printf("copy: %s\n", r2.payload.csd.copy ? "copied" : "original"); 5.71 - printf("card command classes: %03x\n", r2.payload.csd.card_command_classes); 5.72 - printf("device (size multiplier): %d %d\n", r2.payload.csd.device_size + 1, 5.73 - 1 << (r2.payload.csd.device_size_multiplier + 2)); 5.74 - printf("device size: %d\n", (1 << r2.payload.csd.read_blocklen) * 5.75 - (r2.payload.csd.device_size + 1) * 5.76 - (1 << (r2.payload.csd.device_size_multiplier + 2))); 5.77 - printf("transfer speed: %d MHz\n", r2.payload.csd.tran_speed == 0x32 ? 25 : 50); 5.78 - printf("format group: %d %d\n", r2.payload.csd.format, r2.payload.csd.format_group); 5.79 - printf("write time factor: %d\n", 1 << r2.payload.csd.write_time_factor); 5.80 - printf("write protect (temp perm): %s %s\n", r2.payload.csd.temp_write_prot ? "yes" : "no", 5.81 - r2.payload.csd.perm_write_prot ? "yes" : "no"); 5.82 - printf("write protect group (enable size): %s %d\n", r2.payload.csd.write_prot_group_enable ? "yes" : "no", 5.83 - r2.payload.csd.write_prot_group_size + 1); 5.84 - printf("write block (partial length): %s %d\n", r2.payload.csd.write_block_partial ? "yes" : "no", 5.85 - 1 << r2.payload.csd.write_blocklen); 5.86 - printf("read block (partial length): %s %d\n", r2.payload.csd.read_block_partial ? "yes" : "no", 5.87 - 1 << r2.payload.csd.read_blocklen); 5.88 - printf("erase: sector single: %d %s\n", r2.payload.csd.erase_sector_size + 1, 5.89 - r2.payload.csd.erase_single_block_enable ? "yes" : "no"); 5.90 - printf("misalign: read write: %s %s\n", r2.payload.csd.read_block_misalign ? "yes" : "no", 5.91 - r2.payload.csd.write_block_misalign ? "yes" : "no"); 5.92 - printf("max read current (min max): %d %d\n", r2.payload.csd.max_read_current_min, 5.93 - r2.payload.csd.max_read_current_max); 5.94 - printf("max write current (min max): %d %d\n", r2.payload.csd.max_write_current_min, 5.95 - r2.payload.csd.max_write_current_max); 5.96 - printf("read access time (1 2): %d %d\n", r2.payload.csd.data_read_access_time_1, 5.97 - r2.payload.csd.data_read_access_time_2); 5.98 - printf("DSR: %s\n", r2.payload.csd.dsr_implemented ? "yes" : "no"); 5.99 + printf("csd: %d\n", csd->csd); 5.100 + printf("copy: %s\n", csd->copy ? "copied" : "original"); 5.101 + printf("card command classes: %03x\n", csd->card_command_classes); 5.102 + printf("device (size multiplier): %d %d\n", csd->device_size + 1, 5.103 + 1 << (csd->device_size_multiplier + 2)); 5.104 + printf("device size: %d\n", (1 << csd->read_blocklen) * 5.105 + (csd->device_size + 1) * 5.106 + (1 << (csd->device_size_multiplier + 2))); 5.107 + printf("transfer speed: %d MHz\n", csd->tran_speed == 0x32 ? 25 : 50); 5.108 + printf("format group: %d %d\n", csd->format, r2.payload.csd.format_group); 5.109 + printf("write time factor: %d\n", 1 << csd->write_time_factor); 5.110 + printf("write protect (temp perm): %s %s\n", csd->temp_write_prot ? "yes" : "no", 5.111 + csd->perm_write_prot ? "yes" : "no"); 5.112 + printf("write protect group (enable size): %s %d\n", csd->write_prot_group_enable ? "yes" : "no", 5.113 + csd->write_prot_group_size + 1); 5.114 + printf("write block (partial length): %s %d\n", csd->write_block_partial ? "yes" : "no", 5.115 + 1 << csd->write_blocklen); 5.116 + printf("read block (partial length): %s %d\n", csd->read_block_partial ? "yes" : "no", 5.117 + 1 << csd->read_blocklen); 5.118 + printf("erase: sector single: %d %s\n", csd->erase_sector_size + 1, 5.119 + csd->erase_single_block_enable ? "yes" : "no"); 5.120 + printf("misalign: read write: %s %s\n", csd->read_block_misalign ? "yes" : "no", 5.121 + csd->write_block_misalign ? "yes" : "no"); 5.122 + printf("max read current (min max): %d %d\n", csd->max_read_current_min, 5.123 + csd->max_read_current_max); 5.124 + printf("max write current (min max): %d %d\n", csd->max_write_current_min, 5.125 + csd->max_write_current_max); 5.126 + printf("read access time (1 2): %d %d\n", csd->data_read_access_time_1, 5.127 + csd->data_read_access_time_2); 5.128 + printf("DSR: %s\n", csd->dsr_implemented ? "yes" : "no"); 5.129 5.130 // Query the OCR again now that we can associate it with a specific card. 5.131 5.132 @@ -1218,6 +1175,61 @@ 5.133 5.134 5.135 5.136 +// Enable the controller and identify cards. 5.137 + 5.138 +void 5.139 +Msc_channel::enable() 5.140 +{ 5.141 + // NOTE: X1600 and other recent SoCs only. 5.142 + 5.143 + _regs[Msc_low_power_mode] = _regs[Msc_low_power_mode] & ~Low_power_mode_enable; 5.144 + 5.145 + stop_clock(); 5.146 + reset(); 5.147 + 5.148 + // Slow the clock for initialisation. 5.149 + // NOTE: Should use the CPM module to deduce the appropriate divider value. 5.150 + 5.151 + set_field(Msc_clock_rate, Clock_rate_field_mask, Clock_rate_field_shift, 7); 5.152 + 5.153 + send_command(Command_go_idle_state, 0); 5.154 + 5.155 + if (check_sd()) 5.156 + { 5.157 + init_sdio(); 5.158 + init_sdmem(); 5.159 + } 5.160 + 5.161 + init_mmc(); 5.162 + identify_cards(); 5.163 + query_cards(); 5.164 + 5.165 + // Restore the clock. 5.166 + // NOTE: Should use the CPM module to deduce the appropriate divider value. 5.167 + 5.168 + set_field(Msc_clock_rate, Clock_rate_field_mask, Clock_rate_field_shift, 1); 5.169 + 5.170 + // Initially, no card is selected. 5.171 + 5.172 + _card = -1; 5.173 +} 5.174 + 5.175 +// Obtain the card details. 5.176 + 5.177 +struct msc_card * 5.178 +Msc_channel::get_cards() 5.179 +{ 5.180 + return _cards; 5.181 +} 5.182 + 5.183 +// Return the number of active cards. 5.184 + 5.185 +uint8_t 5.186 +Msc_channel::num_cards() 5.187 +{ 5.188 + return _num_cards; 5.189 +} 5.190 + 5.191 // Receive data from the selected card. 5.192 5.193 uint32_t 5.194 @@ -1314,10 +1326,17 @@ 5.195 _regs[Msc_block_count] = block_count; 5.196 _regs[Msc_block_length] = block_size; 5.197 5.198 - // NOTE: Where CCS = 0, byte addressing is used. Otherwise, block addressing is used. 5.199 + // Where CCS = 0, byte addressing is used. Otherwise, block addressing is used. 5.200 + 5.201 + uint32_t address; 5.202 + 5.203 + if (_cards[card].ocr & Ocr_high_capacity_storage) 5.204 + address = block_address; 5.205 + else 5.206 + address = block_address * block_size; 5.207 5.208 if (!send_command(block_count == 1 ? Command_read_single_block 5.209 - : Command_read_multiple_block, block_address)) 5.210 + : Command_read_multiple_block, address)) 5.211 return 0; 5.212 5.213 read_response((uint16_t *) &r1, Response_size_R1);
6.1 --- a/pkg/devices/lib/msc/src/jz4780.cc Fri Feb 16 00:55:51 2024 +0100 6.2 +++ b/pkg/devices/lib/msc/src/jz4780.cc Fri Feb 16 23:11:25 2024 +0100 6.3 @@ -116,9 +116,14 @@ 6.4 static_cast<Dma_jz4780_channel *>(dma)); 6.5 } 6.6 6.7 -uint32_t jz4780_msc_get_status(void *msc_channel) 6.8 +struct msc_card *jz4780_msc_get_cards(void *msc_channel) 6.9 { 6.10 - return static_cast<Msc_channel *>(msc_channel)->get_status(); 6.11 + return static_cast<Msc_channel *>(msc_channel)->get_cards(); 6.12 +} 6.13 + 6.14 +uint8_t jz4780_msc_num_cards(void *msc_channel) 6.15 +{ 6.16 + return static_cast<Msc_channel *>(msc_channel)->num_cards(); 6.17 } 6.18 6.19 void jz4780_msc_enable(void *msc_channel)
7.1 --- a/pkg/devices/lib/msc/src/x1600.cc Fri Feb 16 00:55:51 2024 +0100 7.2 +++ b/pkg/devices/lib/msc/src/x1600.cc Fri Feb 16 23:11:25 2024 +0100 7.3 @@ -116,9 +116,14 @@ 7.4 static_cast<Dma_x1600_channel *>(dma)); 7.5 } 7.6 7.7 -uint32_t x1600_msc_get_status(void *msc_channel) 7.8 +struct msc_card *x1600_msc_get_cards(void *msc_channel) 7.9 { 7.10 - return static_cast<Msc_channel *>(msc_channel)->get_status(); 7.11 + return static_cast<Msc_channel *>(msc_channel)->get_cards(); 7.12 +} 7.13 + 7.14 +uint8_t x1600_msc_num_cards(void *msc_channel) 7.15 +{ 7.16 + return static_cast<Msc_channel *>(msc_channel)->num_cards(); 7.17 } 7.18 7.19 void x1600_msc_enable(void *msc_channel)
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/pkg/devices/util/include/boot.h Fri Feb 16 23:11:25 2024 +0100 8.3 @@ -0,0 +1,47 @@ 8.4 +/* 8.5 + * Boot-related utilities. 8.6 + * 8.7 + * Copyright (C) 2024 Paul Boddie <paul@boddie.org.uk> 8.8 + * 8.9 + * This program is free software; you can redistribute it and/or 8.10 + * modify it under the terms of the GNU General Public License as 8.11 + * published by the Free Software Foundation; either version 2 of 8.12 + * the License, or (at your option) any later version. 8.13 + * 8.14 + * This program is distributed in the hope that it will be useful, 8.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 8.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 8.17 + * GNU General Public License for more details. 8.18 + * 8.19 + * You should have received a copy of the GNU General Public License 8.20 + * along with this program; if not, write to the Free Software 8.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 8.22 + * Boston, MA 02110-1301, USA 8.23 + */ 8.24 + 8.25 +#pragma once 8.26 + 8.27 +#include <l4/sys/compiler.h> 8.28 +#include <stdint.h> 8.29 + 8.30 +struct chs_address 8.31 +{ 8.32 + uint8_t head; 8.33 + uint16_t sector:6, cylinder:10; 8.34 +} __attribute__((packed)); 8.35 + 8.36 +struct partition_table_entry 8.37 +{ 8.38 + uint8_t status; 8.39 + struct chs_address chs_first_sector; 8.40 + uint8_t partition_type; 8.41 + struct chs_address chs_last_sector; 8.42 + uint32_t lba_first_sector; 8.43 + uint32_t num_sectors; 8.44 +} __attribute__((packed)); 8.45 + 8.46 +EXTERN_C_BEGIN 8.47 + 8.48 +struct partition_table_entry *get_partition_table(uint8_t *data); 8.49 + 8.50 +EXTERN_C_END
9.1 --- a/pkg/devices/util/src/Makefile Fri Feb 16 00:55:51 2024 +0100 9.2 +++ b/pkg/devices/util/src/Makefile Fri Feb 16 23:11:25 2024 +0100 9.3 @@ -4,7 +4,7 @@ 9.4 TARGET = libdevice_util.o.a libdevice_util.o.so 9.5 PC_FILENAME := libdevice-util 9.6 9.7 -SRC_CC := byteorder.cc dataspace.cc dl.cc dma.cc event-loop.cc memory.cc 9.8 +SRC_CC := boot.cc byteorder.cc dataspace.cc dl.cc dma.cc event-loop.cc memory.cc 9.9 9.10 PRIVATE_INCDIR += $(PKGDIR)/util/include 9.11
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/pkg/devices/util/src/boot.cc Fri Feb 16 23:11:25 2024 +0100 10.3 @@ -0,0 +1,37 @@ 10.4 +/* 10.5 + * Boot-related utilities. 10.6 + * 10.7 + * Copyright (C) 2024 Paul Boddie <paul@boddie.org.uk> 10.8 + * 10.9 + * This program is free software; you can redistribute it and/or 10.10 + * modify it under the terms of the GNU General Public License as 10.11 + * published by the Free Software Foundation; either version 2 of 10.12 + * the License, or (at your option) any later version. 10.13 + * 10.14 + * This program is distributed in the hope that it will be useful, 10.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10.17 + * GNU General Public License for more details. 10.18 + * 10.19 + * You should have received a copy of the GNU General Public License 10.20 + * along with this program; if not, write to the Free Software 10.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 10.22 + * Boston, MA 02110-1301, USA 10.23 + */ 10.24 + 10.25 +#include <stddef.h> 10.26 + 10.27 +#include "boot.h" 10.28 + 10.29 + 10.30 + 10.31 +// Return a pointer to any partition table in the provided data or NULL if the 10.32 +// data appears not to contain such a table. 10.33 + 10.34 +struct partition_table_entry *get_partition_table(uint8_t *data) 10.35 +{ 10.36 + if ((data[0x1fe] != 0x55) || (data[0x1ff] != 0xaa)) 10.37 + return NULL; 10.38 + 10.39 + return (struct partition_table_entry *) &data[0x1be]; 10.40 +}
11.1 --- a/pkg/landfall-examples/hw_info/common.h Fri Feb 16 00:55:51 2024 +0100 11.2 +++ b/pkg/landfall-examples/hw_info/common.h Fri Feb 16 23:11:25 2024 +0100 11.3 @@ -172,7 +172,9 @@ 11.4 11.5 void *msc_get_channel(void *msc, uint8_t channel, l4_cap_idx_t irq, void *dma); 11.6 11.7 -uint32_t msc_get_status(void *msc_channel); 11.8 +struct msc_card *msc_get_cards(void *msc_channel); 11.9 + 11.10 +uint8_t msc_num_cards(void *msc_channel); 11.11 11.12 void msc_enable(void *msc_channel); 11.13
12.1 --- a/pkg/landfall-examples/hw_info/hw_info.c Fri Feb 16 00:55:51 2024 +0100 12.2 +++ b/pkg/landfall-examples/hw_info/hw_info.c Fri Feb 16 23:11:25 2024 +0100 12.3 @@ -22,8 +22,10 @@ 12.4 #include "common.h" 12.5 #include "defs.h" 12.6 12.7 +#include <l4/devices/boot.h> 12.8 #include <l4/devices/dma.h> 12.9 #include <l4/devices/memory.h> 12.10 +#include <l4/devices/msc.h> 12.11 12.12 #include <l4/io/io.h> 12.13 #include <l4/re/env.h> 12.14 @@ -1136,13 +1138,94 @@ 12.15 12.16 /* MSC operations. */ 12.17 12.18 +static void list_msc_cards(void) 12.19 +{ 12.20 + void *channel = get_channel(num_msc_channels, msc_channels, NULL); 12.21 + struct msc_card *cards; 12.22 + struct CSD *csd; 12.23 + uint8_t num; 12.24 + 12.25 + if (channel == NULL) 12.26 + return; 12.27 + 12.28 + cards = msc_get_cards(channel); 12.29 + 12.30 + printf("Card RCA Bits Size\n"); 12.31 + printf("---- ---- ---- --------------\n"); 12.32 + 12.33 + for (num = 0; num < msc_num_cards(channel); num++) 12.34 + { 12.35 + csd = &cards[num].csd; 12.36 + 12.37 + printf("%d %04x %d %d\n", num, cards[num].rca, cards[num].bus_width, 12.38 + (1 << csd->read_blocklen) * 12.39 + (csd->device_size + 1) * 12.40 + (1 << (csd->device_size_multiplier + 2))); 12.41 + } 12.42 +} 12.43 + 12.44 +static void list_msc_card_partitions(void) 12.45 +{ 12.46 + void *channel = get_channel(num_msc_channels, msc_channels, NULL); 12.47 + struct dma_region *dma_region; 12.48 + struct partition_table_entry *entry; 12.49 + uint32_t card, transferred; 12.50 + uint8_t num; 12.51 + 12.52 + if (channel == NULL) 12.53 + return; 12.54 + 12.55 + dma_region = _get_dma_region(); 12.56 + 12.57 + if (dma_region == NULL) 12.58 + return; 12.59 + 12.60 + if (!read_number("Card", &card)) 12.61 + return; 12.62 + 12.63 + l4_cache_inv_data(dma_region->vaddr, dma_region->vaddr + dma_region->size); 12.64 + 12.65 + transferred = msc_read_blocks(channel, (uint8_t) card, dma_region->paddr, 0, 1); 12.66 + 12.67 + if (!transferred) 12.68 + { 12.69 + printf("Could not read partitions.\n"); 12.70 + return; 12.71 + } 12.72 + 12.73 + entry = get_partition_table((uint8_t *) dma_region->vaddr); 12.74 + 12.75 + if (entry == NULL) 12.76 + { 12.77 + printf("Invalid partition table.\n"); 12.78 + return; 12.79 + } 12.80 + 12.81 + printf("Partition Status Type Start End Address Sectors\n"); 12.82 + printf("--------- ------ ---- --------- --------- -------- --------\n"); 12.83 + 12.84 + for (num = 0; num < 4; num++, entry++) 12.85 + { 12.86 + printf("%d %02x %02x %03x %02x %02x %03x %02x %02x %08x %08x\n", 12.87 + num, entry->status, entry->partition_type, 12.88 + entry->chs_first_sector.cylinder, 12.89 + entry->chs_first_sector.head, 12.90 + entry->chs_first_sector.sector, 12.91 + entry->chs_last_sector.cylinder, 12.92 + entry->chs_last_sector.head, 12.93 + entry->chs_last_sector.sector, 12.94 + entry->lba_first_sector, 12.95 + entry->num_sectors); 12.96 + } 12.97 +} 12.98 + 12.99 static void list_msc_channels(void) 12.100 { 12.101 unsigned int num; 12.102 void *channel; 12.103 12.104 - printf("Channel Status\n"); 12.105 - printf("------- --------\n"); 12.106 + printf("Channel Cards\n"); 12.107 + printf("------- -----\n"); 12.108 12.109 for (num = 0; num < num_msc_channels; num++) 12.110 { 12.111 @@ -1153,7 +1236,7 @@ 12.112 if (channel == NULL) 12.113 printf("inactive\n"); 12.114 else 12.115 - printf("%08x\n", msc_get_status(channel)); 12.116 + printf("%d\n", msc_num_cards(channel)); 12.117 } 12.118 } 12.119 12.120 @@ -1193,7 +1276,7 @@ 12.121 static void read_blocks_from_msc(void) 12.122 { 12.123 void *channel = get_channel(num_msc_channels, msc_channels, NULL); 12.124 - struct dma_region *dma_region = NULL; 12.125 + struct dma_region *dma_region; 12.126 uint32_t card, transferred, block_address, block_count; 12.127 12.128 if (channel == NULL) 12.129 @@ -1755,14 +1838,18 @@ 12.130 { 12.131 if (!strcmp(token, "l") || !strcmp(token, "list")) 12.132 list_msc_channels(); 12.133 + else if (!strcmp(token, "C") || !strcmp(token, "cards")) 12.134 + list_msc_cards(); 12.135 else if (!strcmp(token, "c") || !strcmp(token, "channel")) 12.136 new_msc_channel(msc); 12.137 else if (!strcmp(token, "e") || !strcmp(token, "enable")) 12.138 enable_msc_channel(); 12.139 + else if (!strcmp(token, "p") || !strcmp(token, "partitions")) 12.140 + list_msc_card_partitions(); 12.141 else if (!strcmp(token, "r") || !strcmp(token, "read")) 12.142 read_blocks_from_msc(); 12.143 else 12.144 - printf("msc channel | enable | read\n"); 12.145 + printf("msc cards | channel | enable | partitions | read\n"); 12.146 } 12.147 else 12.148 list_msc_channels();
13.1 --- a/pkg/landfall-examples/hw_info/jz4780.c Fri Feb 16 00:55:51 2024 +0100 13.2 +++ b/pkg/landfall-examples/hw_info/jz4780.c Fri Feb 16 23:11:25 2024 +0100 13.3 @@ -349,9 +349,14 @@ 13.4 return jz4780_msc_get_channel(msc, channel, irq, dma); 13.5 } 13.6 13.7 -uint32_t msc_get_status(void *msc_channel) 13.8 +struct msc_card *msc_get_cards(void *msc_channel) 13.9 { 13.10 - return jz4780_msc_get_status(msc_channel); 13.11 + return jz4780_msc_get_cards(msc_channel); 13.12 +} 13.13 + 13.14 +uint8_t msc_num_cards(void *msc_channel) 13.15 +{ 13.16 + return jz4780_msc_num_cards(msc_channel); 13.17 } 13.18 13.19 void msc_enable(void *msc_channel)
14.1 --- a/pkg/landfall-examples/hw_info/x1600.c Fri Feb 16 00:55:51 2024 +0100 14.2 +++ b/pkg/landfall-examples/hw_info/x1600.c Fri Feb 16 23:11:25 2024 +0100 14.3 @@ -338,9 +338,14 @@ 14.4 return x1600_msc_get_channel(msc, channel, irq, dma); 14.5 } 14.6 14.7 -uint32_t msc_get_status(void *msc_channel) 14.8 +struct msc_card *msc_get_cards(void *msc_channel) 14.9 { 14.10 - return x1600_msc_get_status(msc_channel); 14.11 + return x1600_msc_get_cards(msc_channel); 14.12 +} 14.13 + 14.14 +uint8_t msc_num_cards(void *msc_channel) 14.15 +{ 14.16 + return x1600_msc_num_cards(msc_channel); 14.17 } 14.18 14.19 void msc_enable(void *msc_channel)