source: rtems/c/src/libchip/i2c/spi-sd-card.c @ dccd351

4.104.114.9
Last change on this file since dccd351 was dccd351, checked in by Joel Sherrill <joel.sherrill@…>, on Aug 20, 2008 at 5:30:07 PM

2008-08-20 Sebastian Huber <sebastian.huber@…>

  • libchip/i2c/spi-sd-card.c: Fixed integer conversion warnings.
  • Property mode set to 100644
File size: 33.3 KB
Line 
1/**
2 * @file
3 *
4 * @brief SD Card LibI2C driver.
5 */
6
7/*
8 * Copyright (c) 2008
9 * Embedded Brains GmbH
10 * Obere Lagerstr. 30
11 * D-82178 Puchheim
12 * Germany
13 * rtems@embedded-brains.de
14 *
15 * The license and distribution terms for this file may be found in the file
16 * LICENSE in this distribution or at http://www.rtems.com/license/LICENSE.
17 */
18
19#include <stdio.h>
20#include <errno.h>
21#include <inttypes.h>
22
23#include <rtems.h>
24#include <rtems/libi2c.h>
25#include <rtems/libio.h>
26#include <rtems/diskdevs.h>
27
28#include <libchip/spi-sd-card.h>
29
30#include <rtems/status-checks.h>
31
32/**
33 * @name Integer to and from Byte-Stream Converter
34 * @{
35 */
36
37static inline uint16_t sd_card_get_uint16( const uint8_t *s)
38{
39        return (uint16_t) ((s [0] << 8) | s [1]);
40}
41
42static inline uint32_t sd_card_get_uint32( const uint8_t *s)
43{
44        return ((uint32_t) s [0] << 24) | ((uint32_t) s [1] << 16) | ((uint32_t) s [2] << 8) | (uint32_t) s [3];
45}
46
47static inline void sd_card_put_uint16( uint16_t v, uint8_t *s)
48{
49        *s++ = (uint8_t) (v >> 8);
50        *s   = (uint8_t) (v);
51}
52
53static inline void sd_card_put_uint32( uint32_t v, uint8_t *s)
54{
55        *s++ = (uint8_t) (v >> 24);
56        *s++ = (uint8_t) (v >> 16);
57        *s++ = (uint8_t) (v >> 8);
58        *s   = (uint8_t) (v);
59}
60
61/** @} */
62
63#define SD_CARD_BUSY_TOKEN 0
64
65#define SD_CARD_BLOCK_SIZE_DEFAULT 512
66
67#define SD_CARD_COMMAND_RESPONSE_START 7
68
69/**
70 * @name Commands
71 * @{
72 */
73
74#define SD_CARD_CMD_GO_IDLE_STATE 0
75#define SD_CARD_CMD_SEND_OP_COND 1
76#define SD_CARD_CMD_SEND_CSD 9
77#define SD_CARD_CMD_SEND_CID 10
78#define SD_CARD_CMD_STOP_TRANSMISSION 12
79#define SD_CARD_CMD_SEND_STATUS 13
80#define SD_CARD_CMD_SET_BLOCKLEN 16
81#define SD_CARD_CMD_READ_SINGLE_BLOCK 17
82#define SD_CARD_CMD_READ_MULTIPLE_BLOCK 18
83#define SD_CARD_CMD_SET_BLOCK_COUNT 23
84#define SD_CARD_CMD_WRITE_BLOCK 24
85#define SD_CARD_CMD_WRITE_MULTIPLE_BLOCK 25
86#define SD_CARD_CMD_PROGRAM_CSD 27
87#define SD_CARD_CMD_SET_WRITE_PROT 28
88#define SD_CARD_CMD_CLR_WRITE_PROT 29
89#define SD_CARD_CMD_SEND_WRITE_PROT 30
90#define SD_CARD_CMD_TAG_SECTOR_START 32
91#define SD_CARD_CMD_TAG_SECTOR_END 33
92#define SD_CARD_CMD_UNTAG_SECTOR 34
93#define SD_CARD_CMD_TAG_ERASE_GROUP_START 35
94#define SD_CARD_CMD_TAG_ERASE_GROUP_END 36
95#define SD_CARD_CMD_UNTAG_ERASE_GROUP 37
96#define SD_CARD_CMD_ERASE 38
97#define SD_CARD_CMD_LOCK_UNLOCK 42
98#define SD_CARD_CMD_APP_CMD 55
99#define SD_CARD_CMD_GEN_CND 56
100#define SD_CARD_CMD_READ_OCR 58
101#define SD_CARD_CMD_CRC_ON_OFF 59
102
103/** @} */
104
105/**
106 * @name Application Commands
107 * @{
108 */
109
110#define SD_CARD_ACMD_SD_SEND_OP_COND 41
111
112/** @} */
113
114/**
115 * @name Command Fields
116 * @{
117 */
118
119#define SD_CARD_COMMAND_SET_COMMAND( c, cmd) (c) [1] = (uint8_t) (0x40 + ((cmd) & 0x3f))
120#define SD_CARD_COMMAND_SET_ARGUMENT( c, arg) sd_card_put_uint32( (arg), &((c) [2]))
121#define SD_CARD_COMMAND_SET_CRC7( c, crc7) ((c) [6] = (crc7) << 1)
122
123#define SD_CARD_COMMAND_GET_CRC7( c) ((c) [6] >> 1)
124
125/** @} */
126
127/**
128 * @name Response Fields
129 * @{
130 */
131
132#define SD_CARD_IS_RESPONSE( r) (((r) & 0x80) == 0)
133
134#define SD_CARD_IS_ERRORLESS_RESPONSE( r) (((r) & 0x7e) == 0)
135
136#define SD_CARD_IS_NOT_IDLE_RESPONSE( r) (((r) & 0x81) == 0)
137
138#define SD_CARD_IS_DATA_ERROR( r) (((r) & 0xe0) == 0)
139
140#define SD_CARD_IS_DATA_REJECTED( r) (((r) & 0x1f) != 0x05)
141
142/** @} */
143
144/**
145 * @name Card Identification
146 * @{
147 */
148
149#define SD_CARD_CID_SIZE 16
150
151#define SD_CARD_CID_GET_MID( cid) ((cid) [0])
152#define SD_CARD_CID_GET_OID( cid) sd_card_get_uint16( cid + 1)
153#define SD_CARD_CID_GET_PNM( cid, i) ((char) (cid) [3 + (i)])
154#define SD_CARD_CID_GET_PRV( cid) ((cid) [9])
155#define SD_CARD_CID_GET_PSN( cid) sd_card_get_uint32( cid + 10)
156#define SD_CARD_CID_GET_MDT( cid) ((cid) [14])
157#define SD_CARD_CID_GET_CRC7( cid) ((cid) [15] >> 1)
158
159/** @} */
160
161/**
162 * @name Card Specific Data
163 * @{
164 */
165
166#define SD_CARD_CSD_SIZE 16
167
168#define SD_CARD_CSD_GET_CSD_STRUCTURE( csd) ((csd) [0] >> 6)
169#define SD_CARD_CSD_GET_SPEC_VERS( csd) (((csd) [0] >> 2) & 0xf)
170#define SD_CARD_CSD_GET_TAAC( csd) ((csd) [1])
171#define SD_CARD_CSD_GET_NSAC( csd) ((uint32_t) (csd) [2])
172#define SD_CARD_CSD_GET_TRAN_SPEED( csd) ((csd) [3])
173#define SD_CARD_CSD_GET_C_SIZE( csd) ((((uint32_t) (csd) [6] & 0x3) << 10) + ((uint32_t) (csd) [7] << 2) + (((uint32_t) (csd) [8] >> 6) & 0x3))
174#define SD_CARD_CSD_GET_C_SIZE_MULT( csd) ((((csd) [9] & 0x3) << 1) + (((csd) [10] >> 7) & 0x1))
175#define SD_CARD_CSD_GET_READ_BLK_LEN( csd) ((uint32_t) (csd) [5] & 0xf)
176#define SD_CARD_CSD_GET_WRITE_BLK_LEN( csd) ((((csd) [12] & 0x3) << 2) + (((csd) [13] >> 6) & 0x3))
177
178/** @} */
179
180#define SD_CARD_INVALIDATE_RESPONSE_INDEX( e) e->response_index = SD_CARD_COMMAND_SIZE
181
182/**
183 * @name Data Start and Stop Tokens
184 * @{
185 */
186
187#define SD_CARD_START_BLOCK_SINGLE_BLOCK_READ 0xfe
188#define SD_CARD_START_BLOCK_MULTIPLE_BLOCK_READ 0xfe
189#define SD_CARD_START_BLOCK_SINGLE_BLOCK_WRITE 0xfe
190#define SD_CARD_START_BLOCK_MULTIPLE_BLOCK_WRITE 0xfc
191#define SD_CARD_STOP_TRANSFER_MULTIPLE_BLOCK_WRITE 0xfd
192
193/** @} */
194
195/**
196 * @name Card Specific Data Functions
197 * @{
198 */
199
200static inline uint32_t sd_card_block_number( const uint8_t *csd)
201{
202        uint32_t size = SD_CARD_CSD_GET_C_SIZE( csd);
203        uint32_t mult = 1U << (SD_CARD_CSD_GET_C_SIZE_MULT( csd) + 2);
204        return (size + 1) * mult;
205}
206
207static inline uint32_t sd_card_capacity( const uint8_t *csd)
208{
209        uint32_t block_size = 1U << SD_CARD_CSD_GET_READ_BLK_LEN( csd);
210        return sd_card_block_number( csd) * block_size;
211}
212
213static inline uint32_t sd_card_transfer_speed( const uint8_t *csd)
214{
215        uint32_t s = SD_CARD_CSD_GET_TRAN_SPEED( csd);
216        uint32_t e = s & 0x7;
217        uint32_t m = s >> 3;
218        switch (e) {
219                case 0: s = 10000; break;
220                case 1: s = 100000; break;
221                case 2: s = 1000000; break;
222                case 3: s = 10000000; break;
223                default: s = 0; break;
224        }
225        switch (m) {
226                case 1: s *= 10; break;
227                case 2: s *= 12; break;
228                case 3: s *= 13; break;
229                case 4: s *= 15; break;
230                case 5: s *= 20; break;
231                case 6: s *= 25; break;
232                case 7: s *= 30; break;
233                case 8: s *= 35; break;
234                case 9: s *= 40; break;
235                case 10: s *= 45; break;
236                case 11: s *= 50; break;
237                case 12: s *= 55; break;
238                case 13: s *= 60; break;
239                case 14: s *= 70; break;
240                case 15: s *= 80; break;
241                default: s *= 0; break;
242        }
243        return s;
244}
245
246static inline uint32_t sd_card_access_time( const uint8_t *csd)
247{
248        uint32_t ac = SD_CARD_CSD_GET_TAAC( csd);
249        uint32_t e = ac & 0x7;
250        uint32_t m = ac >> 3;
251        switch (e) {
252                case 0: ac = 1; break;
253                case 1: ac = 10; break;
254                case 2: ac = 100; break;
255                case 3: ac = 1000; break;
256                case 4: ac = 10000; break;
257                case 5: ac = 100000; break;
258                case 6: ac = 1000000; break;
259                case 7: ac = 10000000; break;
260                default: ac = 0; break;
261        }
262        switch (m) {
263                case 1: ac *= 10; break;
264                case 2: ac *= 12; break;
265                case 3: ac *= 13; break;
266                case 4: ac *= 15; break;
267                case 5: ac *= 20; break;
268                case 6: ac *= 25; break;
269                case 7: ac *= 30; break;
270                case 8: ac *= 35; break;
271                case 9: ac *= 40; break;
272                case 10: ac *= 45; break;
273                case 11: ac *= 50; break;
274                case 12: ac *= 55; break;
275                case 13: ac *= 60; break;
276                case 14: ac *= 70; break;
277                case 15: ac *= 80; break;
278                default: ac *= 0; break;
279        }
280        return ac / 10;
281}
282
283static inline uint32_t sd_card_max_access_time( const uint8_t *csd, uint32_t transfer_speed)
284{
285        uint64_t ac = sd_card_access_time( csd);
286        uint32_t n = SD_CARD_CSD_GET_NSAC( csd) * 100;
287        ac = (ac * transfer_speed) / 8000000000ULL;
288        return n + (uint32_t) ac;
289}
290
291/** @} */
292
293/**
294 * @name Communication Functions
295 * @{
296 */
297
298static inline int sd_card_query( sd_card_driver_entry *e, uint8_t *in, int n)
299{
300        return rtems_libi2c_read_bytes( e->minor, in, n);
301}
302
303static int sd_card_wait( sd_card_driver_entry *e)
304{
305        int rv = 0;
306        int r = 0;
307        int n = 2;
308        while (e->busy) {
309                /* Query busy tokens */
310                rv = sd_card_query( e, e->response, n);
311                CHECK_RV( rv, "Busy");
312
313                /* Search for non busy tokens */
314                for (r = 0; r < n; ++r) {
315                        if (e->response [r] != SD_CARD_BUSY_TOKEN) {
316                                e->busy = false;
317                                return 0;
318                        }
319                }
320                n = SD_CARD_COMMAND_SIZE;
321
322                if (e->schedule_if_busy) {
323                        /* Invoke the scheduler */
324                        rtems_task_wake_after( RTEMS_YIELD_PROCESSOR);
325                }
326        }
327        return 0;
328}
329
330static int sd_card_send_command( sd_card_driver_entry *e, uint32_t command, uint32_t argument)
331{
332        int rv = 0;
333        rtems_libi2c_read_write_t rw = {
334                .rd_buf = e->response,
335                .wr_buf = e->command,
336                .byte_cnt = SD_CARD_COMMAND_SIZE
337        };
338        int r = 0;
339
340        SD_CARD_INVALIDATE_RESPONSE_INDEX( e);
341
342        /* Wait until card is not busy */
343        rv = sd_card_wait( e);
344        CHECK_RV( rv, "Wait");
345
346        /* Write command and read response */
347        SD_CARD_COMMAND_SET_COMMAND( e->command, command);
348        SD_CARD_COMMAND_SET_ARGUMENT( e->command, argument);
349        rv = rtems_libi2c_ioctl( e->minor, RTEMS_LIBI2C_IOCTL_READ_WRITE, &rw);
350        CHECK_RV( rv, "Write command and read response");
351
352        /* Check respose */
353        for (r = SD_CARD_COMMAND_RESPONSE_START; r < SD_CARD_COMMAND_SIZE; ++r) {
354                DEBUG_PRINT( "Token [%02u]: 0x%02x\n", r, e->response [r]);
355                e->response_index = r;
356                if (SD_CARD_IS_RESPONSE( e->response [r])) {
357                        if (SD_CARD_IS_ERRORLESS_RESPONSE( e->response [r])) {
358                                return 0;
359                        } else {
360                                SYSLOG_ERROR( "Command error [%02i]: 0x%02" PRIx8 "\n", r, e->response [r]);
361                                goto sd_card_send_command_error;
362                        }
363                } else if (e->response [r] != SD_CARD_IDLE_TOKEN) {
364                        SYSLOG_ERROR( "Unexpected token [%02i]: 0x%02" PRIx8 "\n", r, e->response [r]);
365                        goto sd_card_send_command_error;
366                }
367        }
368
369        SYSLOG_ERROR( "Timeout\n");
370
371sd_card_send_command_error:
372
373        SYSLOG_ERROR( "Response:");
374        for (r = 0; r < SD_CARD_COMMAND_SIZE; ++r) {
375                if (e->response_index == r) {
376                        SYSLOG_PRINT( " %02" PRIx8 ":[%02" PRIx8 "]", e->command [r], e->response [r]);
377                } else {
378                        SYSLOG_PRINT( " %02" PRIx8 ":%02" PRIx8 "", e->command [r], e->response [r]);
379                }
380        }
381        SYSLOG_PRINT( "\n");
382
383        return -RTEMS_IO_ERROR;
384}
385
386static int sd_card_stop_multiple_block_read( sd_card_driver_entry *e)
387{
388        int rv = 0;
389
390        SD_CARD_COMMAND_SET_COMMAND( e->command, SD_CARD_CMD_STOP_TRANSMISSION);
391        rv = rtems_libi2c_write_bytes( e->minor, e->command, SD_CARD_COMMAND_SIZE);
392        CHECK_RV( rv, "Write stop transfer token");
393
394        return 0;
395}
396
397static int sd_card_stop_multiple_block_write( sd_card_driver_entry *e)
398{
399        int rv = 0;
400        uint8_t stop_transfer [3] = { SD_CARD_IDLE_TOKEN, SD_CARD_STOP_TRANSFER_MULTIPLE_BLOCK_WRITE, SD_CARD_IDLE_TOKEN };
401
402        /* Wait until card is not busy */
403        rv = sd_card_wait( e);
404        CHECK_RV( rv, "Wait");
405
406        /* Send stop token */
407        rv = rtems_libi2c_write_bytes( e->minor, stop_transfer, 3);
408        CHECK_RV( rv, "Write stop transfer token");
409
410        /* Card is now busy */
411        e->busy = true;
412
413        return 0;
414}
415
416static int sd_card_read( sd_card_driver_entry *e, uint8_t start_token, uint8_t *in, int n)
417{
418        int rv = 0;
419
420        /* Access time idle tokens */
421        uint32_t n_ac = 1;
422
423        /* Discard command response */
424        int r = e->response_index + 1;
425
426        /* Minimum token number before data start */
427        int next_response_size = 2;
428
429        /* Standard response size */
430        int response_size = SD_CARD_COMMAND_SIZE;
431
432        /* Data input index */
433        int i = 0;
434
435        SD_CARD_INVALIDATE_RESPONSE_INDEX( e);
436
437        while (1) {
438                DEBUG_PRINT( "Search from %u to %u\n", r, response_size - 1);
439
440                /* Search the data start token in in current response buffer */
441                while (r < response_size) {
442                        DEBUG_PRINT( "Token [%02u]: 0x%02x\n", r, e->response [r]);
443                        if (n_ac > e->n_ac_max) {
444                                SYSLOG_ERROR( "Timeout\n");
445                                return -RTEMS_IO_ERROR;
446                        } else if (e->response [r] == start_token) {
447                                /* Discard data start token */
448                                ++r;
449                                goto sd_card_read_start;
450                        } else if (SD_CARD_IS_DATA_ERROR( e->response [r])) {
451                                SYSLOG_ERROR( "Data error token [%02i]: 0x%02" PRIx8 "\n", r, e->response [r]);
452                                return -RTEMS_IO_ERROR;
453                        } else if (e->response [r] != SD_CARD_IDLE_TOKEN) {
454                                SYSLOG_ERROR( "Unexpected token [%02i]: 0x%02" PRIx8 "\n", r, e->response [r]);
455                                return -RTEMS_IO_ERROR;
456                        }
457                        ++n_ac;
458                        ++r;
459                }
460
461                /* Query more */
462                rv = sd_card_query( e, e->response, next_response_size);
463                CHECK_RV( rv, "Query data start token");
464
465                /* Set standard query size */
466                response_size = next_response_size;
467                next_response_size = SD_CARD_COMMAND_SIZE;
468
469                /* Reset start position */
470                r = 0;
471        }
472
473sd_card_read_start:
474
475        /* Read data */
476        while (r < response_size && i < n) {
477                in [i++] = e->response [r++];
478        }
479
480        /* Read more data? */
481        if (i < n) {
482                rv = sd_card_query( e, &in [i], n - i);
483                CHECK_RV( rv, "Read data");
484                i += rv;
485        }
486
487        /* Read CRC 16 and N_RC */
488        rv = sd_card_query( e, e->response, 3);
489        CHECK_RV( rv, "Read CRC 16");
490
491        return i;
492}
493
494static int sd_card_write( sd_card_driver_entry *e, uint8_t start_token, uint8_t *out, int n)
495{
496        int rv = 0;
497        uint8_t crc16 [2] = { 0, 0 };
498
499        /* Data output index */
500        int o = 0;
501
502        /* Wait until card is not busy */
503        rv = sd_card_wait( e);
504        CHECK_RV( rv, "Wait");
505
506        /* Write data start token */
507        rv = rtems_libi2c_write_bytes( e->minor, &start_token, 1);
508        CHECK_RV( rv, "Write data start token");
509
510        /* Write data */
511        o = rtems_libi2c_write_bytes( e->minor, out, n);
512        CHECK_RV( o, "Write data");
513
514        /* Write CRC 16 */
515        rv = rtems_libi2c_write_bytes( e->minor, crc16, 2);
516        CHECK_RV( rv, "Write CRC 16");
517
518        /* Read data response */
519        rv = sd_card_query( e, e->response, 2);
520        CHECK_RV( rv, "Read data response");
521        if (SD_CARD_IS_DATA_REJECTED( e->response [0])) {
522                SYSLOG_ERROR( "Data rejected: 0x%02" PRIx8 "\n", e->response [0]);
523                return -RTEMS_IO_ERROR;
524        }
525
526        /* Card is now busy */
527        e->busy = true;
528
529        return o;
530}
531
532static inline rtems_status_code sd_card_start( sd_card_driver_entry *e)
533{
534        rtems_status_code sc = RTEMS_SUCCESSFUL;
535        int rv = 0;
536
537        sc = rtems_libi2c_send_start( e->minor);
538        CHECK_SC( sc, "Send start");
539
540        rv = rtems_libi2c_ioctl( e->minor, RTEMS_LIBI2C_IOCTL_SET_TFRMODE, &e->transfer_mode);
541        CHECK_RVSC( rv, "Set transfer mode");
542
543        sc = rtems_libi2c_send_addr( e->minor, 1);
544        CHECK_SC( sc, "Send address");
545
546        return RTEMS_SUCCESSFUL;
547}
548
549static inline rtems_status_code sd_card_stop( sd_card_driver_entry *e)
550{
551        rtems_status_code sc = RTEMS_SUCCESSFUL;
552
553        sc = rtems_libi2c_send_stop( e->minor);
554        CHECK_SC( sc, "Send stop");
555
556        return RTEMS_SUCCESSFUL;
557}
558/** @} */
559
560/**
561 * @name Disk Driver Functions
562 * @{
563 */
564
565static int sd_card_disk_block_read( sd_card_driver_entry *e, rtems_blkdev_request *r)
566{
567        rtems_status_code sc = RTEMS_SUCCESSFUL;
568        int rv = 0;
569        uint32_t start_address = RTEMS_BLKDEV_START_BLOCK (r) << e->block_size_shift;
570        uint32_t i = 0;
571
572        DEBUG_PRINT( "start = %u, bufnum = %u\n", r->start, r->bufnum);
573
574#ifdef DEBUG
575        /* Check request */
576  if (r->bufs[0].block >= e->block_number) {
577                SYSLOG_ERROR( "Start block number out of range");
578                return -RTEMS_INTERNAL_ERROR;
579        } else if (r->bufnum > e->block_number - RTEMS_BLKDEV_START_BLOCK (r)) {
580                SYSLOG_ERROR( "Block count out of range");
581                return -RTEMS_INTERNAL_ERROR;
582        }
583#endif /* DEBUG */
584
585        /* Start */
586        sc = sd_card_start( e);
587        CLEANUP_SCRV( sc, rv, sd_card_disk_block_read_cleanup, "Start");
588
589        if (r->bufnum == 1) {
590#ifdef DEBUG
591                /* Check buffer */
592                if (r->bufs [0].length != e->block_size) {
593                        DO_CLEANUP_RV( -RTEMS_INTERNAL_ERROR, rv, sd_card_disk_block_read_cleanup, "Buffer and disk block size are not equal");
594                }
595                DEBUG_PRINT( "[%02u]: buffer = 0x%08x, size = %u\n", 0, r->bufs [0].buffer, r->bufs [0].length);
596#endif /* DEBUG */
597
598                /* Single block read */
599                rv = sd_card_send_command( e, SD_CARD_CMD_READ_SINGLE_BLOCK, start_address);
600                CLEANUP_RV( rv, sd_card_disk_block_read_cleanup, "Send: SD_CARD_CMD_READ_SINGLE_BLOCK");
601                rv = sd_card_read( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_READ, (uint8_t *) r->bufs [0].buffer, (int) e->block_size);
602                CLEANUP_RV( rv, sd_card_disk_block_read_cleanup, "Read: SD_CARD_CMD_READ_SINGLE_BLOCK");
603        } else {
604                /* Start multiple block read */
605                rv = sd_card_send_command( e, SD_CARD_CMD_READ_MULTIPLE_BLOCK, start_address);
606                CLEANUP_RV( rv, sd_card_disk_block_read_stop_cleanup, "Send: SD_CARD_CMD_READ_MULTIPLE_BLOCK");
607
608                /* Multiple block read */
609                for (i = 0; i < r->bufnum; ++i) {
610#ifdef DEBUG
611                        /* Check buffer */
612                        if (r->bufs [i].length != e->block_size) {
613                                DO_CLEANUP_RV( -RTEMS_INTERNAL_ERROR, rv, sd_card_disk_block_read_stop_cleanup, "Buffer and disk block size are not equal");
614                        }
615                        DEBUG_PRINT( "[%02u]: buffer = 0x%08x, size = %u\n", i, r->bufs [i].buffer, r->bufs [i].length);
616#endif /* DEBUG */
617
618                        rv = sd_card_read( e, SD_CARD_START_BLOCK_MULTIPLE_BLOCK_READ, (uint8_t *) r->bufs [i].buffer, (int) e->block_size);
619                        CLEANUP_RV( rv, sd_card_disk_block_read_stop_cleanup, "Read block");
620                }
621
622                /* Stop multiple block read */
623                rv = sd_card_stop_multiple_block_read( e);
624                CLEANUP_RV( rv, sd_card_disk_block_read_cleanup, "Stop multiple block read");
625        }
626
627        /* Stop */
628        sc = sd_card_stop( e);
629        CHECK_SCRV( sc, "Stop");
630
631        /* Done */
632        r->req_done( r->done_arg, RTEMS_SUCCESSFUL, 0);
633
634        return 0;
635
636sd_card_disk_block_read_stop_cleanup:
637
638        /* Stop multiple block read */
639        sd_card_stop_multiple_block_read( e);
640
641sd_card_disk_block_read_cleanup:
642
643        /* Stop */
644        sd_card_stop( e);
645
646        /* Done */
647        r->req_done( r->done_arg, RTEMS_IO_ERROR, 0);
648
649        return rv;
650}
651
652static int sd_card_disk_block_write( sd_card_driver_entry *e, rtems_blkdev_request *r)
653{
654        rtems_status_code sc = RTEMS_SUCCESSFUL;
655        int rv = 0;
656        uint32_t start_address = RTEMS_BLKDEV_START_BLOCK (r) << e->block_size_shift;
657        uint32_t i = 0;
658
659        DEBUG_PRINT( "start = %u, count = %u, bufnum = %u\n", r->start, r->count, r->bufnum);
660
661#ifdef DEBUG
662        /* Check request */
663  if (r->bufs[0].block >= e->block_number) {
664                SYSLOG_ERROR( "Start block number out of range");
665                return -RTEMS_INTERNAL_ERROR;
666        } else if (r->bufnum > e->block_number - RTEMS_BLKDEV_START_BLOCK (r)) {
667                SYSLOG_ERROR( "Block count out of range");
668                return -RTEMS_INTERNAL_ERROR;
669        }
670#endif /* DEBUG */
671
672        /* Start */
673        sc = sd_card_start( e);
674        CLEANUP_SCRV( sc, rv, sd_card_disk_block_write_cleanup, "Start");
675
676        if (r->bufnum == 1) {
677#ifdef DEBUG
678                /* Check buffer */
679                if (r->bufs [0].length != e->block_size) {
680                        DO_CLEANUP_RV( -RTEMS_INTERNAL_ERROR, rv, sd_card_disk_block_write_cleanup, "Buffer and disk block size are not equal");
681                }
682                DEBUG_PRINT( "[%02u]: buffer = 0x%08x, size = %u\n", 0, r->bufs [0].buffer, r->bufs [0].length);
683#endif /* DEBUG */
684
685                /* Single block write */
686                rv = sd_card_send_command( e, SD_CARD_CMD_WRITE_BLOCK, start_address);
687                CLEANUP_RV( rv, sd_card_disk_block_write_cleanup, "Send: SD_CARD_CMD_WRITE_BLOCK");
688                rv = sd_card_write( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_WRITE, (uint8_t *) r->bufs [0].buffer, (int) e->block_size);
689                CLEANUP_RV( rv, sd_card_disk_block_write_cleanup, "Write: SD_CARD_CMD_WRITE_BLOCK");
690        } else {
691                /* Start multiple block write */
692                rv = sd_card_send_command( e, SD_CARD_CMD_WRITE_MULTIPLE_BLOCK, start_address);
693                CLEANUP_RV( rv, sd_card_disk_block_write_stop_cleanup, "Send: SD_CARD_CMD_WRITE_MULTIPLE_BLOCK");
694
695                /* Multiple block write */
696                for (i = 0; i < r->bufnum; ++i) {
697#ifdef DEBUG
698                        /* Check buffer */
699                        if (r->bufs [i].length != e->block_size) {
700                                DO_CLEANUP_RV( -RTEMS_INTERNAL_ERROR, rv, sd_card_disk_block_write_stop_cleanup, "Buffer and disk block size are not equal");
701                        }
702                        DEBUG_PRINT( "[%02u]: buffer = 0x%08x, size = %u\n", i, r->bufs [i].buffer, r->bufs [i].length);
703#endif /* DEBUG */
704
705                        rv = sd_card_write( e, SD_CARD_START_BLOCK_MULTIPLE_BLOCK_WRITE, (uint8_t *) r->bufs [i].buffer, (int) e->block_size);
706                        CLEANUP_RV( rv, sd_card_disk_block_write_stop_cleanup, "Write block");
707                }
708
709                /* Stop multiple block write */
710                rv = sd_card_stop_multiple_block_write( e);
711                CLEANUP_RV( rv, sd_card_disk_block_write_cleanup, "Stop multiple block write");
712        }
713
714        /* Get card status */
715        rv = sd_card_send_command( e, SD_CARD_CMD_SEND_STATUS, 0);
716        CHECK_RV( rv, "Send: SD_CARD_CMD_SEND_STATUS");
717
718        /* Stop */
719        sc = sd_card_stop( e);
720        CHECK_SCRV( sc, "Stop");
721
722        /* Done */
723        r->req_done( r->done_arg, RTEMS_SUCCESSFUL, 0);
724
725        return 0;
726
727sd_card_disk_block_write_stop_cleanup:
728
729        /* Stop multiple block write */
730        sd_card_stop_multiple_block_write( e);
731
732sd_card_disk_block_write_cleanup:
733
734        /* Get card status */
735        rv = sd_card_send_command( e, SD_CARD_CMD_SEND_STATUS, 0);
736        CHECK_RV( rv, "Send: SD_CARD_CMD_SEND_STATUS");
737
738        /* Stop */
739        sd_card_stop( e);
740
741        /* Done */
742        r->req_done( r->done_arg, RTEMS_IO_ERROR, 0);
743
744        return rv;
745}
746
747static int sd_card_disk_ioctl( dev_t dev, uint32_t req, void *arg)
748{
749        DEBUG_PRINT( "dev = %u, req = %u, arg = 0x08%x\n", dev, req, arg);
750        if (req == RTEMS_BLKIO_REQUEST) {
751                rtems_device_minor_number minor = rtems_filesystem_dev_minor_t( dev);
752                sd_card_driver_entry *e = &sd_card_driver_table [minor];
753                rtems_blkdev_request *r = (rtems_blkdev_request *) arg;
754                switch (r->req) {
755                        case RTEMS_BLKDEV_REQ_READ:
756                                return sd_card_disk_block_read( e, r);
757                        case RTEMS_BLKDEV_REQ_WRITE:
758                                return sd_card_disk_block_write( e, r);
759                        case RTEMS_BLKDEV_CAPABILITIES:
760                                *((uint32_t*) arg)  = RTEMS_BLKDEV_CAP_MULTISECTOR_CONT;
761                                return 0;
762                        default:
763                                errno = EBADRQC;
764                                return -1;
765                }
766        } else {
767                errno = EBADRQC;
768                return -1;
769        }
770}
771
772static rtems_status_code sd_card_disk_init( rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
773{
774        /* Do nothing */
775
776        return RTEMS_SUCCESSFUL;
777}
778
779/** @} */
780
781static const rtems_driver_address_table sd_card_disk_ops = {
782        .initialization_entry = sd_card_disk_init,
783        .open_entry = NULL,
784        .close_entry = NULL,
785        .read_entry = NULL,
786        .write_entry = NULL,
787        .control_entry = NULL
788};
789
790static rtems_device_major_number sd_card_disk_major = 0;
791
792static int sd_card_driver_first = 1;
793
794/**
795 * @name LibI2C Driver Functions
796 * @{
797 */
798
799static inline int sd_card_driver_get_entry( rtems_device_minor_number minor, sd_card_driver_entry **e)
800{
801        return rtems_libi2c_ioctl( minor, RTEMS_LIBI2C_IOCTL_GET_DRV_T, e);
802}
803
804static rtems_status_code sd_card_driver_init( rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
805{
806        rtems_status_code sc = RTEMS_SUCCESSFUL;
807        int rv = 0;
808        sd_card_driver_entry *e = NULL;
809        uint8_t block [SD_CARD_BLOCK_SIZE_DEFAULT];
810        uint32_t transfer_speed = 0;
811        uint32_t read_block_size = 0;
812        uint32_t write_block_size = 0;
813        dev_t dev = 0;
814
815        /* Get driver entry */
816        rv = sd_card_driver_get_entry( minor, &e);
817        CHECK_RVSC( rv, "Get driver entry");
818
819        /* Start */
820        sc = sd_card_start( e);
821        CLEANUP_SC( sc, sd_card_driver_init_cleanup, "Start");
822
823        /* Save minor number for disk operations */
824        e->minor = minor;
825
826        /* Register disk driver */
827        if (sd_card_driver_first) {
828                sd_card_driver_first = 0;
829                sc = rtems_io_register_driver( 0, &sd_card_disk_ops, &sd_card_disk_major);
830                CLEANUP_SC( sc, sd_card_driver_init_cleanup, "Register disk IO driver");
831        }
832
833        /* Wait until card is not busy */
834        rv = sd_card_wait( e);
835        CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Wait");
836
837        /* Send idle tokens for at least 74 clock cycles with active chip select */
838        memset( block, SD_CARD_IDLE_TOKEN, SD_CARD_BLOCK_SIZE_DEFAULT);
839        rv = rtems_libi2c_write_bytes( e->minor, block, SD_CARD_BLOCK_SIZE_DEFAULT);
840        CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Active chip select delay");
841
842        /* Stop */
843        sc = sd_card_stop( e);
844        CHECK_SC( sc, "Stop");
845
846        /* Start with inactive chip select */
847        sc = rtems_libi2c_send_start( e->minor);
848        CHECK_SC( sc, "Send start");
849
850        /* Set transfer mode */
851        rv = rtems_libi2c_ioctl( e->minor, RTEMS_LIBI2C_IOCTL_SET_TFRMODE, &e->transfer_mode);
852        CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Set transfer mode");
853
854        /* Send idle tokens with inactive chip select */
855        rv = sd_card_query( e, e->response, SD_CARD_COMMAND_SIZE);
856        CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Inactive chip select delay");
857
858        /* Activate chip select */
859        sc = rtems_libi2c_send_addr( e->minor, 1);
860        CLEANUP_SC( sc, sd_card_driver_init_cleanup, "Send address");
861
862        /* Stop multiple block write */
863        sd_card_stop_multiple_block_write( e);
864
865        /* Get card status */
866        sd_card_send_command( e, SD_CARD_CMD_SEND_STATUS, 0);
867
868        /* Stop multiple block read */
869        sd_card_stop_multiple_block_read( e);
870
871        /* Switch to SPI mode */
872        rv = sd_card_send_command( e, SD_CARD_CMD_GO_IDLE_STATE, 0);
873        CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_CMD_GO_IDLE_STATE");
874
875        /* Initialize card */
876        while (1) {
877                rv = sd_card_send_command( e, SD_CARD_CMD_APP_CMD, 0);
878                CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_CMD_APP_CMD");
879                rv = sd_card_send_command( e, SD_CARD_ACMD_SD_SEND_OP_COND, 0);
880                CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_ACMD_SD_SEND_OP_COND");
881       
882                /* Not idle? */
883                if (SD_CARD_IS_NOT_IDLE_RESPONSE( e->response [e->response_index])) {
884                        break;
885                }
886
887                /* Invoke the scheduler */
888                rtems_task_wake_after( RTEMS_YIELD_PROCESSOR);
889        };
890
891        /* Card Identification */
892        if (e->verbose) {
893                rv = sd_card_send_command( e, SD_CARD_CMD_SEND_CID, 0);
894                CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_CMD_SEND_CID");
895                rv = sd_card_read( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_READ, block, SD_CARD_CID_SIZE);
896                CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Read: SD_CARD_CMD_SEND_CID");
897                SYSLOG( "*** Card Identification ***\n");
898                SYSLOG( "Manufacturer ID          : %" PRIu8 "\n", SD_CARD_CID_GET_MID( block));
899                SYSLOG( "OEM/Application ID       : %" PRIu16 "\n", SD_CARD_CID_GET_OID( block));
900                SYSLOG(
901                        "Product name             : %c%c%c%c%c%c\n",
902                        SD_CARD_CID_GET_PNM( block, 0),
903                        SD_CARD_CID_GET_PNM( block, 1),
904                        SD_CARD_CID_GET_PNM( block, 2),
905                        SD_CARD_CID_GET_PNM( block, 3),
906                        SD_CARD_CID_GET_PNM( block, 4),
907                        SD_CARD_CID_GET_PNM( block, 5)
908                );
909                SYSLOG( "Product revision         : %" PRIu8 "\n", SD_CARD_CID_GET_PRV( block));
910                SYSLOG( "Product serial number    : %" PRIu32 "\n", SD_CARD_CID_GET_PSN( block));
911                SYSLOG( "Manufacturing date       : %" PRIu8 "\n", SD_CARD_CID_GET_MDT( block));
912                SYSLOG( "7-bit CRC checksum       : %" PRIu8 "\n",  SD_CARD_CID_GET_CRC7( block));
913        }
914
915        /* Card Specific Data */
916        rv = sd_card_send_command( e, SD_CARD_CMD_SEND_CSD, 0);
917        CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_CMD_SEND_CSD");
918        rv = sd_card_read( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_READ, block, SD_CARD_CSD_SIZE);
919        CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Read: SD_CARD_CMD_SEND_CSD");
920        transfer_speed = sd_card_transfer_speed( block);
921        e->transfer_mode.baudrate = transfer_speed;
922        e->n_ac_max = sd_card_max_access_time( block, transfer_speed);
923        read_block_size = 1U << SD_CARD_CSD_GET_READ_BLK_LEN( block);
924        e->block_size_shift = SD_CARD_CSD_GET_READ_BLK_LEN( block);
925        write_block_size = 1U << e->block_size_shift;
926        if (read_block_size < write_block_size) {
927                SYSLOG_ERROR( "Read block size smaller than write block size\n");
928                return -RTEMS_IO_ERROR;
929        }
930        e->block_size = write_block_size;
931        e->block_number = sd_card_block_number( block);
932        if (e->verbose) {
933                SYSLOG( "*** Card Specific Data ***\n");
934                SYSLOG( "CSD structure            : %" PRIu8 "\n", SD_CARD_CSD_GET_CSD_STRUCTURE( block));
935                SYSLOG( "Spec version             : %" PRIu8 "\n", SD_CARD_CSD_GET_SPEC_VERS( block));
936                SYSLOG( "Access time [ns]         : %" PRIu32 "\n", sd_card_access_time( block));
937                SYSLOG( "Max access time [N]      : %" PRIu32 "\n", e->n_ac_max);
938                SYSLOG( "Max read block size [B]  : %" PRIu32 "\n", read_block_size);
939                SYSLOG( "Max write block size [B] : %" PRIu32 "\n", write_block_size);
940                SYSLOG( "Block size [B]           : %" PRIu32 "\n", e->block_size);
941                SYSLOG( "Block number             : %" PRIu32 "\n", e->block_number);
942                SYSLOG( "Capacity [B]             : %" PRIu32 "\n", sd_card_capacity( block));
943                SYSLOG( "Max transfer speed [b/s] : %" PRIu32 "\n", transfer_speed);
944        }
945
946        /* Set read block size */
947        rv = sd_card_send_command( e, SD_CARD_CMD_SET_BLOCKLEN, e->block_size);
948        CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_CMD_SET_BLOCKLEN");
949
950        /* Create disk device */
951        dev = rtems_filesystem_make_dev_t( sd_card_disk_major, (rtems_device_minor_number) e->table_index);
952        sc = rtems_disk_io_initialize();
953        CLEANUP_SC( sc, sd_card_driver_init_cleanup, "Initialize RTEMS disk IO");
954        sc = rtems_disk_create_phys( dev, (int) e->block_size, (int) e->block_number, sd_card_disk_ioctl, e->disk_device_name);
955        CLEANUP_SC( sc, sd_card_driver_init_cleanup, "Create disk device");
956
957        /* Stop */
958        sc = sd_card_stop( e);
959        CHECK_SC( sc, "Stop");
960
961        return RTEMS_SUCCESSFUL;
962
963sd_card_driver_init_cleanup:
964
965        /* Stop */
966        sd_card_stop( e);
967
968        return sc;
969}
970
971static rtems_status_code sd_card_driver_read( rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
972{
973        rtems_status_code sc = RTEMS_SUCCESSFUL;
974        int rv = 0;
975        rtems_libio_rw_args_t *rw = (rtems_libio_rw_args_t *) arg;
976        sd_card_driver_entry *e = NULL;
977        uint32_t block_size_mask = 0;
978        uint32_t block_count = 0;
979        uint32_t start_block = 0;
980        uint32_t i = 0;
981
982        /* Clear moved bytes counter */
983        rw->bytes_moved = 0;
984
985        /* Get driver entry */
986        rv = sd_card_driver_get_entry( minor, &e);
987        CHECK_RVSC( rv, "Get driver entry");
988
989        /* Start */
990        sc = sd_card_start( e);
991        CLEANUP_SC( sc, sd_card_driver_read_cleanup, "Start");
992
993        /* Check arguments */
994        block_size_mask = e->block_size - 1;
995        block_count = (uint32_t) rw->count >> e->block_size_shift;
996        start_block = (uint32_t) rw->offset >> e->block_size_shift;
997        if (rw->offset & block_size_mask) {
998                DO_CLEANUP_SC( RTEMS_INVALID_ADDRESS, sc, sd_card_driver_read_cleanup, "Invalid offset");
999        } else if ((rw->count & block_size_mask) || (start_block >= e->block_number) || (block_count > e->block_number - start_block)) {
1000                DO_CLEANUP_SC( RTEMS_INVALID_NUMBER, sc, sd_card_driver_read_cleanup, "Invalid count or out of range");
1001        }
1002
1003        if (block_count == 0) {
1004                /* Do nothing */
1005        } else if (block_count == 1) {
1006                /* Single block read */
1007                rv = sd_card_send_command( e, SD_CARD_CMD_READ_SINGLE_BLOCK, (uint32_t) rw->offset);
1008                CLEANUP_RVSC( rv, sc, sd_card_driver_read_cleanup, "Send: SD_CARD_CMD_READ_SINGLE_BLOCK");
1009                rv = sd_card_read( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_READ, (uint8_t *) rw->buffer, (int) e->block_size);
1010                CLEANUP_RVSC( rv, sc, sd_card_driver_read_cleanup, "Read: SD_CARD_CMD_READ_SINGLE_BLOCK");
1011
1012                /* Set moved bytes counter */
1013                rw->bytes_moved = (uint32_t) rv;
1014        } else {
1015                /* Start multiple block read */
1016                rv = sd_card_send_command( e, SD_CARD_CMD_READ_MULTIPLE_BLOCK, (uint32_t) rw->offset);
1017                CLEANUP_RVSC( rv, sc, sd_card_driver_read_stop_cleanup, "Send: SD_CARD_CMD_READ_MULTIPLE_BLOCK");
1018
1019                /* Multiple block read */
1020                for (i = 0; i < block_count; ++i) {
1021                        rv = sd_card_read( e, SD_CARD_START_BLOCK_MULTIPLE_BLOCK_READ, (uint8_t *) rw->buffer + (i << e->block_size_shift), (int) e->block_size);
1022                        CLEANUP_RVSC( rv, sc, sd_card_driver_read_stop_cleanup, "Read block");
1023
1024                        /* Update moved bytes counter */
1025                        rw->bytes_moved += (uint32_t) rv;
1026                }
1027
1028                /* Stop multiple block read */
1029                rv = sd_card_stop_multiple_block_read( e);
1030                CLEANUP_RVSC( rv, sc, sd_card_driver_read_cleanup, "Stop multiple block read");
1031        }
1032
1033        /* Stop */
1034        sc = sd_card_stop( e);
1035        CHECK_SC( sc, "Stop");
1036
1037        return RTEMS_SUCCESSFUL;
1038
1039sd_card_driver_read_stop_cleanup:
1040
1041        /* Stop multiple block read */
1042        sd_card_stop_multiple_block_read( e);
1043
1044sd_card_driver_read_cleanup:
1045
1046        /* Stop */
1047        sd_card_stop( e);
1048
1049        return sc;
1050}
1051
1052static rtems_status_code sd_card_driver_write( rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
1053{
1054        rtems_status_code sc = RTEMS_SUCCESSFUL;
1055        int rv = 0;
1056        rtems_libio_rw_args_t *rw = (rtems_libio_rw_args_t *) arg;
1057        sd_card_driver_entry *e = NULL;
1058        uint32_t block_size_mask = 0;
1059        uint32_t block_count = 0;
1060        uint32_t start_block = 0;
1061        uint32_t i = 0;
1062
1063        /* Clear moved bytes counter */
1064        rw->bytes_moved = 0;
1065
1066        /* Get driver entry */
1067        rv = sd_card_driver_get_entry( minor, &e);
1068        CHECK_RVSC( rv, "Get driver entry");
1069
1070        /* Start */
1071        sc = sd_card_start( e);
1072        CLEANUP_SC( sc, sd_card_driver_write_cleanup, "Start");
1073
1074        /* Check arguments */
1075        block_size_mask = e->block_size - 1;
1076        block_count = (uint32_t) rw->count >> e->block_size_shift;
1077        start_block = (uint32_t) rw->offset >> e->block_size_shift;
1078        if (rw->offset & block_size_mask) {
1079                DO_CLEANUP_SC( RTEMS_INVALID_ADDRESS, sc, sd_card_driver_write_cleanup, "Invalid offset");
1080        } else if ((rw->count & block_size_mask) || (start_block >= e->block_number) || (block_count > e->block_number - start_block)) {
1081                DO_CLEANUP_SC( RTEMS_INVALID_NUMBER, sc, sd_card_driver_write_cleanup, "Invalid count or out of range");
1082        }
1083
1084        if (block_count == 0) {
1085                /* Do nothing */
1086        } else if (block_count == 1) {
1087                /* Single block write */
1088                rv = sd_card_send_command( e, SD_CARD_CMD_WRITE_BLOCK, (uint32_t) rw->offset);
1089                CLEANUP_RVSC( rv, sc, sd_card_driver_write_cleanup, "Send: SD_CARD_CMD_WRITE_BLOCK");
1090                rv = sd_card_write( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_WRITE, (uint8_t *) rw->buffer, (int) e->block_size);
1091                CLEANUP_RVSC( rv, sc, sd_card_driver_write_cleanup, "Write: SD_CARD_CMD_WRITE_BLOCK");
1092
1093                /* Set moved bytes counter */
1094                rw->bytes_moved = (uint32_t) rv;
1095        } else {
1096                /* Start multiple block write */
1097                rv = sd_card_send_command( e, SD_CARD_CMD_WRITE_MULTIPLE_BLOCK, (uint32_t) rw->offset);
1098                CLEANUP_RVSC( rv, sc, sd_card_driver_write_stop_cleanup, "Send: SD_CARD_CMD_WRITE_MULTIPLE_BLOCK");
1099
1100                /* Multiple block write */
1101                for (i = 0; i < block_count; ++i) {
1102                        rv = sd_card_write( e, SD_CARD_START_BLOCK_MULTIPLE_BLOCK_WRITE, (uint8_t *) rw->buffer + (i << e->block_size_shift), (int) e->block_size);
1103                        CLEANUP_RVSC( rv, sc, sd_card_driver_write_stop_cleanup, "Write: SD_CARD_CMD_WRITE_MULTIPLE_BLOCK");
1104
1105                        /* Update moved bytes counter */
1106                        rw->bytes_moved += (uint32_t) rv;
1107                }
1108
1109                /* Stop multiple block write */
1110                rv = sd_card_stop_multiple_block_write( e);
1111                CLEANUP_RVSC( rv, sc, sd_card_driver_write_cleanup, "Stop multiple block write");
1112        }
1113
1114        /* Get card status */
1115        rv = sd_card_send_command( e, SD_CARD_CMD_SEND_STATUS, 0);
1116        CHECK_RV( rv, "Send: SD_CARD_CMD_SEND_STATUS");
1117
1118        /* Stop */
1119        sc = sd_card_stop( e);
1120        CHECK_SC( sc, "Stop");
1121
1122        return RTEMS_SUCCESSFUL;
1123
1124sd_card_driver_write_stop_cleanup:
1125
1126        /* Stop multiple block write */
1127        sd_card_stop_multiple_block_write( e);
1128
1129sd_card_driver_write_cleanup:
1130
1131        /* Get card status */
1132        rv = sd_card_send_command( e, SD_CARD_CMD_SEND_STATUS, 0);
1133        CHECK_RV( rv, "Send: SD_CARD_CMD_SEND_STATUS");
1134
1135        /* Stop */
1136        sd_card_stop( e);
1137
1138        return sc;
1139}
1140
1141/** @} */
1142
1143const rtems_driver_address_table sd_card_driver_ops = {
1144        .initialization_entry = sd_card_driver_init,
1145        .open_entry = NULL,
1146        .close_entry = NULL,
1147        .read_entry = sd_card_driver_read,
1148        .write_entry = sd_card_driver_write,
1149        .control_entry = NULL
1150};
Note: See TracBrowser for help on using the repository browser.