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

4.104.114.9
Last change on this file since f031251c was f031251c, checked in by Chris Johns <chrisj@…>, on Aug 2, 2008 at 6:26:29 AM

2008-08-02 Chris Johns <chrisj@…>

  • libchip/i2c/spi-sd-card.c, libchip/ide/ata.c: Remove rtems_blkdev_request count and start references. Use RTEMS_BLKDEV_START_BLOCK.
  • 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 = RTEMS_BLKDEV_START_BLOCK (r) << e->block_size_shift;
566        uint32_t i = 0;
567
568        DEBUG_PRINT( "start = %u, bufnum = %u\n", r->start, r->bufnum);
569
570#ifdef DEBUG
571        /* Check request */
572  if (r->bufs[0].block >= e->block_number) {
573                SYSLOG_ERROR( "Start block number out of range");
574                return -RTEMS_INTERNAL_ERROR;
575        } else if (r->bufnum > e->block_number - RTEMS_BLKDEV_START_BLOCK (r)) {
576                SYSLOG_ERROR( "Block count out of range");
577                return -RTEMS_INTERNAL_ERROR;
578        }
579#endif /* DEBUG */
580
581        /* Start */
582        sc = sd_card_start( e);
583        CLEANUP_SCRV( sc, rv, sd_card_disk_block_read_cleanup, "Start");
584
585        if (r->bufnum == 1) {
586#ifdef DEBUG
587                /* Check buffer */
588                if (r->bufs [0].length != e->block_size) {
589                        DO_CLEANUP_RV( -RTEMS_INTERNAL_ERROR, rv, sd_card_disk_block_read_cleanup, "Buffer and disk block size are not equal");
590                }
591                DEBUG_PRINT( "[%02u]: buffer = 0x%08x, size = %u\n", 0, r->bufs [0].buffer, r->bufs [0].length);
592#endif /* DEBUG */
593
594                /* Single block read */
595                rv = sd_card_send_command( e, SD_CARD_CMD_READ_SINGLE_BLOCK, start_address);
596                CLEANUP_RV( rv, sd_card_disk_block_read_cleanup, "Send: SD_CARD_CMD_READ_SINGLE_BLOCK");
597                rv = sd_card_read( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_READ, (uint8_t *) r->bufs [0].buffer, e->block_size);
598                CLEANUP_RV( rv, sd_card_disk_block_read_cleanup, "Read: SD_CARD_CMD_READ_SINGLE_BLOCK");
599        } else {
600                /* Start multiple block read */
601                rv = sd_card_send_command( e, SD_CARD_CMD_READ_MULTIPLE_BLOCK, start_address);
602                CLEANUP_RV( rv, sd_card_disk_block_read_stop_cleanup, "Send: SD_CARD_CMD_READ_MULTIPLE_BLOCK");
603
604                /* Multiple block read */
605                for (i = 0; i < r->bufnum; ++i) {
606#ifdef DEBUG
607                        /* Check buffer */
608                        if (r->bufs [i].length != e->block_size) {
609                                DO_CLEANUP_RV( -RTEMS_INTERNAL_ERROR, rv, sd_card_disk_block_read_stop_cleanup, "Buffer and disk block size are not equal");
610                        }
611                        DEBUG_PRINT( "[%02u]: buffer = 0x%08x, size = %u\n", i, r->bufs [i].buffer, r->bufs [i].length);
612#endif /* DEBUG */
613
614                        rv = sd_card_read( e, SD_CARD_START_BLOCK_MULTIPLE_BLOCK_READ, (uint8_t *) r->bufs [i].buffer, e->block_size);
615                        CLEANUP_RV( rv, sd_card_disk_block_read_stop_cleanup, "Read block");
616                }
617
618                /* Stop multiple block read */
619                rv = sd_card_stop_multiple_block_read( e);
620                CLEANUP_RV( rv, sd_card_disk_block_read_cleanup, "Stop multiple block read");
621        }
622
623        /* Stop */
624        sc = sd_card_stop( e);
625        CHECK_SCRV( sc, "Stop");
626
627        /* Done */
628        r->req_done( r->done_arg, RTEMS_SUCCESSFUL, 0);
629
630        return 0;
631
632sd_card_disk_block_read_stop_cleanup:
633
634        /* Stop multiple block read */
635        sd_card_stop_multiple_block_read( e);
636
637sd_card_disk_block_read_cleanup:
638
639        /* Stop */
640        sd_card_stop( e);
641
642        /* Done */
643        r->req_done( r->done_arg, RTEMS_IO_ERROR, 0);
644
645        return rv;
646}
647
648static int sd_card_disk_block_write( sd_card_driver_entry *e, rtems_blkdev_request *r)
649{
650        rtems_status_code sc = RTEMS_SUCCESSFUL;
651        int rv = 0;
652        uint32_t start_address = RTEMS_BLKDEV_START_BLOCK (r) << e->block_size_shift;
653        uint32_t i = 0;
654
655        DEBUG_PRINT( "start = %u, count = %u, bufnum = %u\n", r->start, r->count, r->bufnum);
656
657#ifdef DEBUG
658        /* Check request */
659  if (r->bufs[0].block >= e->block_number) {
660                SYSLOG_ERROR( "Start block number out of range");
661                return -RTEMS_INTERNAL_ERROR;
662        } else if (r->bufnum > e->block_number - RTEMS_BLKDEV_START_BLOCK (r)) {
663                SYSLOG_ERROR( "Block count out of range");
664                return -RTEMS_INTERNAL_ERROR;
665        }
666#endif /* DEBUG */
667
668        /* Start */
669        sc = sd_card_start( e);
670        CLEANUP_SCRV( sc, rv, sd_card_disk_block_write_cleanup, "Start");
671
672        if (r->bufnum == 1) {
673#ifdef DEBUG
674                /* Check buffer */
675                if (r->bufs [0].length != e->block_size) {
676                        DO_CLEANUP_RV( -RTEMS_INTERNAL_ERROR, rv, sd_card_disk_block_write_cleanup, "Buffer and disk block size are not equal");
677                }
678                DEBUG_PRINT( "[%02u]: buffer = 0x%08x, size = %u\n", 0, r->bufs [0].buffer, r->bufs [0].length);
679#endif /* DEBUG */
680
681                /* Single block write */
682                rv = sd_card_send_command( e, SD_CARD_CMD_WRITE_BLOCK, start_address);
683                CLEANUP_RV( rv, sd_card_disk_block_write_cleanup, "Send: SD_CARD_CMD_WRITE_BLOCK");
684                rv = sd_card_write( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_WRITE, (uint8_t *) r->bufs [0].buffer, e->block_size);
685                CLEANUP_RV( rv, sd_card_disk_block_write_cleanup, "Write: SD_CARD_CMD_WRITE_BLOCK");
686        } else {
687                /* Start multiple block write */
688                rv = sd_card_send_command( e, SD_CARD_CMD_WRITE_MULTIPLE_BLOCK, start_address);
689                CLEANUP_RV( rv, sd_card_disk_block_write_stop_cleanup, "Send: SD_CARD_CMD_WRITE_MULTIPLE_BLOCK");
690
691                /* Multiple block write */
692                for (i = 0; i < r->bufnum; ++i) {
693#ifdef DEBUG
694                        /* Check buffer */
695                        if (r->bufs [i].length != e->block_size) {
696                                DO_CLEANUP_RV( -RTEMS_INTERNAL_ERROR, rv, sd_card_disk_block_write_stop_cleanup, "Buffer and disk block size are not equal");
697                        }
698                        DEBUG_PRINT( "[%02u]: buffer = 0x%08x, size = %u\n", i, r->bufs [i].buffer, r->bufs [i].length);
699#endif /* DEBUG */
700
701                        rv = sd_card_write( e, SD_CARD_START_BLOCK_MULTIPLE_BLOCK_WRITE, (uint8_t *) r->bufs [i].buffer, e->block_size);
702                        CLEANUP_RV( rv, sd_card_disk_block_write_stop_cleanup, "Write block");
703                }
704
705                /* Stop multiple block write */
706                rv = sd_card_stop_multiple_block_write( e);
707                CLEANUP_RV( rv, sd_card_disk_block_write_cleanup, "Stop multiple block write");
708        }
709
710        /* Get card status */
711        rv = sd_card_send_command( e, SD_CARD_CMD_SEND_STATUS, 0);
712        CHECK_RV( rv, "Send: SD_CARD_CMD_SEND_STATUS");
713
714        /* Stop */
715        sc = sd_card_stop( e);
716        CHECK_SCRV( sc, "Stop");
717
718        /* Done */
719        r->req_done( r->done_arg, RTEMS_SUCCESSFUL, 0);
720
721        return 0;
722
723sd_card_disk_block_write_stop_cleanup:
724
725        /* Stop multiple block write */
726        sd_card_stop_multiple_block_write( e);
727
728sd_card_disk_block_write_cleanup:
729
730        /* Get card status */
731        rv = sd_card_send_command( e, SD_CARD_CMD_SEND_STATUS, 0);
732        CHECK_RV( rv, "Send: SD_CARD_CMD_SEND_STATUS");
733
734        /* Stop */
735        sd_card_stop( e);
736
737        /* Done */
738        r->req_done( r->done_arg, RTEMS_IO_ERROR, 0);
739
740        return rv;
741}
742
743static int sd_card_disk_ioctl( dev_t dev, uint32_t req, void *arg)
744{
745        DEBUG_PRINT( "dev = %u, req = %u, arg = 0x08%x\n", dev, req, arg);
746        if (req == RTEMS_BLKIO_REQUEST) {
747                rtems_device_minor_number minor = rtems_filesystem_dev_minor_t( dev);
748                sd_card_driver_entry *e = &sd_card_driver_table [minor];
749                rtems_blkdev_request *r = (rtems_blkdev_request *) arg;
750                switch (r->req) {
751                        case RTEMS_BLKDEV_REQ_READ:
752                                return sd_card_disk_block_read( e, r);
753                        case RTEMS_BLKDEV_REQ_WRITE:
754                                return sd_card_disk_block_write( e, r);
755                        case RTEMS_BLKDEV_CAPABILITIES:
756                                *((uint32_t*) arg)  = RTEMS_BLKDEV_CAP_MULTISECTOR_CONT;
757                                return 0;
758                        default:
759                                errno = EBADRQC;
760                                return -1;
761                }
762        } else {
763                errno = EBADRQC;
764                return -1;
765        }
766}
767
768static rtems_status_code sd_card_disk_init( rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
769{
770        /* Do nothing */
771
772        return RTEMS_SUCCESSFUL;
773}
774
775/** @} */
776
777static const rtems_driver_address_table sd_card_disk_ops = {
778        .initialization_entry = sd_card_disk_init,
779        .open_entry = NULL,
780        .close_entry = NULL,
781        .read_entry = NULL,
782        .write_entry = NULL,
783        .control_entry = NULL
784};
785
786static rtems_device_major_number sd_card_disk_major = 0;
787
788static int sd_card_driver_first = 1;
789
790/**
791 * @name LibI2C Driver Functions
792 * @{
793 */
794
795static inline int sd_card_driver_get_entry( rtems_device_minor_number minor, sd_card_driver_entry **e)
796{
797        return rtems_libi2c_ioctl( minor, RTEMS_LIBI2C_IOCTL_GET_DRV_T, e);
798}
799
800static rtems_status_code sd_card_driver_init( rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
801{
802        rtems_status_code sc = RTEMS_SUCCESSFUL;
803        int rv = 0;
804        sd_card_driver_entry *e = NULL;
805        uint8_t block [SD_CARD_BLOCK_SIZE_DEFAULT];
806        uint32_t transfer_speed = 0;
807        uint32_t read_block_size = 0;
808        uint32_t write_block_size = 0;
809        dev_t dev = 0;
810
811        /* Get driver entry */
812        rv = sd_card_driver_get_entry( minor, &e);
813        CHECK_RVSC( rv, "Get driver entry");
814
815        /* Start */
816        sc = sd_card_start( e);
817        CLEANUP_SC( sc, sd_card_driver_init_cleanup, "Start");
818
819        /* Save minor number for disk operations */
820        e->minor = minor;
821
822        /* Register disk driver */
823        if (sd_card_driver_first) {
824                sd_card_driver_first = 0;
825                sc = rtems_io_register_driver( 0, &sd_card_disk_ops, &sd_card_disk_major);
826                CLEANUP_SC( sc, sd_card_driver_init_cleanup, "Register disk IO driver");
827        }
828
829        /* Wait until card is not busy */
830        rv = sd_card_wait( e);
831        CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Wait");
832
833        /* Send idle tokens for at least 74 clock cycles with active chip select */
834        memset( block, SD_CARD_IDLE_TOKEN, SD_CARD_BLOCK_SIZE_DEFAULT);
835        rv = rtems_libi2c_write_bytes( e->minor, block, SD_CARD_BLOCK_SIZE_DEFAULT);
836        CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Active chip select delay");
837
838        /* Stop */
839        sc = sd_card_stop( e);
840        CHECK_SC( sc, "Stop");
841
842        /* Start with inactive chip select */
843        sc = rtems_libi2c_send_start( e->minor);
844        CHECK_SC( sc, "Send start");
845
846        /* Set transfer mode */
847        rv = rtems_libi2c_ioctl( e->minor, RTEMS_LIBI2C_IOCTL_SET_TFRMODE, &e->transfer_mode);
848        CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Set transfer mode");
849
850        /* Send idle tokens with inactive chip select */
851        rv = sd_card_query( e, e->response, SD_CARD_COMMAND_SIZE);
852        CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Inactive chip select delay");
853
854        /* Activate chip select */
855        sc = rtems_libi2c_send_addr( e->minor, 1);
856        CLEANUP_SC( sc, sd_card_driver_init_cleanup, "Send address");
857
858        /* Stop multiple block write */
859        sd_card_stop_multiple_block_write( e);
860
861        /* Get card status */
862        sd_card_send_command( e, SD_CARD_CMD_SEND_STATUS, 0);
863
864        /* Stop multiple block read */
865        sd_card_stop_multiple_block_read( e);
866
867        /* Switch to SPI mode */
868        rv = sd_card_send_command( e, SD_CARD_CMD_GO_IDLE_STATE, 0);
869        CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_CMD_GO_IDLE_STATE");
870
871        /* Initialize card */
872        while (1) {
873                rv = sd_card_send_command( e, SD_CARD_CMD_APP_CMD, 0);
874                CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_CMD_APP_CMD");
875                rv = sd_card_send_command( e, SD_CARD_ACMD_SD_SEND_OP_COND, 0);
876                CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_ACMD_SD_SEND_OP_COND");
877       
878                /* Not idle? */
879                if (SD_CARD_IS_NOT_IDLE_RESPONSE( e->response [e->response_index])) {
880                        break;
881                }
882
883                /* Invoke the scheduler */
884                rtems_task_wake_after( RTEMS_YIELD_PROCESSOR);
885        };
886
887        /* Card Identification */
888        if (e->verbose) {
889                rv = sd_card_send_command( e, SD_CARD_CMD_SEND_CID, 0);
890                CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_CMD_SEND_CID");
891                rv = sd_card_read( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_READ, block, SD_CARD_CID_SIZE);
892                CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Read: SD_CARD_CMD_SEND_CID");
893                SYSLOG( "*** Card Identification ***\n");
894                SYSLOG( "Manufacturer ID          : %" PRIu8 "\n", SD_CARD_CID_GET_MID( block));
895                SYSLOG( "OEM/Application ID       : %" PRIu16 "\n", SD_CARD_CID_GET_OID( block));
896                SYSLOG(
897                        "Product name             : %c%c%c%c%c%c\n",
898                        SD_CARD_CID_GET_PNM( block, 0),
899                        SD_CARD_CID_GET_PNM( block, 1),
900                        SD_CARD_CID_GET_PNM( block, 2),
901                        SD_CARD_CID_GET_PNM( block, 3),
902                        SD_CARD_CID_GET_PNM( block, 4),
903                        SD_CARD_CID_GET_PNM( block, 5)
904                );
905                SYSLOG( "Product revision         : %" PRIu8 "\n", SD_CARD_CID_GET_PRV( block));
906                SYSLOG( "Product serial number    : %" PRIu32 "\n", SD_CARD_CID_GET_PSN( block));
907                SYSLOG( "Manufacturing date       : %" PRIu8 "\n", SD_CARD_CID_GET_MDT( block));
908                SYSLOG( "7-bit CRC checksum       : %" PRIu8 "\n",  SD_CARD_CID_GET_CRC7( block));
909        }
910
911        /* Card Specific Data */
912        rv = sd_card_send_command( e, SD_CARD_CMD_SEND_CSD, 0);
913        CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_CMD_SEND_CSD");
914        rv = sd_card_read( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_READ, block, SD_CARD_CSD_SIZE);
915        CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Read: SD_CARD_CMD_SEND_CSD");
916        transfer_speed = sd_card_transfer_speed( block);
917        e->transfer_mode.baudrate = transfer_speed;
918        e->n_ac_max = sd_card_max_access_time( block, transfer_speed);
919        read_block_size = 1 << SD_CARD_CSD_GET_READ_BLK_LEN( block);
920        e->block_size_shift = SD_CARD_CSD_GET_READ_BLK_LEN( block);
921        write_block_size = 1 << e->block_size_shift;
922        if (read_block_size < write_block_size) {
923                SYSLOG_ERROR( "Read block size smaller than write block size\n");
924                return -RTEMS_IO_ERROR;
925        }
926        e->block_size = write_block_size;
927        e->block_number = sd_card_block_number( block);
928        if (e->verbose) {
929                SYSLOG( "*** Card Specific Data ***\n");
930                SYSLOG( "CSD structure            : %" PRIu8 "\n", SD_CARD_CSD_GET_CSD_STRUCTURE( block));
931                SYSLOG( "Spec version             : %" PRIu8 "\n", SD_CARD_CSD_GET_SPEC_VERS( block));
932                SYSLOG( "Access time [ns]         : %" PRIu32 "\n", sd_card_access_time( block));
933                SYSLOG( "Max access time [N]      : %" PRIu32 "\n", e->n_ac_max);
934                SYSLOG( "Max read block size [B]  : %" PRIu32 "\n", read_block_size);
935                SYSLOG( "Max write block size [B] : %" PRIu32 "\n", write_block_size);
936                SYSLOG( "Block size [B]           : %" PRIu32 "\n", e->block_size);
937                SYSLOG( "Block number             : %" PRIu32 "\n", e->block_number);
938                SYSLOG( "Capacity [B]             : %" PRIu32 "\n", sd_card_capacity( block));
939                SYSLOG( "Max transfer speed [b/s] : %" PRIu32 "\n", transfer_speed);
940        }
941
942        /* Set read block size */
943        rv = sd_card_send_command( e, SD_CARD_CMD_SET_BLOCKLEN, e->block_size);
944        CLEANUP_RVSC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_CMD_SET_BLOCKLEN");
945
946        /* Create disk device */
947        dev = rtems_filesystem_make_dev_t( sd_card_disk_major, e->table_index);
948        sc = rtems_disk_io_initialize();
949        CLEANUP_SC( sc, sd_card_driver_init_cleanup, "Initialize RTEMS disk IO");
950        sc = rtems_disk_create_phys( dev, e->block_size, e->block_number, sd_card_disk_ioctl, e->disk_device_name);
951        CLEANUP_SC( sc, sd_card_driver_init_cleanup, "Create disk device");
952
953        /* Stop */
954        sc = sd_card_stop( e);
955        CHECK_SC( sc, "Stop");
956
957        return RTEMS_SUCCESSFUL;
958
959sd_card_driver_init_cleanup:
960
961        /* Stop */
962        sd_card_stop( e);
963
964        return sc;
965}
966
967static rtems_status_code sd_card_driver_read( rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
968{
969        rtems_status_code sc = RTEMS_SUCCESSFUL;
970        int rv = 0;
971        rtems_libio_rw_args_t *rw = (rtems_libio_rw_args_t *) arg;
972        sd_card_driver_entry *e = NULL;
973        uint32_t block_size_mask = 0;
974        uint32_t block_count = 0;
975        uint32_t start_block = 0;
976        uint32_t i = 0;
977
978        /* Clear moved bytes counter */
979        rw->bytes_moved = 0;
980
981        /* Get driver entry */
982        rv = sd_card_driver_get_entry( minor, &e);
983        CHECK_RVSC( rv, "Get driver entry");
984
985        /* Start */
986        sc = sd_card_start( e);
987        CLEANUP_SC( sc, sd_card_driver_read_cleanup, "Start");
988
989        /* Check arguments */
990        block_size_mask = e->block_size - 1;
991        block_count = rw->count >> e->block_size_shift;
992        start_block = rw->offset >> e->block_size_shift;
993        if (rw->offset & block_size_mask) {
994                DO_CLEANUP_SC( RTEMS_INVALID_ADDRESS, sc, sd_card_driver_read_cleanup, "Invalid offset");
995        } else if ((rw->count & block_size_mask) || (start_block >= e->block_number) || (block_count > e->block_number - start_block)) {
996                DO_CLEANUP_SC( RTEMS_INVALID_NUMBER, sc, sd_card_driver_read_cleanup, "Invalid count or out of range");
997        }
998
999        if (block_count == 0) {
1000                /* Do nothing */
1001        } else if (block_count == 1) {
1002                /* Single block read */
1003                rv = sd_card_send_command( e, SD_CARD_CMD_READ_SINGLE_BLOCK, rw->offset);
1004                CLEANUP_RVSC( rv, sc, sd_card_driver_read_cleanup, "Send: SD_CARD_CMD_READ_SINGLE_BLOCK");
1005                rv = sd_card_read( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_READ, (uint8_t *) rw->buffer, e->block_size);
1006                CLEANUP_RVSC( rv, sc, sd_card_driver_read_cleanup, "Read: SD_CARD_CMD_READ_SINGLE_BLOCK");
1007
1008                /* Set moved bytes counter */
1009                rw->bytes_moved = rv;
1010        } else {
1011                /* Start multiple block read */
1012                rv = sd_card_send_command( e, SD_CARD_CMD_READ_MULTIPLE_BLOCK, rw->offset);
1013                CLEANUP_RVSC( rv, sc, sd_card_driver_read_stop_cleanup, "Send: SD_CARD_CMD_READ_MULTIPLE_BLOCK");
1014
1015                /* Multiple block read */
1016                for (i = 0; i < block_count; ++i) {
1017                        rv = sd_card_read( e, SD_CARD_START_BLOCK_MULTIPLE_BLOCK_READ, (uint8_t *) rw->buffer + (i << e->block_size_shift), e->block_size);
1018                        CLEANUP_RVSC( rv, sc, sd_card_driver_read_stop_cleanup, "Read block");
1019
1020                        /* Update moved bytes counter */
1021                        rw->bytes_moved += rv;
1022                }
1023
1024                /* Stop multiple block read */
1025                rv = sd_card_stop_multiple_block_read( e);
1026                CLEANUP_RVSC( rv, sc, sd_card_driver_read_cleanup, "Stop multiple block read");
1027        }
1028
1029        /* Stop */
1030        sc = sd_card_stop( e);
1031        CHECK_SC( sc, "Stop");
1032
1033        return RTEMS_SUCCESSFUL;
1034
1035sd_card_driver_read_stop_cleanup:
1036
1037        /* Stop multiple block read */
1038        sd_card_stop_multiple_block_read( e);
1039
1040sd_card_driver_read_cleanup:
1041
1042        /* Stop */
1043        sd_card_stop( e);
1044
1045        return sc;
1046}
1047
1048static rtems_status_code sd_card_driver_write( rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
1049{
1050        rtems_status_code sc = RTEMS_SUCCESSFUL;
1051        int rv = 0;
1052        rtems_libio_rw_args_t *rw = (rtems_libio_rw_args_t *) arg;
1053        sd_card_driver_entry *e = NULL;
1054        uint32_t block_size_mask = 0;
1055        uint32_t block_count = 0;
1056        uint32_t start_block = 0;
1057        uint32_t i = 0;
1058
1059        /* Clear moved bytes counter */
1060        rw->bytes_moved = 0;
1061
1062        /* Get driver entry */
1063        rv = sd_card_driver_get_entry( minor, &e);
1064        CHECK_RVSC( rv, "Get driver entry");
1065
1066        /* Start */
1067        sc = sd_card_start( e);
1068        CLEANUP_SC( sc, sd_card_driver_write_cleanup, "Start");
1069
1070        /* Check arguments */
1071        block_size_mask = e->block_size - 1;
1072        block_count = rw->count >> e->block_size_shift;
1073        start_block = rw->offset >> e->block_size_shift;
1074        if (rw->offset & block_size_mask) {
1075                DO_CLEANUP_SC( RTEMS_INVALID_ADDRESS, sc, sd_card_driver_write_cleanup, "Invalid offset");
1076        } else if ((rw->count & block_size_mask) || (start_block >= e->block_number) || (block_count > e->block_number - start_block)) {
1077                DO_CLEANUP_SC( RTEMS_INVALID_NUMBER, sc, sd_card_driver_write_cleanup, "Invalid count or out of range");
1078        }
1079
1080        if (block_count == 0) {
1081                /* Do nothing */
1082        } else if (block_count == 1) {
1083                /* Single block write */
1084                rv = sd_card_send_command( e, SD_CARD_CMD_WRITE_BLOCK, rw->offset);
1085                CLEANUP_RVSC( rv, sc, sd_card_driver_write_cleanup, "Send: SD_CARD_CMD_WRITE_BLOCK");
1086                rv = sd_card_write( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_WRITE, (uint8_t *) rw->buffer, e->block_size);
1087                CLEANUP_RVSC( rv, sc, sd_card_driver_write_cleanup, "Write: SD_CARD_CMD_WRITE_BLOCK");
1088
1089                /* Set moved bytes counter */
1090                rw->bytes_moved = rv;
1091        } else {
1092                /* Start multiple block write */
1093                rv = sd_card_send_command( e, SD_CARD_CMD_WRITE_MULTIPLE_BLOCK, rw->offset);
1094                CLEANUP_RVSC( rv, sc, sd_card_driver_write_stop_cleanup, "Send: SD_CARD_CMD_WRITE_MULTIPLE_BLOCK");
1095
1096                /* Multiple block write */
1097                for (i = 0; i < block_count; ++i) {
1098                        rv = sd_card_write( e, SD_CARD_START_BLOCK_MULTIPLE_BLOCK_WRITE, (uint8_t *) rw->buffer + (i << e->block_size_shift), e->block_size);
1099                        CLEANUP_RVSC( rv, sc, sd_card_driver_write_stop_cleanup, "Write: SD_CARD_CMD_WRITE_MULTIPLE_BLOCK");
1100
1101                        /* Update moved bytes counter */
1102                        rw->bytes_moved += rv;
1103                }
1104
1105                /* Stop multiple block write */
1106                rv = sd_card_stop_multiple_block_write( e);
1107                CLEANUP_RVSC( rv, sc, sd_card_driver_write_cleanup, "Stop multiple block write");
1108        }
1109
1110        /* Get card status */
1111        rv = sd_card_send_command( e, SD_CARD_CMD_SEND_STATUS, 0);
1112        CHECK_RV( rv, "Send: SD_CARD_CMD_SEND_STATUS");
1113
1114        /* Stop */
1115        sc = sd_card_stop( e);
1116        CHECK_SC( sc, "Stop");
1117
1118        return RTEMS_SUCCESSFUL;
1119
1120sd_card_driver_write_stop_cleanup:
1121
1122        /* Stop multiple block write */
1123        sd_card_stop_multiple_block_write( e);
1124
1125sd_card_driver_write_cleanup:
1126
1127        /* Get card status */
1128        rv = sd_card_send_command( e, SD_CARD_CMD_SEND_STATUS, 0);
1129        CHECK_RV( rv, "Send: SD_CARD_CMD_SEND_STATUS");
1130
1131        /* Stop */
1132        sd_card_stop( e);
1133
1134        return sc;
1135}
1136
1137/** @} */
1138
1139const rtems_driver_address_table sd_card_driver_ops = {
1140        .initialization_entry = sd_card_driver_init,
1141        .open_entry = NULL,
1142        .close_entry = NULL,
1143        .read_entry = sd_card_driver_read,
1144        .write_entry = sd_card_driver_write,
1145        .control_entry = NULL
1146};
Note: See TracBrowser for help on using the repository browser.