2.1 --- a/pkg/devices/lib/msc/src/common.cc Thu Feb 15 23:18:09 2024 +0100
2.2 +++ b/pkg/devices/lib/msc/src/common.cc Fri Feb 16 00:55:51 2024 +0100
2.3 @@ -24,7 +24,6 @@
2.4 #include <l4/util/util.h>
2.5
2.6 #include <stdio.h>
2.7 -#include <string.h>
2.8
2.9 #include "msc-common.h"
2.10
2.11 @@ -464,13 +463,14 @@
2.12
2.13
2.14 // MMC response structures.
2.15 +// These are 16-bit aligned to permit conversion to 16-bit arrays.
2.16
2.17 struct R1
2.18 {
2.19 uint8_t end_crc;
2.20 uint32_t status;
2.21 uint8_t index:6, trans_start:2;
2.22 -} __attribute__((packed));
2.23 +} __attribute__((packed,aligned(__alignof__(uint16_t))));
2.24
2.25 struct R2
2.26 {
2.27 @@ -484,14 +484,14 @@
2.28 } payload;
2.29
2.30 uint8_t reserved_trans_start;
2.31 -} __attribute__((packed));
2.32 +} __attribute__((packed,aligned(__alignof__(uint16_t))));
2.33
2.34 struct R3
2.35 {
2.36 uint8_t end_reserved;
2.37 uint32_t ocr;
2.38 uint8_t reserved_trans_start;
2.39 -} __attribute__((packed));
2.40 +} __attribute__((packed,aligned(__alignof__(uint16_t))));
2.41
2.42 // SDIO response structures.
2.43
2.44 @@ -500,7 +500,7 @@
2.45 uint8_t end_reserved;
2.46 uint32_t ocr:24, stuff:3, memory_present:1, number_io_functions:3, ready:1;
2.47 uint8_t reserved_trans_start;
2.48 -} __attribute__((packed));
2.49 +} __attribute__((packed,aligned(__alignof__(uint16_t))));
2.50
2.51 struct R5
2.52 {
2.53 @@ -510,7 +510,7 @@
2.54 io_current_state:2, illegal_command:1, crc_error:1;
2.55 uint16_t stuff;
2.56 uint8_t index:6, trans_start:2;
2.57 -} __attribute__((packed));
2.58 +} __attribute__((packed,aligned(__alignof__(uint16_t))));
2.59
2.60 struct R6
2.61 {
2.62 @@ -518,7 +518,7 @@
2.63 uint16_t status;
2.64 uint16_t rca;
2.65 uint8_t index:6, trans_start:2;
2.66 -} __attribute__((packed));
2.67 +} __attribute__((packed,aligned(__alignof__(uint16_t))));
2.68
2.69 struct R7
2.70 {
2.71 @@ -531,7 +531,7 @@
2.72 } check_voltage;
2.73
2.74 uint8_t index:6, trans_start:2;
2.75 -} __attribute__((packed));
2.76 +} __attribute__((packed,aligned(__alignof__(uint16_t))));
2.77
2.78
2.79
2.80 @@ -825,7 +825,7 @@
2.81 bool
2.82 Msc_channel::send_app_command(uint8_t index, uint32_t arg)
2.83 {
2.84 - if (!send_command(Command_app_cmd, _current_rca << 16))
2.85 + if (!send_command(Command_app_cmd, _cards[_card].rca << 16))
2.86 return false;
2.87
2.88 return send_command(index, arg, get_app_response_format(index),
2.89 @@ -873,7 +873,7 @@
2.90 // NOTE: May need to set the SD bus width.
2.91
2.92 set_field(Msc_command_data_control, Cdc_bus_width_field_mask,
2.93 - Cdc_bus_width_field_shift, encode_bus_width(_current_bus_width));
2.94 + Cdc_bus_width_field_shift, encode_bus_width(_cards[_card].bus_width));
2.95
2.96 set_field(Msc_command_data_control, Cdc_recv_fifo_level_field_mask,
2.97 Cdc_recv_fifo_level_field_shift, Cdc_fifo_level_16);
2.98 @@ -924,6 +924,30 @@
2.99 return have_response;
2.100 }
2.101
2.102 +// Wait indefinitely for an interrupt request, returning true if one was delivered.
2.103 +
2.104 +bool
2.105 +Msc_channel::wait_for_irq(uint32_t flags)
2.106 +{
2.107 + return !l4_error(l4_irq_receive(_irq, L4_IPC_NEVER)) &&
2.108 + (_regs[Msc_interrupt_flag] & flags);
2.109 +}
2.110 +
2.111 +// Wait up to the given timeout (in microseconds) for an interrupt request,
2.112 +// returning true if one was delivered.
2.113 +
2.114 +bool
2.115 +Msc_channel::wait_for_irq(uint32_t flags, unsigned int timeout)
2.116 +{
2.117 + return !l4_error(l4_irq_receive(_irq, l4_timeout(L4_IPC_TIMEOUT_NEVER,
2.118 + l4util_micros2l4to(timeout)))) &&
2.119 + (_regs[Msc_interrupt_flag] & flags);
2.120 +}
2.121 +
2.122 +
2.123 +
2.124 +// Enable the controller and identify cards.
2.125 +
2.126 void
2.127 Msc_channel::enable()
2.128 {
2.129 @@ -956,7 +980,9 @@
2.130
2.131 set_field(Msc_clock_rate, Clock_rate_field_mask, Clock_rate_field_shift, 1);
2.132
2.133 - _current_rca = 0;
2.134 + // Initially, no card is selected.
2.135 +
2.136 + _card = -1;
2.137 }
2.138
2.139 // Check the voltage range of the SD card, potentially establishing that it is
2.140 @@ -965,8 +991,7 @@
2.141 bool
2.142 Msc_channel::check_sd()
2.143 {
2.144 - uint16_t buffer[Response_size_R7];
2.145 - struct R7 *r = (struct R7 *) buffer;
2.146 + struct R7 r7;
2.147
2.148 // Send an interface condition command.
2.149 // A card may not respond to this command.
2.150 @@ -974,11 +999,11 @@
2.151 if (!send_command(Command_send_if_cond, If_cond_default_voltage_range))
2.152 return true;
2.153
2.154 - read_response(buffer, Response_size_R7);
2.155 + read_response((uint16_t *) &r7, Response_size_R7);
2.156
2.157 // Reject any card not supporting the default voltage range.
2.158
2.159 - if (r->check_voltage.raw != If_cond_default_voltage_range)
2.160 + if (r7.check_voltage.raw != If_cond_default_voltage_range)
2.161 return false;
2.162
2.163 return true;
2.164 @@ -989,8 +1014,7 @@
2.165 void
2.166 Msc_channel::init_sdio()
2.167 {
2.168 - uint16_t buffer[Response_size_R4];
2.169 - struct R4 *r = (struct R4 *) buffer;
2.170 + struct R4 r4;
2.171 uint32_t ocr = 0;
2.172
2.173 // Reset any SDIO card or IO unit in a combined memory/IO card.
2.174 @@ -1010,28 +1034,27 @@
2.175 if (!send_command(Command_io_send_op_cond, ocr))
2.176 return;
2.177
2.178 - read_response(buffer, Response_size_R4);
2.179 + read_response((uint16_t *) &r4, Response_size_R4);
2.180
2.181 // Finish if no IO functions provided.
2.182 // NOTE: Should only need to check this the first time.
2.183
2.184 - if (r->number_io_functions == 0)
2.185 + if (r4.number_io_functions == 0)
2.186 return;
2.187
2.188 - if (r->ocr != Ocr_default_voltage_range)
2.189 + if (r4.ocr != Ocr_default_voltage_range)
2.190 {
2.191 ocr = Ocr_default_voltage_range;
2.192 continue;
2.193 }
2.194 }
2.195 - while (!r->ready);
2.196 + while (!r4.ready);
2.197 }
2.198
2.199 void
2.200 Msc_channel::init_sdmem()
2.201 {
2.202 - uint16_t buffer[Response_size_R3];
2.203 - struct R3 *r = (struct R3 *) buffer;
2.204 + struct R3 r3;
2.205
2.206 // Incorporate the HCS bit into the OCR for SDMEM.
2.207
2.208 @@ -1042,15 +1065,15 @@
2.209 if (!send_app_command(App_command_sd_send_op_cond, ocr))
2.210 return;
2.211
2.212 - read_response(buffer, Response_size_R3);
2.213 + read_response((uint16_t *) &r3, Response_size_R3);
2.214
2.215 - if (r->ocr != Ocr_default_voltage_range)
2.216 + if (r3.ocr != Ocr_default_voltage_range)
2.217 {
2.218 ocr = Ocr_default_voltage_range | Ocr_high_capacity_storage;
2.219 continue;
2.220 }
2.221 }
2.222 - while (!(r->ocr & Ocr_card_powered_up));
2.223 + while (!(r3.ocr & Ocr_card_powered_up));
2.224 }
2.225
2.226 void
2.227 @@ -1062,8 +1085,7 @@
2.228 // are solicited, the host must determine a suitable argument and reissue the
2.229 // command.
2.230
2.231 - uint16_t buffer[Response_size_R3];
2.232 - struct R3 *r = (struct R3 *) buffer;
2.233 + struct R3 r3;
2.234 uint32_t ocr = 0;
2.235
2.236 do
2.237 @@ -1071,124 +1093,133 @@
2.238 if (!send_command(Command_send_op_cond, ocr))
2.239 return;
2.240
2.241 - read_response(buffer, Response_size_R3);
2.242 + read_response((uint16_t *) &r3, Response_size_R3);
2.243
2.244 - if (r->ocr != Ocr_default_voltage_range)
2.245 + if (r3.ocr != Ocr_default_voltage_range)
2.246 {
2.247 ocr = Ocr_default_voltage_range;
2.248 continue;
2.249 }
2.250 }
2.251 - while (!(r->ocr & Ocr_card_powered_up));
2.252 + while (!(r3.ocr & Ocr_card_powered_up));
2.253 }
2.254
2.255 void
2.256 Msc_channel::identify_cards()
2.257 {
2.258 - uint16_t buffer[Response_size_R2];
2.259 - struct R2 *r = (struct R2 *) buffer;
2.260 + struct R2 r2;
2.261 + struct R6 r6;
2.262
2.263 - _cards = 0;
2.264 + _num_cards = 0;
2.265
2.266 while (send_command(Command_all_send_cid, 0))
2.267 {
2.268 - read_response(buffer, Response_size_R2);
2.269 + read_response((uint16_t *) &r2, Response_size_R2);
2.270
2.271 - memcpy(&_cid[_cards], r->payload.raw, sizeof(r->payload.raw));
2.272 + _cards[_num_cards].cid = r2.payload.cid;
2.273
2.274 - printf("card: %d\n", _cards);
2.275 - printf("date: %d %d\n", r->payload.cid.month, r->payload.cid.year);
2.276 - printf("serial: %d\n", r->payload.cid.serial);
2.277 - printf("revision: %d\n", r->payload.cid.revision);
2.278 - printf("name: %c%c%c%c%c\n", r->payload.cid.name[4], r->payload.cid.name[3],
2.279 - r->payload.cid.name[2], r->payload.cid.name[1],
2.280 - r->payload.cid.name[0]);
2.281 - printf("oem: %d\n", r->payload.cid.oem);
2.282 - printf("manufacturer: %d\n", r->payload.cid.manufacturer);
2.283 + printf("card: %d\n", _num_cards);
2.284 + printf("date: %d %d\n", r2.payload.cid.month, r2.payload.cid.year);
2.285 + printf("serial: %d\n", r2.payload.cid.serial);
2.286 + printf("revision: %d\n", r2.payload.cid.revision);
2.287 + printf("name: %c%c%c%c%c\n", r2.payload.cid.name[4], r2.payload.cid.name[3],
2.288 + r2.payload.cid.name[2], r2.payload.cid.name[1],
2.289 + r2.payload.cid.name[0]);
2.290 + printf("oem: %d\n", r2.payload.cid.oem);
2.291 + printf("manufacturer: %d\n", r2.payload.cid.manufacturer);
2.292
2.293 // Try and obtain a card-issued address.
2.294
2.295 if (send_command(Command_send_relative_addr, 0))
2.296 {
2.297 - uint16_t addr_buffer[Response_size_R6];
2.298 - struct R6 *ar = (struct R6 *) addr_buffer;
2.299 -
2.300 - read_response(addr_buffer, Response_size_R6);
2.301 -
2.302 - memcpy(&_rca[_cards], &ar->rca, sizeof(ar->rca));
2.303 + read_response((uint16_t *) &r6, Response_size_R6);
2.304 + _cards[_num_cards].rca = r6.rca;
2.305 }
2.306
2.307 // Try and assign an address.
2.308 // Employ 1-based relative addressing.
2.309
2.310 - else if (send_command(Command_set_relative_addr, _cards + 1))
2.311 - _rca[_cards] = _cards + 1;
2.312 + else if (send_command(Command_set_relative_addr, _num_cards + 1))
2.313 + _cards[_num_cards].rca = _num_cards + 1;
2.314
2.315 // Otherwise, stop identification.
2.316
2.317 else
2.318 return;
2.319
2.320 - // Set the default bus width.
2.321 + // Set the default bus width to be determined.
2.322
2.323 - _bus_width[_cards] = 0;
2.324 + _cards[_num_cards].bus_width = 0;
2.325
2.326 - _cards++;
2.327 + _num_cards++;
2.328 }
2.329 }
2.330
2.331 void
2.332 Msc_channel::query_cards()
2.333 {
2.334 - uint16_t buffer[Response_size_R2];
2.335 - struct R2 *r = (struct R2 *) buffer;
2.336 + struct R2 r2;
2.337 + struct R3 r3;
2.338 uint8_t card;
2.339
2.340 - for (card = 0; card < _cards; card++)
2.341 + for (card = 0; card < _num_cards; card++)
2.342 {
2.343 // Employ 1-based relative addressing.
2.344
2.345 - if (!send_command(Command_send_csd, _rca[card] << 16))
2.346 + if (!send_command(Command_send_csd, _cards[card].rca << 16))
2.347 return;
2.348
2.349 - read_response(buffer, Response_size_R2);
2.350 + read_response((uint16_t *) &r2, Response_size_R2);
2.351
2.352 - memcpy(&_csd[card], r->payload.raw, sizeof(r->payload.raw));
2.353 + _cards[card].csd = r2.payload.csd;
2.354
2.355 printf("card: %d\n", card);
2.356 - printf("csd: %d\n", r->payload.csd.csd);
2.357 - printf("copy: %s\n", r->payload.csd.copy ? "copied" : "original");
2.358 - printf("card command classes: %03x\n", r->payload.csd.card_command_classes);
2.359 - printf("device (size multiplier): %d %d\n", r->payload.csd.device_size + 1,
2.360 - 1 << (r->payload.csd.device_size_multiplier + 2));
2.361 - printf("device size: %d\n", (1 << r->payload.csd.read_blocklen) *
2.362 - (r->payload.csd.device_size + 1) *
2.363 - (1 << (r->payload.csd.device_size_multiplier + 2)));
2.364 - printf("transfer speed: %d MHz\n", r->payload.csd.tran_speed == 0x32 ? 25 : 50);
2.365 - printf("format group: %d %d\n", r->payload.csd.format, r->payload.csd.format_group);
2.366 - printf("write time factor: %d\n", 1 << r->payload.csd.write_time_factor);
2.367 - printf("write protect (temp perm): %s %s\n", r->payload.csd.temp_write_prot ? "yes" : "no",
2.368 - r->payload.csd.perm_write_prot ? "yes" : "no");
2.369 - printf("write protect group (enable size): %s %d\n", r->payload.csd.write_prot_group_enable ? "yes" : "no",
2.370 - r->payload.csd.write_prot_group_size + 1);
2.371 - printf("write block (partial length): %s %d\n", r->payload.csd.write_block_partial ? "yes" : "no",
2.372 - 1 << r->payload.csd.write_blocklen);
2.373 - printf("read block (partial length): %s %d\n", r->payload.csd.read_block_partial ? "yes" : "no",
2.374 - 1 << r->payload.csd.read_blocklen);
2.375 - printf("erase: sector single: %d %s\n", r->payload.csd.erase_sector_size + 1,
2.376 - r->payload.csd.erase_single_block_enable ? "yes" : "no");
2.377 - printf("misalign: read write: %s %s\n", r->payload.csd.read_block_misalign ? "yes" : "no",
2.378 - r->payload.csd.write_block_misalign ? "yes" : "no");
2.379 - printf("max read current (min max): %d %d\n", r->payload.csd.max_read_current_min,
2.380 - r->payload.csd.max_read_current_max);
2.381 - printf("max write current (min max): %d %d\n", r->payload.csd.max_write_current_min,
2.382 - r->payload.csd.max_write_current_max);
2.383 - printf("read access time (1 2): %d %d\n", r->payload.csd.data_read_access_time_1,
2.384 - r->payload.csd.data_read_access_time_2);
2.385 - printf("DSR: %s\n", r->payload.csd.dsr_implemented ? "yes" : "no");
2.386 + printf("csd: %d\n", r2.payload.csd.csd);
2.387 + printf("copy: %s\n", r2.payload.csd.copy ? "copied" : "original");
2.388 + printf("card command classes: %03x\n", r2.payload.csd.card_command_classes);
2.389 + printf("device (size multiplier): %d %d\n", r2.payload.csd.device_size + 1,
2.390 + 1 << (r2.payload.csd.device_size_multiplier + 2));
2.391 + printf("device size: %d\n", (1 << r2.payload.csd.read_blocklen) *
2.392 + (r2.payload.csd.device_size + 1) *
2.393 + (1 << (r2.payload.csd.device_size_multiplier + 2)));
2.394 + printf("transfer speed: %d MHz\n", r2.payload.csd.tran_speed == 0x32 ? 25 : 50);
2.395 + printf("format group: %d %d\n", r2.payload.csd.format, r2.payload.csd.format_group);
2.396 + printf("write time factor: %d\n", 1 << r2.payload.csd.write_time_factor);
2.397 + printf("write protect (temp perm): %s %s\n", r2.payload.csd.temp_write_prot ? "yes" : "no",
2.398 + r2.payload.csd.perm_write_prot ? "yes" : "no");
2.399 + printf("write protect group (enable size): %s %d\n", r2.payload.csd.write_prot_group_enable ? "yes" : "no",
2.400 + r2.payload.csd.write_prot_group_size + 1);
2.401 + printf("write block (partial length): %s %d\n", r2.payload.csd.write_block_partial ? "yes" : "no",
2.402 + 1 << r2.payload.csd.write_blocklen);
2.403 + printf("read block (partial length): %s %d\n", r2.payload.csd.read_block_partial ? "yes" : "no",
2.404 + 1 << r2.payload.csd.read_blocklen);
2.405 + printf("erase: sector single: %d %s\n", r2.payload.csd.erase_sector_size + 1,
2.406 + r2.payload.csd.erase_single_block_enable ? "yes" : "no");
2.407 + printf("misalign: read write: %s %s\n", r2.payload.csd.read_block_misalign ? "yes" : "no",
2.408 + r2.payload.csd.write_block_misalign ? "yes" : "no");
2.409 + printf("max read current (min max): %d %d\n", r2.payload.csd.max_read_current_min,
2.410 + r2.payload.csd.max_read_current_max);
2.411 + printf("max write current (min max): %d %d\n", r2.payload.csd.max_write_current_min,
2.412 + r2.payload.csd.max_write_current_max);
2.413 + printf("read access time (1 2): %d %d\n", r2.payload.csd.data_read_access_time_1,
2.414 + r2.payload.csd.data_read_access_time_2);
2.415 + printf("DSR: %s\n", r2.payload.csd.dsr_implemented ? "yes" : "no");
2.416 +
2.417 + // Query the OCR again now that we can associate it with a specific card.
2.418 +
2.419 + if (!send_app_command(App_command_read_ocr, 0))
2.420 + return;
2.421 +
2.422 + read_response((uint16_t *) &r3, Response_size_R3);
2.423 +
2.424 + _cards[card].ocr = r3.ocr;
2.425 }
2.426 }
2.427
2.428 +
2.429 +
2.430 +// Receive data from the selected card.
2.431 +
2.432 uint32_t
2.433 Msc_channel::recv_data(l4re_dma_space_dma_addr_t paddr, uint32_t count)
2.434 {
2.435 @@ -1209,6 +1240,8 @@
2.436 return to_transfer;
2.437 }
2.438
2.439 +// Send data to the selected card.
2.440 +
2.441 uint32_t
2.442 Msc_channel::send_data(l4re_dma_space_dma_addr_t paddr, uint32_t count)
2.443 {
2.444 @@ -1229,49 +1262,48 @@
2.445 return to_transfer;
2.446 }
2.447
2.448 +// Read blocks from the indicated card into a memory region.
2.449 +
2.450 uint32_t
2.451 Msc_channel::read_blocks(uint8_t card, l4re_dma_space_dma_addr_t paddr,
2.452 uint32_t block_address, uint32_t block_count)
2.453 {
2.454 - uint32_t block_size = 1 << _csd[card].read_blocklen;
2.455 - uint16_t buffer[Response_size_R1];
2.456 - struct R1 *r = (struct R1 *) buffer;
2.457 + uint32_t block_size = 1 << _cards[card].csd.read_blocklen;
2.458 + struct R1 r1;
2.459
2.460 // Select the requested card.
2.461
2.462 - if (_current_rca != _rca[card])
2.463 + if (_card != card)
2.464 {
2.465 - if (!send_command(Command_select_deselect_card, _rca[card] << 16))
2.466 + if (!send_command(Command_select_deselect_card, _cards[card].rca << 16))
2.467 return 0;
2.468
2.469 - read_response(buffer, Response_size_R1);
2.470 + read_response((uint16_t *) &r1, Response_size_R1);
2.471
2.472 - if (r->status & R1_status_error_mask)
2.473 + if (r1.status & R1_status_error_mask)
2.474 return 0;
2.475
2.476 - _current_rca = _rca[card];
2.477 + _card = card;
2.478 }
2.479
2.480 // NOTE: SMEM cards should allow bus width setting with the SCR register
2.481 // NOTE: describing the permitted values.
2.482 // NOTE: SDIO cards have their bus width set in CCCR via CMD52.
2.483
2.484 - if (!_bus_width[card])
2.485 + if (!_cards[card].bus_width)
2.486 {
2.487 if (send_app_command(App_command_set_bus_width, Bus_width_4bit))
2.488 - _bus_width[card] = 4;
2.489 + _cards[card].bus_width = 4;
2.490 else
2.491 - _bus_width[card] = 1;
2.492 + _cards[card].bus_width = 1;
2.493 }
2.494
2.495 - _current_bus_width = _bus_width[card];
2.496 -
2.497 if (!send_command(Command_set_blocklen, block_size))
2.498 return 0;
2.499
2.500 - read_response(buffer, Response_size_R1);
2.501 + read_response((uint16_t *) &r1, Response_size_R1);
2.502
2.503 - if (r->status & R1_status_error_mask)
2.504 + if (r1.status & R1_status_error_mask)
2.505 return 0;
2.506
2.507 // NOTE: Consider issuing a predefined block count command to any multiple
2.508 @@ -1288,9 +1320,9 @@
2.509 : Command_read_multiple_block, block_address))
2.510 return 0;
2.511
2.512 - read_response(buffer, Response_size_R1);
2.513 + read_response((uint16_t *) &r1, Response_size_R1);
2.514
2.515 - if (r->status & R1_status_error_mask)
2.516 + if (r1.status & R1_status_error_mask)
2.517 return 0;
2.518
2.519 // NOTE: Use Msc_block_success_count instead.
2.520 @@ -1303,26 +1335,6 @@
2.521 return transferred;
2.522 }
2.523
2.524 -// Wait indefinitely for an interrupt request, returning true if one was delivered.
2.525 -
2.526 -bool
2.527 -Msc_channel::wait_for_irq(uint32_t flags)
2.528 -{
2.529 - return !l4_error(l4_irq_receive(_irq, L4_IPC_NEVER)) &&
2.530 - (_regs[Msc_interrupt_flag] & flags);
2.531 -}
2.532 -
2.533 -// Wait up to the given timeout (in microseconds) for an interrupt request,
2.534 -// returning true if one was delivered.
2.535 -
2.536 -bool
2.537 -Msc_channel::wait_for_irq(uint32_t flags, unsigned int timeout)
2.538 -{
2.539 - return !l4_error(l4_irq_receive(_irq, l4_timeout(L4_IPC_TIMEOUT_NEVER,
2.540 - l4util_micros2l4to(timeout)))) &&
2.541 - (_regs[Msc_interrupt_flag] & flags);
2.542 -}
2.543 -
2.544
2.545
2.546 // Peripheral abstraction.