+ uint8_t ret;
+ uint8_t response[1];
+ uint8_t start_block[8];
+ uint16_t status;
+ int tries;
+
+ ao_sdcard_lock();
+ if (!initialized) {
+ ao_sdcard_setup();
+ initialized = 1;
+ if (sdtype != ao_sdtype_unknown)
+ present = 1;
+ }
+ if (!present) {
+ ao_sdcard_unlock();
+ return 0;
+ }
+ DBG("write block %d\n", block);
+ if (sdtype != ao_sdtype_sd2block)
+ block <<= 9;
+
+ ao_sdcard_get();
+
+ for (tries = 0; tries < 10; tries++) {
+ ao_sdcard_select();
+
+ ret = ao_sdcard_send_cmd(SDCARD_WRITE_BLOCK, block);
+ ao_sdcard_recv_reply(NULL, 0);
+ if (ret != SDCARD_STATUS_READY_STATE)
+ goto bail;
+
+ /* Write a pad byte followed by the data start block marker */
+ start_block[0] = 0xff;
+ start_block[1] = SDCARD_DATA_START_BLOCK;
+ ao_sdcard_send(start_block, 2);
+
+ /* Send the data */
+ ao_sdcard_send(data, 512);
+
+ /* Fake the CRC */
+ ao_sdcard_send_fixed(0xff, 2);
+
+ /* See if the card liked the data */
+ ao_sdcard_recv(response, sizeof (response));
+ if ((response[0] & SDCARD_DATA_RES_MASK) != SDCARD_DATA_RES_ACCEPTED) {
+ int i;
+ WARN("Data not accepted, response");
+ for (i = 0; i < (int) sizeof (response); i++)
+ WARN(" %02x", response[i]);
+ WARN("\n");
+ ret = 0x3f;
+ goto bail;
+ }
+
+ /* Wait for the bus to go idle (should be done with an interrupt?) */
+ if (!ao_sdcard_wait_busy()) {
+ ret = 0x3f;
+ goto bail;
+ }
+
+ /* Check the current status after the write completes */
+ status = _ao_sdcard_send_status();
+ if ((status & 0xff) != SDCARD_STATUS_READY_STATE) {
+ WARN ("send status after write %04x\n", status);
+ ret = status & 0xff;
+ goto bail;
+ }
+ bail:
+ ao_sdcard_deselect();
+ DBG("write %s\n", ret == SDCARD_STATUS_READY_STATE ? "success" : "failure");
+ if (ret == SDCARD_STATUS_READY_STATE)
+ break;
+ }
+ ao_sdcard_put();
+ ao_sdcard_unlock();
+ if (tries)
+ WARN("took %d tries to write %d\n", tries + 1, block);
+
+ return ret == SDCARD_STATUS_READY_STATE;
+}
+
+#if SDCARD_DEBUG
+static uint8_t test_data[512];
+
+static void
+ao_sdcard_test_read(void)
+{
+ int i;
+
+ ao_cmd_decimal();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+
+ for (i = 0; i < 100; i++) {
+ printf ("."); flush();
+ if (!ao_sdcard_read_block(ao_cmd_lex_u32+i, test_data)) {
+ printf ("read error %d\n", i);
+ return;
+ }
+ }
+ printf ("data:");
+ for (i = 0; i < 18; i++)
+ printf (" %02x", test_data[i]);
+ printf ("\n");