static int server_on_request(struct xio_session *session, struct xio_msg *xio_req, int last_in_rxq, void *cb_user_conext) { struct client_info *ci = (struct client_info *)cb_user_conext; struct sd_req *hdr; struct request *req; struct xio_iovec_ex *sglist = vmsg_sglist(&xio_req->in); int nents = vmsg_sglist_nents(&xio_req->in); sd_debug("on request: %p, %p, nents: %d", session, xio_req, nents); hdr = xio_req->in.header.iov_base; req = alloc_request(ci, hdr->data_length); memcpy(&req->rq, hdr, sizeof(req->rq)); if (hdr->data_length && hdr->flags & SD_FLAG_CMD_WRITE) { sd_assert(nents == 1); req->data = sglist[0].iov_base; } xio_req->in.header.iov_base = NULL; xio_req->in.header.iov_len = 0; vmsg_sglist_set_nents(&xio_req->in, 0); ci->xio_req = xio_req; queue_request(req); xio_context_stop_loop(xio_get_main_ctx()); return 0; }
int xio_exec_req(const struct node_id *nid, struct sd_req *hdr, void *data, bool (*need_retry)(uint32_t epoch), uint32_t epoch, uint32_t max_count) { struct xio_context *ctx = xio_context_create(NULL, 0, -1); struct client_data cli = { .ctx = ctx }; struct xio_connection *conn = sd_xio_create_connection(ctx, nid, &cli); struct xio_msg xreq; struct sd_rsp rsp; sd_assert(!is_main_thread()); memset(&rsp, 0, sizeof(rsp)); memset(&xreq, 0, sizeof(xreq)); client_msg_vec_init(&xreq); memset(&rsp, 0, sizeof(rsp)); msg_prep_for_send(hdr, &rsp, data, &xreq); xio_send_request(conn, &xreq); xio_context_run_loop(ctx, XIO_INFINITE); msg_finalize(hdr, data, cli.rsp); xio_connection_destroy(conn); xio_context_destroy(ctx); return 0; }
u8 sd_open( void ) { u8 i; u8 resp[ R1 + 16 + 2 ]; u24 deleteme; // Check for card if( !sd_card_present() ) return( SD_ERR_NOCARD ); // SPI to 400kHz SPI_BRG_H = 0x00; SPI_BRG_L = 0x7D; // Required delays before initialization sd_assert(); sd_delay( 100 ); sd_deassert(); sd_delay( 2 ); // Enter idle state if( sd_send_command( CMD0_GO_IDLE_STATE, NULL, NULL ) != SD_ERR_OK ) return( SD_ERR_GENERIC ); // Read OCR (for operating conditions) and verify 3.3V capability if( sd_send_command( CMD58_READ_OCR, NULL, resp ) != SD_ERR_OK ) return( SD_ERR_GENERIC ); if( !( resp[ 2 ] & MSK_OCR_33 ) ) return( SD_ERR_OCR ); // Initialize card i = 0; do { if( sd_send_command( ACMD41_APP_SEND_OP_COND, NULL, resp ) != SD_ERR_OK ) return( SD_ERR_GENERIC ); } while( ( resp[ 0 ] & SD_ERR_R1_IDLE ) && ++i != SD_IDLE_TIMEOUT ); // Set block length to 512 (compatible with SDHC) if( sd_set_blocklen( 512 ) != SD_ERR_OK ) return( SD_ERR_GENERIC ); // Read CSD //if( sd_send_command( CMD9_SEND_CSD, NULL, resp ) != SD_ERR_OK ) return( SD_ERR_GENERIC ); /* for( i = 0; i < 255; i++ ) { sd_readblock( i, block ); for( deleteme = 0; deleteme < 512; deleteme++ ) { if( block[ deleteme ] != 0 ) { asm( "NOP" ); asm( "NOP" ); asm( "NOP" ); asm( "NOP" ); asm( "NOP" ); asm( "NOP" ); asm( "NOP" ); asm( "NOP" ); break; } } } */ // All hail the initialized SD card! return( SD_ERR_OK ); }
static void signal_handler(int listen_fd, int events, void *data) { struct signalfd_siginfo siginfo; int uninitialized_var(ret); ret = read(sigfd, &siginfo, sizeof(siginfo)); sd_assert(ret == sizeof(siginfo)); sd_debug("signal %d, ssi pid %d", siginfo.ssi_signo, siginfo.ssi_pid); switch (siginfo.ssi_signo) { case SIGTERM: sys->cinfo.status = SD_STATUS_KILLED; break; default: sd_err("signal %d unhandled", siginfo.ssi_signo); break; } }
static u8 sd_readblock( u32 addr, u8 *data ) { u8 tmp, i, resp[ R2 ]; u24 count; u16 crc; addr <<= 9; //sd_waitidle(); if( sd_send_command( CMD17_READ_SINGLE_BLOCK, &addr, resp ) != SD_ERR_OK ) return( SD_ERR_GENERIC ); if( resp[ 0 ] ) return( SD_ERR_READ ); sd_assert(); // Wait (with timeout) for data token i = 0; do { tmp = spi_txrx( CMD_IDLE ); } while( ++i != SD_READ_TIMEOUT && tmp == 0xFF ); // Bail on error if( !( tmp & MSK_TOK_DATAERROR ) ) { spi_txrx( CMD_IDLE ); sd_deassert(); return( SD_ERR_READ ); } // Read data count = 512; while( count-- ) { *data++ = spi_txrx( CMD_IDLE ); } // Read CRC high8( crc ) = spi_txrx( CMD_IDLE ); low8( crc ) = spi_txrx( CMD_IDLE ); tmp = spi_txrx( CMD_IDLE ); sd_deassert(); return( SD_ERR_OK ); }
static int server_on_session_event(struct xio_session *session, struct xio_session_event_data *event_data, void *cb_user_context) { struct client_info *ci; struct xio_connection_attr attr; struct server_data *server_data = (struct server_data *)cb_user_context; sd_debug("session event: %s. session:%p, connection:%p, reason: %s", xio_session_event_str(event_data->event), session, event_data->conn, xio_strerror(event_data->reason)); switch (event_data->event) { case XIO_SESSION_NEW_CONNECTION_EVENT: server_data->nr_conn++; memset(&attr, 0, sizeof(attr)); ci = xio_create_client(session, event_data->conn); list_add_tail(&ci->conn.list, &server_data->conn_list); attr.user_context = ci; xio_modify_connection(event_data->conn, &attr, XIO_CONNECTION_ATTR_USER_CTX); xio_context_stop_loop(xio_get_main_ctx()); break; case XIO_SESSION_CONNECTION_TEARDOWN_EVENT: server_data->nr_conn--; sd_assert(0 <= server_data->nr_conn); xio_connection_destroy(event_data->conn); xio_context_stop_loop(xio_get_main_ctx()); break; case XIO_SESSION_TEARDOWN_EVENT: xio_session_destroy(session); xio_context_stop_loop(xio_get_main_ctx()); break; default: break; }; return 0; }
static void msg_finalize(struct sd_req *hdr, void *data, struct xio_msg *xrsp) { struct xio_vmsg *pimsg = &xrsp->in; struct xio_iovec_ex *isglist = vmsg_sglist(pimsg); int nents = vmsg_sglist_nents(pimsg); sd_assert(xrsp->in.header.iov_len == sizeof(struct sd_rsp)); memcpy(hdr, xrsp->in.header.iov_base, sizeof(*hdr)); if (data) { int total = 0; for (int i = 0; i < nents; i++) { memcpy((char *)data + total, isglist[i].iov_base, isglist[i].iov_len); total += isglist[i].iov_len; } } xio_release_response(xrsp); }
int default_update_epoch(uint32_t epoch) { sd_assert(epoch); return for_each_object_in_wd(check_stale_objects, false, &epoch); }
static u8 sd_send_command( u16 cmd, void *arg, void* resp ) { u8 i, tmp; // Prefix with an ACMD? if( cmd & 0x0100 ) { tmp = sd_send_command( CMD55_APP_CMD, NULL, NULL ); if( tmp != SD_ERR_OK ) return( tmp ); } // Select SD card sd_assert(); // Send command spi_txrx( ( ( ( u8 )cmd ) & 0x3F ) | 0x40 ); // Send arguments if( arg ) { spi_txrx( *( ( ( u8* )arg ) + 3 ) ); spi_txrx( *( ( ( u8* )arg ) + 2 ) ); spi_txrx( *( ( ( u8* )arg ) + 1 ) ); spi_txrx( *( ( ( u8* )arg ) + 0 ) ); } else { spi_txrx( 0 ); spi_txrx( 0 ); spi_txrx( 0 ); spi_txrx( 0 ); } // CRC, ignored for all commands except reset - where it is always 0x95 spi_txrx( 0x95 ); // Read first response byte with timeout i = 0; do { tmp = spi_txrx( CMD_IDLE ); i++; } while( ( tmp & 0x80 ) != 0 && i < SD_CMD_TIMEOUT ); // Bail if timed out if( ( tmp & 0x80 ) != 0 ) { sd_deassert(); return( SD_ERR_TIMEOUT ); } switch( cmd ) { case CMD12_STOP_TRANSMISSION: i = R1b; break; case CMD8_SEND_IF_COND: i = R7; break; case CMD58_READ_OCR: i = R3; break; case CMD9_SEND_CSD: case CMD10_SEND_CID: i = R1 + 16 + 2; break; default: i = R1; } // Read remaining response data while( i-- ) { if( resp ) ( ( u8* )resp )[ i ] = tmp; tmp = spi_txrx( CMD_IDLE ); } // Deselect card sd_deassert(); // All seems to be in order return( SD_ERR_OK ); }