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

4.104.114.95
Last change on this file since 57df51f was 3735f08, checked in by Chris Johns <chrisj@…>, on 07/29/08 at 02:23:48

2008-07-29 Chris Johns <chrisj@…>

  • libchip/i2c/spi-sd-card.c: Updated to the libblock changes.
  • libchip/ide/ata.c: Change to use a mutex rather than disable pre-emption. Updated to the libblock changes.
  • libchip/ide/ata_internal.h: Updated to the new chains API.
  • libchip/ide/ide_controller.c: Updated to the libblock changes. Added come debug tracing.
  • libchip/ide/ide_ctrl_cfg.h, libchip/ide/ide_ctrl_io.h: Updated to the libblock changes.
  • Property mode set to 100644
File size: 33.0 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) | ((uint16_t) 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++ = v >> 8;
50        *s   = v;
51}
52
53static inline void sd_card_put_uint32( uint32_t v, uint8_t *s)
54{
55        *s++ = v >> 24;
56        *s++ = v >> 16;
57        *s++ = v >> 8;
58        *s   = 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] = 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) ((csd) [2])
172#define SD_CARD_CSD_GET_TRAN_SPEED( csd) ((csd) [3])
173#define SD_CARD_CSD_GET_C_SIZE( csd) ((((csd) [6] & 0x3) << 10) + ((csd) [7] << 2) + (((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) ((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 = 1 << (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 = 1 << 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        ac = (ac * (uint64_t) transfer_speed) / 8000000000ULL;
287        uint32_t n = SD_CARD_CSD_GET_NSAC( csd) * 100;
288        return n + 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 = { rd_buf : e->response, wr_buf : e->command, byte_cnt : SD_CARD_COMMAND_SIZE };
334        int r = 0;
335
336        SD_CARD_INVALIDATE_RESPONSE_INDEX( e);
337
338        /* Wait until card is not busy */
339        rv = sd_card_wait( e);
340        CHECK_RV( rv, "Wait");
341
342        /* Write command and read response */
343        SD_CARD_COMMAND_SET_COMMAND( e->command, command);
344        SD_CARD_COMMAND_SET_ARGUMENT( e->command, argument);
345        rv = rtems_libi2c_ioctl( e->minor, RTEMS_LIBI2C_IOCTL_READ_WRITE, &rw);
346        CHECK_RV( rv, "Write command and read response");
347
348        /* Check respose */
349        for (r = SD_CARD_COMMAND_RESPONSE_START; r < SD_CARD_COMMAND_SIZE; ++r) {
350                DEBUG_PRINT( "Token [%02u]: 0x%02x\n", r, e->response [r]);
351                e->response_index = r;
352                if (SD_CARD_IS_RESPONSE( e->response [r])) {
353                        if (SD_CARD_IS_ERRORLESS_RESPONSE( e->response [r])) {
354                                return 0;
355                        } else {
356                                SYSLOG_ERROR( "Command error [%02i]: 0x%02" PRIx8 "\n", r, e->response [r]);
357                                goto sd_card_send_command_error;
358                        }
359                } else if (e->response [r] != SD_CARD_IDLE_TOKEN) {
360                        SYSLOG_ERROR( "Unexpected token [%02i]: 0x%02" PRIx8 "\n", r, e->response [r]);
361                        goto sd_card_send_command_error;
362                }
363        }
364
365        SYSLOG_ERROR( "Timeout\n");
366
367sd_card_send_command_error:
368
369        SYSLOG_ERROR( "Response:");
370        for (r = 0; r < SD_CARD_COMMAND_SIZE; ++r) {
371                if (e->response_index == r) {
372                        SYSLOG_PRINT( " %02" PRIx8 ":[%02" PRIx8 "]", e->command [r], e->response [r]);
373                } else {
374                        SYSLOG_PRINT( " %02" PRIx8 ":%02" PRIx8 "", e->command [r], e->response [r]);
375                }
376        }
377        SYSLOG_PRINT( "\n");
378
379        return -RTEMS_IO_ERROR;
380}
381
382static int sd_card_stop_multiple_block_read( sd_card_driver_entry *e)
383{
384        int rv = 0;
385
386        SD_CARD_COMMAND_SET_COMMAND( e->command, SD_CARD_CMD_STOP_TRANSMISSION);
387        rv = rtems_libi2c_write_bytes( e->minor, e->command, SD_CARD_COMMAND_SIZE);
388        CHECK_RV( rv, "Write stop transfer token");
389
390        return 0;
391}
392
393static int sd_card_stop_multiple_block_write( sd_card_driver_entry *e)
394{
395        int rv = 0;
396        uint8_t stop_transfer [3] = { SD_CARD_IDLE_TOKEN, SD_CARD_STOP_TRANSFER_MULTIPLE_BLOCK_WRITE, SD_CARD_IDLE_TOKEN };
397
398        /* Wait until card is not busy */
399        rv = sd_card_wait( e);
400        CHECK_RV( rv, "Wait");
401
402        /* Send stop token */
403        rv = rtems_libi2c_write_bytes( e->minor, stop_transfer, 3);
404        CHECK_RV( rv, "Write stop transfer token");
405
406        /* Card is now busy */
407        e->busy = true;
408
409        return 0;
410}
411
412static int sd_card_read( sd_card_driver_entry *e, uint8_t start_token, uint8_t *in, int n)
413{
414        int rv = 0;
415
416        /* Access time idle tokens */
417        uint32_t n_ac = 1;
418
419        /* Discard command response */
420        int r = e->response_index + 1;
421
422        /* Minimum token number before data start */
423        int next_response_size = 2;
424
425        /* Standard response size */
426        int response_size = SD_CARD_COMMAND_SIZE;
427
428        /* Data input index */
429        int i = 0;
430
431        SD_CARD_INVALIDATE_RESPONSE_INDEX( e);
432
433        while (1) {
434                DEBUG_PRINT( "Search from %u to %u\n", r, response_size - 1);
435
436                /* Search the data start token in in current response buffer */
437                while (r < response_size) {
438                        DEBUG_PRINT( "Token [%02u]: 0x%02x\n", r, e->response [r]);
439                        if (n_ac > e->n_ac_max) {
440                                SYSLOG_ERROR( "Timeout\n");
441                                return -RTEMS_IO_ERROR;
442                        } else if (e->response [r] == start_token) {
443                                /* Discard data start token */
444                                ++r;
445                                goto sd_card_read_start;
446                        } else if (SD_CARD_IS_DATA_ERROR( e->response [r])) {
447                                SYSLOG_ERROR( "Data error token [%02i]: 0x%02" PRIx8 "\n", r, e->response [r]);
448                                return -RTEMS_IO_ERROR;
449                        } else if (e->response [r] != SD_CARD_IDLE_TOKEN) {
450                                SYSLOG_ERROR( "Unexpected token [%02i]: 0x%02" PRIx8 "\n", r, e->response [r]);
451                                return -RTEMS_IO_ERROR;
452                        }
453                        ++n_ac;
454                        ++r;
455                }
456
457                /* Query more */
458                rv = sd_card_query( e, e->response, next_response_size);
459                CHECK_RV( rv, "Query data start token");
460
461                /* Set standard query size */
462                response_size = next_response_size;
463                next_response_size = SD_CARD_COMMAND_SIZE;
464
465                /* Reset start position */
466                r = 0;
467        }
468
469sd_card_read_start:
470
471        /* Read data */
472        while (r < response_size && i < n) {
473                in [i++] = e->response [r++];
474        }
475
476        /* Read more data? */
477        if (i < n) {
478                rv = sd_card_query( e, &in [i], n - i);
479                CHECK_RV( rv, "Read data");
480                i += rv;
481        }
482
483        /* Read CRC 16 and N_RC */
484        rv = sd_card_query( e, e->response, 3);
485        CHECK_RV( rv, "Read CRC 16");
486
487        return i;
488}
489
490static int sd_card_write( sd_card_driver_entry *e, uint8_t start_token, uint8_t *out, int n)
491{
492        int rv = 0;
493        uint8_t crc16 [2] = { 0, 0 };
494
495        /* Data output index */
496        int o = 0;
497
498        /* Wait until card is not busy */
499        rv = sd_card_wait( e);
500        CHECK_RV( rv, "Wait");
501
502        /* Write data start token */
503        rv = rtems_libi2c_write_bytes( e->minor, &start_token, 1);
504        CHECK_RV( rv, "Write data start token");
505
506        /* Write data */
507        o = rtems_libi2c_write_bytes( e->minor, out, n);
508        CHECK_RV( o, "Write data");
509
510        /* Write CRC 16 */
511        rv = rtems_libi2c_write_bytes( e->minor, crc16, 2);
512        CHECK_RV( rv, "Write CRC 16");
513
514        /* Read data response */
515        rv = sd_card_query( e, e->response, 2);
516        CHECK_RV( rv, "Read data response");
517        if (SD_CARD_IS_DATA_REJECTED( e->response [0])) {
518                SYSLOG_ERROR( "Data rejected: 0x%02" PRIx8 "\n", e->response [0]);
519                return -RTEMS_IO_ERROR;
520        }
521
522        /* Card is now busy */
523        e->busy = true;
524
525        return o;
526}
527
528static inline rtems_status_code sd_card_start( sd_card_driver_entry *e)
529{
530        rtems_status_code sc = RTEMS_SUCCESSFUL;
531        int rv = 0;
532
533        sc = rtems_libi2c_send_start( e->minor);
534        CHECK_SC( sc, "Send start");
535
536        rv = rtems_libi2c_ioctl( e->minor, RTEMS_LIBI2C_IOCTL_SET_TFRMODE, &e->transfer_mode);
537        CHECK_RVSC( rv, "Set transfer mode");
538
539        sc = rtems_libi2c_send_addr( e->minor, 1);
540        CHECK_SC( sc, "Send address");
541
542        return RTEMS_SUCCESSFUL;
543}
544
545static inline rtems_status_code sd_card_stop( sd_card_driver_entry *e)
546{
547        rtems_status_code sc = RTEMS_SUCCESSFUL;
548
549        sc = rtems_libi2c_send_stop( e->minor);
550        CHECK_SC( sc, "Send stop");
551
552        return RTEMS_SUCCESSFUL;
553}
554/** @} */
555
556/**
557 * @name Disk Driver Functions
558 * @{
559 */
560
561static int sd_card_disk_block_read( sd_card_driver_entry *e, rtems_blkdev_request *r)
562{
563        rtems_status_code sc = RTEMS_SUCCESSFUL;
564        int rv = 0;
565        uint32_t start_address = r->start << e->block_size_shift;
566        uint32_t i = 0;
567
568        DEBUG_PRINT( "start = %u, count = %u, bufnum = %u\n", r->start, r->count, r->bufnum);
569
570#ifdef DEBUG
571        /* Check request */
572        if (r->count != r->bufnum) {
573                SYSLOG_ERROR( "Block count and buffer number are not equal");
574                return -RTEMS_INTERNAL_ERROR;
575        } else if (r->start >= e->block_number) {
576                SYSLOG_ERROR( "Start block number out of range");
577                return -RTEMS_INTERNAL_ERROR;
578        } else if (r->count > e->block_number - r->start) {
579                SYSLOG_ERROR( "Block count out of range");
580                return -RTEMS_INTERNAL_ERROR;
581        }
582#endif /* DEBUG */
583
584        /* Start */
585        sc = sd_card_start( e);
586        CLEANUP_SCRV( sc, rv, sd_card_disk_block_read_cleanup, "Start");
587
588        if (r->count == 1) {
589#ifdef DEBUG
590                /* Check buffer */
591                if (r->bufs [0].length != e->block_size) {
592                        DO_CLEANUP_RV( -RTEMS_INTERNAL_ERROR, rv, sd_card_disk_block_read_cleanup, "Buffer and disk block size are not equal");
593                }
594                DEBUG_PRINT( "[%02u]: buffer = 0x%08x, size = %u\n", 0, r->bufs [0].buffer, r->bufs [0].length);
595#endif /* DEBUG */
596
597                /* Single block read */
598                rv = sd_card_send_command( e, SD_CARD_CMD_READ_SINGLE_BLOCK, start_address);
599                CLEANUP_RV( rv, sd_card_disk_block_read_cleanup, "Send: SD_CARD_CMD_READ_SINGLE_BLOCK");
600                rv = sd_card_read( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_READ, (uint8_t *) r->bufs [0].buffer, e->block_size);
601                CLEANUP_RV( rv, sd_card_disk_block_read_cleanup, "Read: SD_CARD_CMD_READ_SINGLE_BLOCK");
602        } else {
603                /* Start multiple block read */
604                rv = sd_card_send_command( e, SD_CARD_CMD_READ_MULTIPLE_BLOCK, start_address);
605                CLEANUP_RV( rv, sd_card_disk_block_read_stop_cleanup, "Send: SD_CARD_CMD_READ_MULTIPLE_BLOCK");
606
607                /* Multiple block read */
608                for (i = 0; i < r->count; ++i) {
609#ifdef DEBUG
610                        /* Check buffer */
611                        if (r->bufs [i].length != e->block_size) {
612                                DO_CLEANUP_RV( -RTEMS_INTERNAL_ERROR, rv, sd_card_disk_block_read_stop_cleanup, "Buffer and disk block size are not equal");
613                        }
614                        DEBUG_PRINT( "[%02u]: buffer = 0x%08x, size = %u\n", i, r->bufs [i].buffer, r->bufs [i].length);
615#endif /* DEBUG */
616
617                        rv = sd_card_read( e, SD_CARD_START_BLOCK_MULTIPLE_BLOCK_READ, (uint8_t *) r->bufs [i].buffer, e->block_size);
618                        CLEANUP_RV( rv, sd_card_disk_block_read_stop_cleanup, "Read block");
619                }
620
621                /* Stop multiple block read */
622                rv = sd_card_stop_multiple_block_read( e);
623                CLEANUP_RV( rv, sd_card_disk_block_read_cleanup, "Stop multiple block read");
624        }
625
626        /* Stop */
627        sc = sd_card_stop( e);
628        CHECK_SCRV( sc, "Stop");
629
630        /* Done */
631        r->req_done( r->done_arg, RTEMS_SUCCESSFUL, 0);
632
633        return 0;
634
635sd_card_disk_block_read_stop_cleanup:
636
637        /* Stop multiple block read */
638        sd_card_stop_multiple_block_read( e);
639
640sd_card_disk_block_read_cleanup:
641
642        /* Stop */
643        sd_card_stop( e);
644
645        /* Done */
646        r->req_done( r->done_arg, RTEMS_IO_ERROR, 0);
647
648        return rv;
649}
650
651static int sd_card_disk_block_write( sd_card_driver_entry *e, rtems_blkdev_request *r)
652{
653        rtems_status_code sc = RTEMS_SUCCESSFUL;
654        int rv = 0;
655        uint32_t start_address = r->start << e->block_size_shift;
656        uint32_t i = 0;
657
658        DEBUG_PRINT( "start = %u, count = %u, bufnum = %u\n", r->start, r->count, r->bufnum);
659
660#ifdef DEBUG
661        /* Check request */
662        if (r->count != r->bufnum) {
663                SYSLOG_ERROR( "Block count and buffer number are not equal");
664                return -RTEMS_INTERNAL_ERROR;
665        } else if (r->start >= e->block_number) {
666                SYSLOG_ERROR( "Start block number out of range");
667                return -RTEMS_INTERNAL_ERROR;
668        } else if (r->count > e->block_number - r->start) {
669                SYSLOG_ERROR( "Block count out of range");
670                return -RTEMS_INTERNAL_ERROR;
671        }
672#endif /* DEBUG */
673
674        /* Start */
675        sc = sd_card_start( e);
676        CLEANUP_SCRV( sc, rv, sd_card_disk_block_write_cleanup, "Start");
677
678        if (r->count == 1) {
679#ifdef DEBUG
680                /* Check buffer */
681                if (r->bufs [0].length != e->block_size) {
682                        DO_CLEANUP_RV( -RTEMS_INTERNAL_ERROR, rv, sd_card_disk_block_write_cleanup, "Buffer and disk block size are not equal");
683                }
684                DEBUG_PRINT( "[%02u]: buffer = 0x%08x, size = %u\n", 0, r->bufs [0].buffer, r->bufs [0].length);
685#endif /* DEBUG */
686
687                /* Single block write */
688                rv = sd_card_send_command( e, SD_CARD_CMD_WRITE_BLOCK, start_address);
689                CLEANUP_RV( rv, sd_card_disk_block_write_cleanup, "Send: SD_CARD_CMD_WRITE_BLOCK");
690                rv = sd_card_write( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_WRITE, (uint8_t *) r->bufs [0].buffer, e->block_size);
691                CLEANUP_RV( rv, sd_card_disk_block_write_cleanup, "Write: SD_CARD_CMD_WRITE_BLOCK");
692        } else {
693                /* Start multiple block write */
694                rv = sd_card_send_command( e, SD_CARD_CMD_WRITE_MULTIPLE_BLOCK, start_address);
695                CLEANUP_RV( rv, sd_card_disk_block_write_stop_cleanup, "Send: SD_CARD_CMD_WRITE_MULTIPLE_BLOCK");
696
697                /* Multiple block write */
698                for (i = 0; i < r->count; ++i) {
699#ifdef DEBUG
700                        /* Check buffer */
701                        if (r->bufs [i].length != e->block_size) {
702                                DO_CLEANUP_RV( -RTEMS_INTERNAL_ERROR, rv, sd_card_disk_block_write_stop_cleanup, "Buffer and disk block size are not equal");
703                        }
704                        DEBUG_PRINT( "[%02u]: buffer = 0x%08x, size = %u\n", i, r->bufs [i].buffer, r->bufs [i].length);
705#endif /* DEBUG */
706
707                        rv = sd_card_write( e, SD_CARD_START_BLOCK_MULTIPLE_BLOCK_WRITE, (uint8_t *) r->bufs [i].buffer, e->block_size);
708                        CLEANUP_RV( rv, sd_card_disk_block_write_stop_cleanup, "Write block");
709                }
710
711                /* Stop multiple block write */
712                rv = sd_card_stop_multiple_block_write( e);
713                CLEANUP_RV( rv, sd_card_disk_block_write_cleanup, "Stop multiple block write");
714        }
715
716        /* Get card status */
717        rv = sd_card_send_command( e, SD_CARD_CMD_SEND_STATUS, 0);
718        CHECK_RV( rv, "Send: SD_CARD_CMD_SEND_STATUS");
719
720        /* Stop */
721        sc = sd_card_stop( e);
722        CHECK_SCRV( sc, "Stop");
723
724        /* Done */
725        r->req_done( r->done_arg, RTEMS_SUCCESSFUL, 0);
726
727        return 0;
728
729sd_card_disk_block_write_stop_cleanup:
730
731        /* Stop multiple block write */
732        sd_card_stop_multiple_block_write( e);
733
734sd_card_disk_block_write_cleanup:
735
736        /* Get card status */
737        rv = sd_card_send_command( e, SD_CARD_CMD_SEND_STATUS, 0);
738        CHECK_RV( rv, "Send: SD_CARD_CMD_SEND_STATUS");
739
740        /* Stop */
741        sd_card_stop( e);
742
743        /* Done */
744        r->req_done( r->done_arg, RTEMS_IO_ERROR, 0);
745
746        return rv;
747}
748
749static int sd_card_disk_ioctl( dev_t dev, uint32_t req, void *arg)
750{
751        DEBUG_PRINT( "dev = %u, req = %u, arg = 0x08%x\n", dev, req, arg);
752        if (req == RTEMS_BLKIO_REQUEST) {
753                rtems_device_minor_number minor = rtems_filesystem_dev_minor_t( dev);
754                sd_card_driver_entry *e = &sd_card_driver_table [minor];
755                rtems_blkdev_request *r = (rtems_blkdev_request *) arg;
756                switch (r->req) {
757                        case RTEMS_BLKDEV_REQ_READ:
758                                return sd_card_disk_block_read( e, r);
759                        case RTEMS_BLKDEV_REQ_WRITE:
760                                return sd_card_disk_block_write( e, r);
761                        default:
762                                errno = EBADRQC;
763                                return -1;
764                }
765        } else {
766                errno = EBADRQC;
767                return -1;
768        }
769}
770
771static rtems_status_code sd_card_disk_init( rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
772{
773        /* Do nothing */
774
775        return RTEMS_SUCCESSFUL;
776}
777
778/** @} */
779
780static const rtems_driver_address_table sd_card_disk_ops = {
781        .initialization_entry = sd_card_disk_init,
782        .open_entry = NULL,
783        .close_entry = NULL,
784        .read_entry = NULL,
785        .write_entry = NULL,
786        .control_entry = NULL
787};
788
789static rtems_device_major_number sd_card_disk_major = 0;
790
791static int sd_card_driver_first = 1;
792
793/**
794 * @name LibI2C Driver Functions
795 * @{
796 */
797
798static inline int sd_card_driver_get_entry( rtems_device_minor_number minor, sd_card_driver_entry **e)
799{
800        return rtems_libi2c_ioctl( minor, RTEMS_LIBI2C_IOCTL_GET_DRV_T, e);
801}
802
803static rtems_status_code sd_card_driver_init( rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
804{
805        rtems_status_code sc = RTEMS_SUCCESSFUL;
806        int rv = 0;
807        sd_card_driver_entry *e = NULL;
808        uint8_t block [SD_CARD_BLOCK_SIZE_DEFAULT];
809        uint32_t transfer_speed = 0;
810        uint32_t read_block_size = 0;
811        uint32_t write_block_size = 0;
812        dev_t dev = 0;
813
814        /* Get driver entry */
815        rv = sd_card_driver_get_entry( minor, &e);
816        CHECK_RVSC( rv, "Get driver entry");
817
818        /* Start */
819        sc = sd_card_start( e);
820        CLEANUP_SC( sc, sd_card_driver_init_cleanup, "Start");
821
822        /* Save minor number for disk operations */
823        e->minor = minor;
824
825        /* Register disk driver */
826        if (sd_card_driver_first) {
827                sd_card_driver_first = 0;
828                sc = rtems_io_register_driver( 0, &sd_card_disk_ops, &sd_card_disk_major);
829                CLEANUP_SC( sc, sd_card_driver_init_cleanup, "Register disk IO driver");
830        }
831
832        /* Wait until card is not busy */
833        rv = sd_card_wait( e);
834        CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Wait");
835
836        /* Send idle tokens for at least 74 clock cycles with active chip select */
837        memset( block, SD_CARD_IDLE_TOKEN, SD_CARD_BLOCK_SIZE_DEFAULT);
838        rv = rtems_libi2c_write_bytes( e->minor, block, SD_CARD_BLOCK_SIZE_DEFAULT);
839        CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Active chip select delay");
840
841        /* Stop */
842        sc = sd_card_stop( e);
843        CHECK_SC( sc, "Stop");
844
845        /* Start with inactive chip select */
846        sc = rtems_libi2c_send_start( e->minor);
847        CHECK_SC( sc, "Send start");
848
849        /* Set transfer mode */
850        rv = rtems_libi2c_ioctl( e->minor, RTEMS_LIBI2C_IOCTL_SET_TFRMODE, &e->transfer_mode);
851        CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Set transfer mode");
852
853        /* Send idle tokens with inactive chip select */
854        rv = sd_card_query( e, e->response, SD_CARD_COMMAND_SIZE);
855        CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Inactive chip select delay");
856
857        /* Activate chip select */
858        sc = rtems_libi2c_send_addr( e->minor, 1);
859        CLEANUP_SC( sc, sd_card_driver_init_cleanup, "Send address");
860
861        /* Stop multiple block write */
862        sd_card_stop_multiple_block_write( e);
863
864        /* Get card status */
865        sd_card_send_command( e, SD_CARD_CMD_SEND_STATUS, 0);
866
867        /* Stop multiple block read */
868        sd_card_stop_multiple_block_read( e);
869
870        /* Switch to SPI mode */
871        rv = sd_card_send_command( e, SD_CARD_CMD_GO_IDLE_STATE, 0);
872        CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_CMD_GO_IDLE_STATE");
873
874        /* Initialize card */
875        while (1) {
876                rv = sd_card_send_command( e, SD_CARD_CMD_APP_CMD, 0);
877                CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_CMD_APP_CMD");
878                rv = sd_card_send_command( e, SD_CARD_ACMD_SD_SEND_OP_COND, 0);
879                CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_ACMD_SD_SEND_OP_COND");
880       
881                /* Not idle? */
882                if (SD_CARD_IS_NOT_IDLE_RESPONSE( e->response [e->response_index])) {
883                        break;
884                }
885
886                /* Invoke the scheduler */
887                rtems_task_wake_after( RTEMS_YIELD_PROCESSOR);
888        };
889
890        /* Card Identification */
891        if (e->verbose) {
892                rv = sd_card_send_command( e, SD_CARD_CMD_SEND_CID, 0);
893                CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_CMD_SEND_CID");
894                rv = sd_card_read( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_READ, block, SD_CARD_CID_SIZE);
895                CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Read: SD_CARD_CMD_SEND_CID");
896                SYSLOG( "*** Card Identification ***\n");
897                SYSLOG( "Manufacturer ID          : %" PRIu8 "\n", SD_CARD_CID_GET_MID( block));
898                SYSLOG( "OEM/Application ID       : %" PRIu16 "\n", SD_CARD_CID_GET_OID( block));
899                SYSLOG(
900                        "Product name             : %c%c%c%c%c%c\n",
901                        SD_CARD_CID_GET_PNM( block, 0),
902                        SD_CARD_CID_GET_PNM( block, 1),
903                        SD_CARD_CID_GET_PNM( block, 2),
904                        SD_CARD_CID_GET_PNM( block, 3),
905                        SD_CARD_CID_GET_PNM( block, 4),
906                        SD_CARD_CID_GET_PNM( block, 5)
907                );
908                SYSLOG( "Product revision         : %" PRIu8 "\n", SD_CARD_CID_GET_PRV( block));
909                SYSLOG( "Product serial number    : %" PRIu32 "\n", SD_CARD_CID_GET_PSN( block));
910                SYSLOG( "Manufacturing date       : %" PRIu8 "\n", SD_CARD_CID_GET_MDT( block));
911                SYSLOG( "7-bit CRC checksum       : %" PRIu8 "\n",  SD_CARD_CID_GET_CRC7( block));
912        }
913
914        /* Card Specific Data */
915        rv = sd_card_send_command( e, SD_CARD_CMD_SEND_CSD, 0);
916        CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_CMD_SEND_CSD");
917        rv = sd_card_read( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_READ, block, SD_CARD_CSD_SIZE);
918        CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Read: SD_CARD_CMD_SEND_CSD");
919        transfer_speed = sd_card_transfer_speed( block);
920        e->transfer_mode.baudrate = transfer_speed;
921        e->n_ac_max = sd_card_max_access_time( block, transfer_speed);
922        read_block_size = 1 << SD_CARD_CSD_GET_READ_BLK_LEN( block);
923        e->block_size_shift = SD_CARD_CSD_GET_READ_BLK_LEN( block);
924        write_block_size = 1 << e->block_size_shift;
925        if (read_block_size < write_block_size) {
926                SYSLOG_ERROR( "Read block size smaller than write block size\n");
927                return -RTEMS_IO_ERROR;
928        }
929        e->block_size = write_block_size;
930        e->block_number = sd_card_block_number( block);
931        if (e->verbose) {
932                SYSLOG( "*** Card Specific Data ***\n");
933                SYSLOG( "CSD structure            : %" PRIu8 "\n", SD_CARD_CSD_GET_CSD_STRUCTURE( block));
934                SYSLOG( "Spec version             : %" PRIu8 "\n", SD_CARD_CSD_GET_SPEC_VERS( block));
935                SYSLOG( "Access time [ns]         : %" PRIu32 "\n", sd_card_access_time( block));
936                SYSLOG( "Max access time [N]      : %" PRIu32 "\n", e->n_ac_max);
937                SYSLOG( "Max read block size [B]  : %" PRIu32 "\n", read_block_size);
938                SYSLOG( "Max write block size [B] : %" PRIu32 "\n", write_block_size);
939                SYSLOG( "Block size [B]           : %" PRIu32 "\n", e->block_size);
940                SYSLOG( "Block number             : %" PRIu32 "\n", e->block_number);
941                SYSLOG( "Capacity [B]             : %" PRIu32 "\n", sd_card_capacity( block));
942                SYSLOG( "Max transfer speed [b/s] : %" PRIu32 "\n", transfer_speed);
943        }
944
945        /* Set read block size */
946        rv = sd_card_send_command( e, SD_CARD_CMD_SET_BLOCKLEN, e->block_size);
947        CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_CMD_SET_BLOCKLEN");
948
949        /* Create disk device */
950        dev = rtems_filesystem_make_dev_t( sd_card_disk_major, e->table_index);
951        sc = rtems_disk_io_initialize();
952        CLEANUP_SC( sc, sd_card_driver_init_cleanup, "Initialize RTEMS disk IO");
953        sc = rtems_disk_create_phys( dev, e->block_size, e->block_number, sd_card_disk_ioctl, e->disk_device_name);
954        CLEANUP_SC( sc, sd_card_driver_init_cleanup, "Create disk device");
955
956        /* Stop */
957        sc = sd_card_stop( e);
958        CHECK_SC( sc, "Stop");
959
960        return RTEMS_SUCCESSFUL;
961
962sd_card_driver_init_cleanup:
963
964        /* Stop */
965        sd_card_stop( e);
966
967        return sc;
968}
969
970static rtems_status_code sd_card_driver_read( rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
971{
972        rtems_status_code sc = RTEMS_SUCCESSFUL;
973        int rv = 0;
974        rtems_libio_rw_args_t *rw = (rtems_libio_rw_args_t *) arg;
975        sd_card_driver_entry *e = NULL;
976        uint32_t block_size_mask = 0;
977        uint32_t block_count = 0;
978        uint32_t start_block = 0;
979        uint32_t i = 0;
980
981        /* Clear moved bytes counter */
982        rw->bytes_moved = 0;
983
984        /* Get driver entry */
985        rv = sd_card_driver_get_entry( minor, &e);
986        CHECK_RVSC( rv, "Get driver entry");
987
988        /* Start */
989        sc = sd_card_start( e);
990        CLEANUP_SC( sc, sd_card_driver_read_cleanup, "Start");
991
992        /* Check arguments */
993        block_size_mask = e->block_size - 1;
994        block_count = rw->count >> e->block_size_shift;
995        start_block = rw->offset >> e->block_size_shift;
996        if (rw->offset & block_size_mask) {
997                DO_CLEANUP_SC( RTEMS_INVALID_ADDRESS, sc, sd_card_driver_read_cleanup, "Invalid offset");
998        } else if ((rw->count & block_size_mask) || (start_block >= e->block_number) || (block_count > e->block_number - start_block)) {
999                DO_CLEANUP_SC( RTEMS_INVALID_NUMBER, sc, sd_card_driver_read_cleanup, "Invalid count or out of range");
1000        }
1001
1002        if (block_count == 0) {
1003                /* Do nothing */
1004        } else if (block_count == 1) {
1005                /* Single block read */
1006                rv = sd_card_send_command( e, SD_CARD_CMD_READ_SINGLE_BLOCK, rw->offset);
1007                CLEANUP_RVSC( rv, sc, sd_card_driver_read_cleanup, "Send: SD_CARD_CMD_READ_SINGLE_BLOCK");
1008                rv = sd_card_read( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_READ, (uint8_t *) rw->buffer, e->block_size);
1009                CLEANUP_RVSC( rv, sc, sd_card_driver_read_cleanup, "Read: SD_CARD_CMD_READ_SINGLE_BLOCK");
1010
1011                /* Set moved bytes counter */
1012                rw->bytes_moved = rv;
1013        } else {
1014                /* Start multiple block read */
1015                rv = sd_card_send_command( e, SD_CARD_CMD_READ_MULTIPLE_BLOCK, rw->offset);
1016                CLEANUP_RVSC( rv, sc, sd_card_driver_read_stop_cleanup, "Send: SD_CARD_CMD_READ_MULTIPLE_BLOCK");
1017
1018                /* Multiple block read */
1019                for (i = 0; i < block_count; ++i) {
1020                        rv = sd_card_read( e, SD_CARD_START_BLOCK_MULTIPLE_BLOCK_READ, (uint8_t *) rw->buffer + (i << e->block_size_shift), e->block_size);
1021                        CLEANUP_RVSC( rv, sc, sd_card_driver_read_stop_cleanup, "Read block");
1022
1023                        /* Update moved bytes counter */
1024                        rw->bytes_moved += rv;
1025                }
1026
1027                /* Stop multiple block read */
1028                rv = sd_card_stop_multiple_block_read( e);
1029                CLEANUP_RVSC( rv, sc, sd_card_driver_read_cleanup, "Stop multiple block read");
1030        }
1031
1032        /* Stop */
1033        sc = sd_card_stop( e);
1034        CHECK_SC( sc, "Stop");
1035
1036        return RTEMS_SUCCESSFUL;
1037
1038sd_card_driver_read_stop_cleanup:
1039
1040        /* Stop multiple block read */
1041        sd_card_stop_multiple_block_read( e);
1042
1043sd_card_driver_read_cleanup:
1044
1045        /* Stop */
1046        sd_card_stop( e);
1047
1048        return sc;
1049}
1050
1051static rtems_status_code sd_card_driver_write( rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
1052{
1053        rtems_status_code sc = RTEMS_SUCCESSFUL;
1054        int rv = 0;
1055        rtems_libio_rw_args_t *rw = (rtems_libio_rw_args_t *) arg;
1056        sd_card_driver_entry *e = NULL;
1057        uint32_t block_size_mask = 0;
1058        uint32_t block_count = 0;
1059        uint32_t start_block = 0;
1060        uint32_t i = 0;
1061
1062        /* Clear moved bytes counter */
1063        rw->bytes_moved = 0;
1064
1065        /* Get driver entry */
1066        rv = sd_card_driver_get_entry( minor, &e);
1067        CHECK_RVSC( rv, "Get driver entry");
1068
1069        /* Start */
1070        sc = sd_card_start( e);
1071        CLEANUP_SC( sc, sd_card_driver_write_cleanup, "Start");
1072
1073        /* Check arguments */
1074        block_size_mask = e->block_size - 1;
1075        block_count = rw->count >> e->block_size_shift;
1076        start_block = rw->offset >> e->block_size_shift;
1077        if (rw->offset & block_size_mask) {
1078                DO_CLEANUP_SC( RTEMS_INVALID_ADDRESS, sc, sd_card_driver_write_cleanup, "Invalid offset");
1079        } else if ((rw->count & block_size_mask) || (start_block >= e->block_number) || (block_count > e->block_number - start_block)) {
1080                DO_CLEANUP_SC( RTEMS_INVALID_NUMBER, sc, sd_card_driver_write_cleanup, "Invalid count or out of range");
1081        }
1082
1083        if (block_count == 0) {
1084                /* Do nothing */
1085        } else if (block_count == 1) {
1086                /* Single block write */
1087                rv = sd_card_send_command( e, SD_CARD_CMD_WRITE_BLOCK, rw->offset);
1088                CLEANUP_RVSC( rv, sc, sd_card_driver_write_cleanup, "Send: SD_CARD_CMD_WRITE_BLOCK");
1089                rv = sd_card_write( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_WRITE, (uint8_t *) rw->buffer, e->block_size);
1090                CLEANUP_RVSC( rv, sc, sd_card_driver_write_cleanup, "Write: SD_CARD_CMD_WRITE_BLOCK");
1091
1092                /* Set moved bytes counter */
1093                rw->bytes_moved = rv;
1094        } else {
1095                /* Start multiple block write */
1096                rv = sd_card_send_command( e, SD_CARD_CMD_WRITE_MULTIPLE_BLOCK, rw->offset);
1097                CLEANUP_RVSC( rv, sc, sd_card_driver_write_stop_cleanup, "Send: SD_CARD_CMD_WRITE_MULTIPLE_BLOCK");
1098
1099                /* Multiple block write */
1100                for (i = 0; i < block_count; ++i) {
1101                        rv = sd_card_write( e, SD_CARD_START_BLOCK_MULTIPLE_BLOCK_WRITE, (uint8_t *) rw->buffer + (i << e->block_size_shift), e->block_size);
1102                        CLEANUP_RVSC( rv, sc, sd_card_driver_write_stop_cleanup, "Write: SD_CARD_CMD_WRITE_MULTIPLE_BLOCK");
1103
1104                        /* Update moved bytes counter */
1105                        rw->bytes_moved += rv;
1106                }
1107
1108                /* Stop multiple block write */
1109                rv = sd_card_stop_multiple_block_write( e);
1110                CLEANUP_RVSC( rv, sc, sd_card_driver_write_cleanup, "Stop multiple block write");
1111        }
1112
1113        /* Get card status */
1114        rv = sd_card_send_command( e, SD_CARD_CMD_SEND_STATUS, 0);
1115        CHECK_RV( rv, "Send: SD_CARD_CMD_SEND_STATUS");
1116
1117        /* Stop */
1118        sc = sd_card_stop( e);
1119        CHECK_SC( sc, "Stop");
1120
1121        return RTEMS_SUCCESSFUL;
1122
1123sd_card_driver_write_stop_cleanup:
1124
1125        /* Stop multiple block write */
1126        sd_card_stop_multiple_block_write( e);
1127
1128sd_card_driver_write_cleanup:
1129
1130        /* Get card status */
1131        rv = sd_card_send_command( e, SD_CARD_CMD_SEND_STATUS, 0);
1132        CHECK_RV( rv, "Send: SD_CARD_CMD_SEND_STATUS");
1133
1134        /* Stop */
1135        sd_card_stop( e);
1136
1137        return sc;
1138}
1139
1140/** @} */
1141
1142const rtems_driver_address_table sd_card_driver_ops = {
1143        .initialization_entry = sd_card_driver_init,
1144        .open_entry = NULL,
1145        .close_entry = NULL,
1146        .read_entry = sd_card_driver_read,
1147        .write_entry = sd_card_driver_write,
1148        .control_entry = NULL
1149};
Note: See TracBrowser for help on using the repository browser.