1.1 --- a/pkg/devices/lib/msc/src/common.cc Thu Feb 15 23:18:09 2024 +0100
1.2 +++ b/pkg/devices/lib/msc/src/common.cc Fri Feb 16 00:55:51 2024 +0100
1.3 @@ -24,7 +24,6 @@
1.4 #include <l4/util/util.h>
1.5
1.6 #include <stdio.h>
1.7 -#include <string.h>
1.8
1.9 #include "msc-common.h"
1.10
1.11 @@ -464,13 +463,14 @@
1.12
1.13
1.14 // MMC response structures.
1.15 +// These are 16-bit aligned to permit conversion to 16-bit arrays.
1.16
1.17 struct R1
1.18 {
1.19 uint8_t end_crc;
1.20 uint32_t status;
1.21 uint8_t index:6, trans_start:2;
1.22 -} __attribute__((packed));
1.23 +} __attribute__((packed,aligned(__alignof__(uint16_t))));
1.24
1.25 struct R2
1.26 {
1.27 @@ -484,14 +484,14 @@
1.28 } payload;
1.29
1.30 uint8_t reserved_trans_start;
1.31 -} __attribute__((packed));
1.32 +} __attribute__((packed,aligned(__alignof__(uint16_t))));
1.33
1.34 struct R3
1.35 {
1.36 uint8_t end_reserved;
1.37 uint32_t ocr;
1.38 uint8_t reserved_trans_start;
1.39 -} __attribute__((packed));
1.40 +} __attribute__((packed,aligned(__alignof__(uint16_t))));
1.41
1.42 // SDIO response structures.
1.43
1.44 @@ -500,7 +500,7 @@
1.45 uint8_t end_reserved;
1.46 uint32_t ocr:24, stuff:3, memory_present:1, number_io_functions:3, ready:1;
1.47 uint8_t reserved_trans_start;
1.48 -} __attribute__((packed));
1.49 +} __attribute__((packed,aligned(__alignof__(uint16_t))));
1.50
1.51 struct R5
1.52 {
1.53 @@ -510,7 +510,7 @@
1.54 io_current_state:2, illegal_command:1, crc_error:1;
1.55 uint16_t stuff;
1.56 uint8_t index:6, trans_start:2;
1.57 -} __attribute__((packed));
1.58 +} __attribute__((packed,aligned(__alignof__(uint16_t))));
1.59
1.60 struct R6
1.61 {
1.62 @@ -518,7 +518,7 @@
1.63 uint16_t status;
1.64 uint16_t rca;
1.65 uint8_t index:6, trans_start:2;
1.66 -} __attribute__((packed));
1.67 +} __attribute__((packed,aligned(__alignof__(uint16_t))));
1.68
1.69 struct R7
1.70 {
1.71 @@ -531,7 +531,7 @@
1.72 } check_voltage;
1.73
1.74 uint8_t index:6, trans_start:2;
1.75 -} __attribute__((packed));
1.76 +} __attribute__((packed,aligned(__alignof__(uint16_t))));
1.77
1.78
1.79
1.80 @@ -825,7 +825,7 @@
1.81 bool
1.82 Msc_channel::send_app_command(uint8_t index, uint32_t arg)
1.83 {
1.84 - if (!send_command(Command_app_cmd, _current_rca << 16))
1.85 + if (!send_command(Command_app_cmd, _cards[_card].rca << 16))
1.86 return false;
1.87
1.88 return send_command(index, arg, get_app_response_format(index),
1.89 @@ -873,7 +873,7 @@
1.90 // NOTE: May need to set the SD bus width.
1.91
1.92 set_field(Msc_command_data_control, Cdc_bus_width_field_mask,
1.93 - Cdc_bus_width_field_shift, encode_bus_width(_current_bus_width));
1.94 + Cdc_bus_width_field_shift, encode_bus_width(_cards[_card].bus_width));
1.95
1.96 set_field(Msc_command_data_control, Cdc_recv_fifo_level_field_mask,
1.97 Cdc_recv_fifo_level_field_shift, Cdc_fifo_level_16);
1.98 @@ -924,6 +924,30 @@
1.99 return have_response;
1.100 }
1.101
1.102 +// Wait indefinitely for an interrupt request, returning true if one was delivered.
1.103 +
1.104 +bool
1.105 +Msc_channel::wait_for_irq(uint32_t flags)
1.106 +{
1.107 + return !l4_error(l4_irq_receive(_irq, L4_IPC_NEVER)) &&
1.108 + (_regs[Msc_interrupt_flag] & flags);
1.109 +}
1.110 +
1.111 +// Wait up to the given timeout (in microseconds) for an interrupt request,
1.112 +// returning true if one was delivered.
1.113 +
1.114 +bool
1.115 +Msc_channel::wait_for_irq(uint32_t flags, unsigned int timeout)
1.116 +{
1.117 + return !l4_error(l4_irq_receive(_irq, l4_timeout(L4_IPC_TIMEOUT_NEVER,
1.118 + l4util_micros2l4to(timeout)))) &&
1.119 + (_regs[Msc_interrupt_flag] & flags);
1.120 +}
1.121 +
1.122 +
1.123 +
1.124 +// Enable the controller and identify cards.
1.125 +
1.126 void
1.127 Msc_channel::enable()
1.128 {
1.129 @@ -956,7 +980,9 @@
1.130
1.131 set_field(Msc_clock_rate, Clock_rate_field_mask, Clock_rate_field_shift, 1);
1.132
1.133 - _current_rca = 0;
1.134 + // Initially, no card is selected.
1.135 +
1.136 + _card = -1;
1.137 }
1.138
1.139 // Check the voltage range of the SD card, potentially establishing that it is
1.140 @@ -965,8 +991,7 @@
1.141 bool
1.142 Msc_channel::check_sd()
1.143 {
1.144 - uint16_t buffer[Response_size_R7];
1.145 - struct R7 *r = (struct R7 *) buffer;
1.146 + struct R7 r7;
1.147
1.148 // Send an interface condition command.
1.149 // A card may not respond to this command.
1.150 @@ -974,11 +999,11 @@
1.151 if (!send_command(Command_send_if_cond, If_cond_default_voltage_range))
1.152 return true;
1.153
1.154 - read_response(buffer, Response_size_R7);
1.155 + read_response((uint16_t *) &r7, Response_size_R7);
1.156
1.157 // Reject any card not supporting the default voltage range.
1.158
1.159 - if (r->check_voltage.raw != If_cond_default_voltage_range)
1.160 + if (r7.check_voltage.raw != If_cond_default_voltage_range)
1.161 return false;
1.162
1.163 return true;
1.164 @@ -989,8 +1014,7 @@
1.165 void
1.166 Msc_channel::init_sdio()
1.167 {
1.168 - uint16_t buffer[Response_size_R4];
1.169 - struct R4 *r = (struct R4 *) buffer;
1.170 + struct R4 r4;
1.171 uint32_t ocr = 0;
1.172
1.173 // Reset any SDIO card or IO unit in a combined memory/IO card.
1.174 @@ -1010,28 +1034,27 @@
1.175 if (!send_command(Command_io_send_op_cond, ocr))
1.176 return;
1.177
1.178 - read_response(buffer, Response_size_R4);
1.179 + read_response((uint16_t *) &r4, Response_size_R4);
1.180
1.181 // Finish if no IO functions provided.
1.182 // NOTE: Should only need to check this the first time.
1.183
1.184 - if (r->number_io_functions == 0)
1.185 + if (r4.number_io_functions == 0)
1.186 return;
1.187
1.188 - if (r->ocr != Ocr_default_voltage_range)
1.189 + if (r4.ocr != Ocr_default_voltage_range)
1.190 {
1.191 ocr = Ocr_default_voltage_range;
1.192 continue;
1.193 }
1.194 }
1.195 - while (!r->ready);
1.196 + while (!r4.ready);
1.197 }
1.198
1.199 void
1.200 Msc_channel::init_sdmem()
1.201 {
1.202 - uint16_t buffer[Response_size_R3];
1.203 - struct R3 *r = (struct R3 *) buffer;
1.204 + struct R3 r3;
1.205
1.206 // Incorporate the HCS bit into the OCR for SDMEM.
1.207
1.208 @@ -1042,15 +1065,15 @@
1.209 if (!send_app_command(App_command_sd_send_op_cond, ocr))
1.210 return;
1.211
1.212 - read_response(buffer, Response_size_R3);
1.213 + read_response((uint16_t *) &r3, Response_size_R3);
1.214
1.215 - if (r->ocr != Ocr_default_voltage_range)
1.216 + if (r3.ocr != Ocr_default_voltage_range)
1.217 {
1.218 ocr = Ocr_default_voltage_range | Ocr_high_capacity_storage;
1.219 continue;
1.220 }
1.221 }
1.222 - while (!(r->ocr & Ocr_card_powered_up));
1.223 + while (!(r3.ocr & Ocr_card_powered_up));
1.224 }
1.225
1.226 void
1.227 @@ -1062,8 +1085,7 @@
1.228 // are solicited, the host must determine a suitable argument and reissue the
1.229 // command.
1.230
1.231 - uint16_t buffer[Response_size_R3];
1.232 - struct R3 *r = (struct R3 *) buffer;
1.233 + struct R3 r3;
1.234 uint32_t ocr = 0;
1.235
1.236 do
1.237 @@ -1071,124 +1093,133 @@
1.238 if (!send_command(Command_send_op_cond, ocr))
1.239 return;
1.240
1.241 - read_response(buffer, Response_size_R3);
1.242 + read_response((uint16_t *) &r3, Response_size_R3);
1.243
1.244 - if (r->ocr != Ocr_default_voltage_range)
1.245 + if (r3.ocr != Ocr_default_voltage_range)
1.246 {
1.247 ocr = Ocr_default_voltage_range;
1.248 continue;
1.249 }
1.250 }
1.251 - while (!(r->ocr & Ocr_card_powered_up));
1.252 + while (!(r3.ocr & Ocr_card_powered_up));
1.253 }
1.254
1.255 void
1.256 Msc_channel::identify_cards()
1.257 {
1.258 - uint16_t buffer[Response_size_R2];
1.259 - struct R2 *r = (struct R2 *) buffer;
1.260 + struct R2 r2;
1.261 + struct R6 r6;
1.262
1.263 - _cards = 0;
1.264 + _num_cards = 0;
1.265
1.266 while (send_command(Command_all_send_cid, 0))
1.267 {
1.268 - read_response(buffer, Response_size_R2);
1.269 + read_response((uint16_t *) &r2, Response_size_R2);
1.270
1.271 - memcpy(&_cid[_cards], r->payload.raw, sizeof(r->payload.raw));
1.272 + _cards[_num_cards].cid = r2.payload.cid;
1.273
1.274 - printf("card: %d\n", _cards);
1.275 - printf("date: %d %d\n", r->payload.cid.month, r->payload.cid.year);
1.276 - printf("serial: %d\n", r->payload.cid.serial);
1.277 - printf("revision: %d\n", r->payload.cid.revision);
1.278 - printf("name: %c%c%c%c%c\n", r->payload.cid.name[4], r->payload.cid.name[3],
1.279 - r->payload.cid.name[2], r->payload.cid.name[1],
1.280 - r->payload.cid.name[0]);
1.281 - printf("oem: %d\n", r->payload.cid.oem);
1.282 - printf("manufacturer: %d\n", r->payload.cid.manufacturer);
1.283 + printf("card: %d\n", _num_cards);
1.284 + printf("date: %d %d\n", r2.payload.cid.month, r2.payload.cid.year);
1.285 + printf("serial: %d\n", r2.payload.cid.serial);
1.286 + printf("revision: %d\n", r2.payload.cid.revision);
1.287 + printf("name: %c%c%c%c%c\n", r2.payload.cid.name[4], r2.payload.cid.name[3],
1.288 + r2.payload.cid.name[2], r2.payload.cid.name[1],
1.289 + r2.payload.cid.name[0]);
1.290 + printf("oem: %d\n", r2.payload.cid.oem);
1.291 + printf("manufacturer: %d\n", r2.payload.cid.manufacturer);
1.292
1.293 // Try and obtain a card-issued address.
1.294
1.295 if (send_command(Command_send_relative_addr, 0))
1.296 {
1.297 - uint16_t addr_buffer[Response_size_R6];
1.298 - struct R6 *ar = (struct R6 *) addr_buffer;
1.299 -
1.300 - read_response(addr_buffer, Response_size_R6);
1.301 -
1.302 - memcpy(&_rca[_cards], &ar->rca, sizeof(ar->rca));
1.303 + read_response((uint16_t *) &r6, Response_size_R6);
1.304 + _cards[_num_cards].rca = r6.rca;
1.305 }
1.306
1.307 // Try and assign an address.
1.308 // Employ 1-based relative addressing.
1.309
1.310 - else if (send_command(Command_set_relative_addr, _cards + 1))
1.311 - _rca[_cards] = _cards + 1;
1.312 + else if (send_command(Command_set_relative_addr, _num_cards + 1))
1.313 + _cards[_num_cards].rca = _num_cards + 1;
1.314
1.315 // Otherwise, stop identification.
1.316
1.317 else
1.318 return;
1.319
1.320 - // Set the default bus width.
1.321 + // Set the default bus width to be determined.
1.322
1.323 - _bus_width[_cards] = 0;
1.324 + _cards[_num_cards].bus_width = 0;
1.325
1.326 - _cards++;
1.327 + _num_cards++;
1.328 }
1.329 }
1.330
1.331 void
1.332 Msc_channel::query_cards()
1.333 {
1.334 - uint16_t buffer[Response_size_R2];
1.335 - struct R2 *r = (struct R2 *) buffer;
1.336 + struct R2 r2;
1.337 + struct R3 r3;
1.338 uint8_t card;
1.339
1.340 - for (card = 0; card < _cards; card++)
1.341 + for (card = 0; card < _num_cards; card++)
1.342 {
1.343 // Employ 1-based relative addressing.
1.344
1.345 - if (!send_command(Command_send_csd, _rca[card] << 16))
1.346 + if (!send_command(Command_send_csd, _cards[card].rca << 16))
1.347 return;
1.348
1.349 - read_response(buffer, Response_size_R2);
1.350 + read_response((uint16_t *) &r2, Response_size_R2);
1.351
1.352 - memcpy(&_csd[card], r->payload.raw, sizeof(r->payload.raw));
1.353 + _cards[card].csd = r2.payload.csd;
1.354
1.355 printf("card: %d\n", card);
1.356 - printf("csd: %d\n", r->payload.csd.csd);
1.357 - printf("copy: %s\n", r->payload.csd.copy ? "copied" : "original");
1.358 - printf("card command classes: %03x\n", r->payload.csd.card_command_classes);
1.359 - printf("device (size multiplier): %d %d\n", r->payload.csd.device_size + 1,
1.360 - 1 << (r->payload.csd.device_size_multiplier + 2));
1.361 - printf("device size: %d\n", (1 << r->payload.csd.read_blocklen) *
1.362 - (r->payload.csd.device_size + 1) *
1.363 - (1 << (r->payload.csd.device_size_multiplier + 2)));
1.364 - printf("transfer speed: %d MHz\n", r->payload.csd.tran_speed == 0x32 ? 25 : 50);
1.365 - printf("format group: %d %d\n", r->payload.csd.format, r->payload.csd.format_group);
1.366 - printf("write time factor: %d\n", 1 << r->payload.csd.write_time_factor);
1.367 - printf("write protect (temp perm): %s %s\n", r->payload.csd.temp_write_prot ? "yes" : "no",
1.368 - r->payload.csd.perm_write_prot ? "yes" : "no");
1.369 - printf("write protect group (enable size): %s %d\n", r->payload.csd.write_prot_group_enable ? "yes" : "no",
1.370 - r->payload.csd.write_prot_group_size + 1);
1.371 - printf("write block (partial length): %s %d\n", r->payload.csd.write_block_partial ? "yes" : "no",
1.372 - 1 << r->payload.csd.write_blocklen);
1.373 - printf("read block (partial length): %s %d\n", r->payload.csd.read_block_partial ? "yes" : "no",
1.374 - 1 << r->payload.csd.read_blocklen);
1.375 - printf("erase: sector single: %d %s\n", r->payload.csd.erase_sector_size + 1,
1.376 - r->payload.csd.erase_single_block_enable ? "yes" : "no");
1.377 - printf("misalign: read write: %s %s\n", r->payload.csd.read_block_misalign ? "yes" : "no",
1.378 - r->payload.csd.write_block_misalign ? "yes" : "no");
1.379 - printf("max read current (min max): %d %d\n", r->payload.csd.max_read_current_min,
1.380 - r->payload.csd.max_read_current_max);
1.381 - printf("max write current (min max): %d %d\n", r->payload.csd.max_write_current_min,
1.382 - r->payload.csd.max_write_current_max);
1.383 - printf("read access time (1 2): %d %d\n", r->payload.csd.data_read_access_time_1,
1.384 - r->payload.csd.data_read_access_time_2);
1.385 - printf("DSR: %s\n", r->payload.csd.dsr_implemented ? "yes" : "no");
1.386 + printf("csd: %d\n", r2.payload.csd.csd);
1.387 + printf("copy: %s\n", r2.payload.csd.copy ? "copied" : "original");
1.388 + printf("card command classes: %03x\n", r2.payload.csd.card_command_classes);
1.389 + printf("device (size multiplier): %d %d\n", r2.payload.csd.device_size + 1,
1.390 + 1 << (r2.payload.csd.device_size_multiplier + 2));
1.391 + printf("device size: %d\n", (1 << r2.payload.csd.read_blocklen) *
1.392 + (r2.payload.csd.device_size + 1) *
1.393 + (1 << (r2.payload.csd.device_size_multiplier + 2)));
1.394 + printf("transfer speed: %d MHz\n", r2.payload.csd.tran_speed == 0x32 ? 25 : 50);
1.395 + printf("format group: %d %d\n", r2.payload.csd.format, r2.payload.csd.format_group);
1.396 + printf("write time factor: %d\n", 1 << r2.payload.csd.write_time_factor);
1.397 + printf("write protect (temp perm): %s %s\n", r2.payload.csd.temp_write_prot ? "yes" : "no",
1.398 + r2.payload.csd.perm_write_prot ? "yes" : "no");
1.399 + printf("write protect group (enable size): %s %d\n", r2.payload.csd.write_prot_group_enable ? "yes" : "no",
1.400 + r2.payload.csd.write_prot_group_size + 1);
1.401 + printf("write block (partial length): %s %d\n", r2.payload.csd.write_block_partial ? "yes" : "no",
1.402 + 1 << r2.payload.csd.write_blocklen);
1.403 + printf("read block (partial length): %s %d\n", r2.payload.csd.read_block_partial ? "yes" : "no",
1.404 + 1 << r2.payload.csd.read_blocklen);
1.405 + printf("erase: sector single: %d %s\n", r2.payload.csd.erase_sector_size + 1,
1.406 + r2.payload.csd.erase_single_block_enable ? "yes" : "no");
1.407 + printf("misalign: read write: %s %s\n", r2.payload.csd.read_block_misalign ? "yes" : "no",
1.408 + r2.payload.csd.write_block_misalign ? "yes" : "no");
1.409 + printf("max read current (min max): %d %d\n", r2.payload.csd.max_read_current_min,
1.410 + r2.payload.csd.max_read_current_max);
1.411 + printf("max write current (min max): %d %d\n", r2.payload.csd.max_write_current_min,
1.412 + r2.payload.csd.max_write_current_max);
1.413 + printf("read access time (1 2): %d %d\n", r2.payload.csd.data_read_access_time_1,
1.414 + r2.payload.csd.data_read_access_time_2);
1.415 + printf("DSR: %s\n", r2.payload.csd.dsr_implemented ? "yes" : "no");
1.416 +
1.417 + // Query the OCR again now that we can associate it with a specific card.
1.418 +
1.419 + if (!send_app_command(App_command_read_ocr, 0))
1.420 + return;
1.421 +
1.422 + read_response((uint16_t *) &r3, Response_size_R3);
1.423 +
1.424 + _cards[card].ocr = r3.ocr;
1.425 }
1.426 }
1.427
1.428 +
1.429 +
1.430 +// Receive data from the selected card.
1.431 +
1.432 uint32_t
1.433 Msc_channel::recv_data(l4re_dma_space_dma_addr_t paddr, uint32_t count)
1.434 {
1.435 @@ -1209,6 +1240,8 @@
1.436 return to_transfer;
1.437 }
1.438
1.439 +// Send data to the selected card.
1.440 +
1.441 uint32_t
1.442 Msc_channel::send_data(l4re_dma_space_dma_addr_t paddr, uint32_t count)
1.443 {
1.444 @@ -1229,49 +1262,48 @@
1.445 return to_transfer;
1.446 }
1.447
1.448 +// Read blocks from the indicated card into a memory region.
1.449 +
1.450 uint32_t
1.451 Msc_channel::read_blocks(uint8_t card, l4re_dma_space_dma_addr_t paddr,
1.452 uint32_t block_address, uint32_t block_count)
1.453 {
1.454 - uint32_t block_size = 1 << _csd[card].read_blocklen;
1.455 - uint16_t buffer[Response_size_R1];
1.456 - struct R1 *r = (struct R1 *) buffer;
1.457 + uint32_t block_size = 1 << _cards[card].csd.read_blocklen;
1.458 + struct R1 r1;
1.459
1.460 // Select the requested card.
1.461
1.462 - if (_current_rca != _rca[card])
1.463 + if (_card != card)
1.464 {
1.465 - if (!send_command(Command_select_deselect_card, _rca[card] << 16))
1.466 + if (!send_command(Command_select_deselect_card, _cards[card].rca << 16))
1.467 return 0;
1.468
1.469 - read_response(buffer, Response_size_R1);
1.470 + read_response((uint16_t *) &r1, Response_size_R1);
1.471
1.472 - if (r->status & R1_status_error_mask)
1.473 + if (r1.status & R1_status_error_mask)
1.474 return 0;
1.475
1.476 - _current_rca = _rca[card];
1.477 + _card = card;
1.478 }
1.479
1.480 // NOTE: SMEM cards should allow bus width setting with the SCR register
1.481 // NOTE: describing the permitted values.
1.482 // NOTE: SDIO cards have their bus width set in CCCR via CMD52.
1.483
1.484 - if (!_bus_width[card])
1.485 + if (!_cards[card].bus_width)
1.486 {
1.487 if (send_app_command(App_command_set_bus_width, Bus_width_4bit))
1.488 - _bus_width[card] = 4;
1.489 + _cards[card].bus_width = 4;
1.490 else
1.491 - _bus_width[card] = 1;
1.492 + _cards[card].bus_width = 1;
1.493 }
1.494
1.495 - _current_bus_width = _bus_width[card];
1.496 -
1.497 if (!send_command(Command_set_blocklen, block_size))
1.498 return 0;
1.499
1.500 - read_response(buffer, Response_size_R1);
1.501 + read_response((uint16_t *) &r1, Response_size_R1);
1.502
1.503 - if (r->status & R1_status_error_mask)
1.504 + if (r1.status & R1_status_error_mask)
1.505 return 0;
1.506
1.507 // NOTE: Consider issuing a predefined block count command to any multiple
1.508 @@ -1288,9 +1320,9 @@
1.509 : Command_read_multiple_block, block_address))
1.510 return 0;
1.511
1.512 - read_response(buffer, Response_size_R1);
1.513 + read_response((uint16_t *) &r1, Response_size_R1);
1.514
1.515 - if (r->status & R1_status_error_mask)
1.516 + if (r1.status & R1_status_error_mask)
1.517 return 0;
1.518
1.519 // NOTE: Use Msc_block_success_count instead.
1.520 @@ -1303,26 +1335,6 @@
1.521 return transferred;
1.522 }
1.523
1.524 -// Wait indefinitely for an interrupt request, returning true if one was delivered.
1.525 -
1.526 -bool
1.527 -Msc_channel::wait_for_irq(uint32_t flags)
1.528 -{
1.529 - return !l4_error(l4_irq_receive(_irq, L4_IPC_NEVER)) &&
1.530 - (_regs[Msc_interrupt_flag] & flags);
1.531 -}
1.532 -
1.533 -// Wait up to the given timeout (in microseconds) for an interrupt request,
1.534 -// returning true if one was delivered.
1.535 -
1.536 -bool
1.537 -Msc_channel::wait_for_irq(uint32_t flags, unsigned int timeout)
1.538 -{
1.539 - return !l4_error(l4_irq_receive(_irq, l4_timeout(L4_IPC_TIMEOUT_NEVER,
1.540 - l4util_micros2l4to(timeout)))) &&
1.541 - (_regs[Msc_interrupt_flag] & flags);
1.542 -}
1.543 -
1.544
1.545
1.546 // Peripheral abstraction.