Remove unused card_detect(), and make card_detect_target() static inline in each...
[kugel-rb.git] / firmware / target / arm / ata-sd-pp.c
blobfafc5f20d97099c4d726aa5becc4d92313a67604
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2006 Daniel Ankers
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include "config.h" /* for HAVE_MULTIDRIVE */
22 #include "fat.h"
23 #include "hotswap.h"
24 #ifdef HAVE_HOTSWAP
25 #include "sd-pp-target.h"
26 #endif
27 #include "ata_idle_notify.h"
28 #include "system.h"
29 #include <string.h>
30 #include "thread.h"
31 #include "led.h"
32 #include "disk.h"
33 #include "cpu.h"
34 #include "panic.h"
35 #include "usb.h"
36 #include "sd.h"
37 #include "storage.h"
39 #define SECTOR_SIZE 512
40 #define BLOCKS_PER_BANK 0x7a7800
42 /* Comparing documentations of various MMC/SD controllers revealed, */
43 /* that this controller seems to be a mix of PXA27x, PXA255 and */
44 /* some PP specific stuff. The register and bit definitions are */
45 /* taken from the 'PXA27x Developers Manual', as it appears to be */
46 /* the closest match. Known differences and obscurities are commented.*/
48 #define MMC_STRPCL (*(volatile unsigned int *)(0x70008200))
49 #define MMC_STAT (*(volatile unsigned int *)(0x70008204))
50 #define MMC_CLKRT (*(volatile unsigned int *)(0x70008208))
51 #define MMC_SPI (*(volatile unsigned int *)(0x7000820c))
52 #define MMC_CMDAT (*(volatile unsigned int *)(0x70008210))
53 #define MMC_RESTO (*(volatile unsigned int *)(0x70008214))
54 #define MMC_RDTO (*(volatile unsigned int *)(0x70008218))
55 #define MMC_BLKLEN (*(volatile unsigned int *)(0x7000821c))
56 #define MMC_NUMBLK (*(volatile unsigned int *)(0x70008220))
57 #define MMC_I_MASK (*(volatile unsigned int *)(0x70008224))
58 #define MMC_CMD (*(volatile unsigned int *)(0x70008228))
59 #define MMC_ARGH (*(volatile unsigned int *)(0x7000822c))
60 #define MMC_ARGL (*(volatile unsigned int *)(0x70008230))
61 #define MMC_RES (*(volatile unsigned int *)(0x70008234))
63 /* PXA255/27x have separate RX/TX FIFOs with 32x8 bit */
64 /* PP502x has a combined Data FIFO with 16x16 bit */
65 #define MMC_DATA_FIFO (*(volatile unsigned int *)(0x70008280))
67 /* PP specific registers, no other controller seem to have such. */
68 #define MMC_SD_STATE (*(volatile unsigned int *)(0x70008238))
69 #define MMC_INIT_1 (*(volatile unsigned int *)(0x70008240))
70 #define MMC_INIT_2 (*(volatile unsigned int *)(0x70008244))
72 /* MMC_STAT bits */
73 #define STAT_SDIO_SUSPEND_ACK (1 << 16)
74 #define STAT_SDIO_INT (1 << 15)
75 #define STAT_RD_STALLED (1 << 14)
76 #define STAT_END_CMD_RES (1 << 13)
77 #define STAT_PRG_DONE (1 << 12)
78 #define STAT_DATA_TRAN_DONE (1 << 11)
79 #define STAT_SPI_WR_ERR (1 << 10)
80 #define STAT_FLASH_ERR (1 << 9)
81 #define STAT_CLK_EN (1 << 8)
82 #define STAT_RECV_FIFO_FULL (1 << 7) /* taken from PXA255 */
83 #define STAT_XMIT_FIFO_EMPTY (1 << 6) /* taken from PXA255 */
84 #define STAT_RES_CRC_ERR (1 << 5)
85 #define STAT_DAT_ERR_TOKEN (1 << 4)
86 #define STAT_CRC_RD_ERR (1 << 3)
87 #define STAT_CRC_WR_ERR (1 << 2)
88 #define STAT_TIME_OUT_RES (1 << 1)
89 #define STAT_TIME_OUT_READ (1)
90 #define STAT_ERROR_BITS (0x3f)
92 /* MMC_CMDAT bits */
93 /* Some of the bits used by the OF don't make much sense with these */
94 /* definitions. So they're probably different between PXA and PP502x */
95 /* Bits 0-5 appear to match though. */
96 #define CMDAT_SDIO_RESUME (1 << 13)
97 #define CMDAT_SDIO_SUSPEND (1 << 12)
98 #define CMDAT_SDIO_INT_EN (1 << 11)
99 #define CMDAT_STOP_TRAN (1 << 10)
100 #define CMDAT_SD_4DAT (1 << 8)
101 #define CMDAT_DMA_EN (1 << 7)
102 #define CMDAT_INIT (1 << 6)
103 #define CMDAT_BUSY (1 << 5)
104 #define CMDAT_STRM_BLK (1 << 4)
105 #define CMDAT_WR_RD (1 << 3)
106 #define CMDAT_DATA_EN (1 << 2)
107 #define CMDAT_RES_TYPE3 (3)
108 #define CMDAT_RES_TYPE2 (2)
109 #define CMDAT_RES_TYPE1 (1)
111 /* MMC_I_MASK bits */
112 /* PP502x apparently only has bits 0-3 */
113 #define I_MASK_SDIO_SUSPEND_ACK (1 << 12)
114 #define I_MASK_SDIO_INT (1 << 11)
115 #define I_MASK_RD_STALLED (1 << 10)
116 #define I_MASK_RES_ERR (1 << 9)
117 #define I_MASK_DAT_ERR (1 << 8)
118 #define I_MASK_TINT (1 << 7)
119 #define I_MASK_TXFIFO_WR_REQ (1 << 6)
120 #define I_MASK_RXFIFO_RD_REQ (1 << 5)
121 #define I_MASK_CLK_IS_OFF (1 << 4)
122 #define I_MASK_STOP_CMD (1 << 3)
123 #define I_MASK_END_CMD_RES (1 << 2)
124 #define I_MASK_PRG_DONE (1 << 1)
125 #define I_MASK_DATA_TRAN_DONE (1 << 0)
127 #define FIFO_LEN 16 /* FIFO is 16 words deep */
129 #define EC_OK 0
130 #define EC_FAILED 1
131 #define EC_NOCARD 2
132 #define EC_WAIT_STATE_FAILED 3
133 #define EC_CHECK_TIMEOUT_FAILED 4
134 #define EC_POWER_UP 5
135 #define EC_READ_TIMEOUT 6
136 #define EC_WRITE_TIMEOUT 7
137 #define EC_TRAN_SEL_BANK 8
138 #define EC_TRAN_READ_ENTRY 9
139 #define EC_TRAN_READ_EXIT 10
140 #define EC_TRAN_WRITE_ENTRY 11
141 #define EC_TRAN_WRITE_EXIT 12
142 #define EC_FIFO_SEL_BANK_EMPTY 13
143 #define EC_FIFO_SEL_BANK_DONE 14
144 #define EC_FIFO_ENA_BANK_EMPTY 15
145 #define EC_FIFO_READ_FULL 16
146 #define EC_FIFO_WR_EMPTY 17
147 #define EC_FIFO_WR_DONE 18
148 #define EC_COMMAND 19
149 #define NUM_EC 20
151 /* for compatibility */
152 static long last_disk_activity = -1;
154 /** static, private data **/
155 static bool initialized = false;
157 static long next_yield = 0;
158 #define MIN_YIELD_PERIOD 1000
160 static tCardInfo card_info[2];
161 static tCardInfo *currcard = NULL; /* current active card */
163 struct sd_card_status
165 int retry;
166 int retry_max;
169 static struct sd_card_status sd_status[NUM_DRIVES] =
171 { 0, 1 },
172 #ifdef HAVE_MULTIDRIVE
173 { 0, 10 }
174 #endif
177 /* Shoot for around 75% usage */
178 static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)];
179 static const char sd_thread_name[] = "ata/sd";
180 static struct mutex sd_mtx SHAREDBSS_ATTR;
181 static struct event_queue sd_queue;
183 #ifdef HAVE_HOTSWAP
184 static int sd_first_drive = 0;
185 #endif
187 /* Posted when card plugged status has changed */
188 #define SD_HOTSWAP 1
189 /* Actions taken by sd_thread when card status has changed */
190 enum sd_thread_actions
192 SDA_NONE = 0x0,
193 SDA_UNMOUNTED = 0x1,
194 SDA_MOUNTED = 0x2
197 /* Private Functions */
199 static unsigned int check_time[NUM_EC];
201 static inline bool sd_check_timeout(long timeout, int id)
203 return !TIME_AFTER(USEC_TIMER, check_time[id] + timeout);
206 static bool sd_poll_status(unsigned int trigger, long timeout)
208 long t = USEC_TIMER;
210 while ((MMC_STAT & trigger) == 0)
212 long time = USEC_TIMER;
214 if (TIME_AFTER(time, next_yield))
216 long ty = USEC_TIMER;
217 yield();
218 timeout += USEC_TIMER - ty;
219 next_yield = ty + MIN_YIELD_PERIOD;
222 if (TIME_AFTER(time, t + timeout))
223 return false;
226 return true;
229 static int sd_command(unsigned int cmd, unsigned long arg1,
230 unsigned long *response, unsigned int cmdat)
232 int i, words; /* Number of 16 bit words to read from MMC_RES */
233 unsigned int data[9];
235 MMC_CMD = cmd;
236 MMC_ARGH = (unsigned int)((arg1 & 0xffff0000) >> 16);
237 MMC_ARGL = (unsigned int)((arg1 & 0xffff));
238 MMC_CMDAT = cmdat;
240 if (!sd_poll_status(STAT_END_CMD_RES, 100000))
241 return -EC_COMMAND;
243 if ((MMC_STAT & STAT_ERROR_BITS) != 0)
244 /* Error sending command */
245 return -EC_COMMAND - (MMC_STAT & STAT_ERROR_BITS)*100;
247 if (cmd == SD_GO_IDLE_STATE)
248 return 0; /* no response here */
250 words = (cmdat == CMDAT_RES_TYPE2) ? 9 : 3;
252 for (i = 0; i < words; i++) /* MMC_RES is read MSB first */
253 data[i] = MMC_RES; /* Read most significant 16-bit word */
255 if (response == NULL)
257 /* response discarded */
259 else if (cmdat == CMDAT_RES_TYPE2)
261 /* Response type 2 has the following structure:
262 * [135:135] Start Bit - '0'
263 * [134:134] Transmission bit - '0'
264 * [133:128] Reserved - '111111'
265 * [127:001] CID or CSD register including internal CRC7
266 * [000:000] End Bit - '1'
268 response[3] = (data[0]<<24) + (data[1]<<8) + (data[2]>>8);
269 response[2] = (data[2]<<24) + (data[3]<<8) + (data[4]>>8);
270 response[1] = (data[4]<<24) + (data[5]<<8) + (data[6]>>8);
271 response[0] = (data[6]<<24) + (data[7]<<8) + (data[8]>>8);
273 else
275 /* Response types 1, 1b, 3, 6, 7 have the following structure:
276 * Types 4 and 5 are not supported.
278 * [47] Start bit - '0'
279 * [46] Transmission bit - '0'
280 * [45:40] R1, R1b, R6, R7: Command index
281 * R3: Reserved - '111111'
282 * [39:8] R1, R1b: Card Status
283 * R3: OCR Register
284 * R6: [31:16] RCA
285 * [15: 0] Card Status Bits 23, 22, 19, 12:0
286 * [23] COM_CRC_ERROR
287 * [22] ILLEGAL_COMMAND
288 * [19] ERROR
289 * [12:9] CURRENT_STATE
290 * [8] READY_FOR_DATA
291 * [7:6]
292 * [5] SD_APP_CMD
293 * [4]
294 * [3] AKE_SEQ_ERROR
295 * [2] Reserved
296 * [1:0] Reserved for test mode
297 * R7: [19:16] Voltage accepted
298 * [15:8] echo-back of check pattern
299 * [7:1] R1, R1b: CRC7
300 * R3: Reserved - '1111111'
301 * [0] End Bit - '1'
303 response[0] = (data[0]<<24) + (data[1]<<8) + (data[2]>>8);
306 return 0;
309 static int sd_wait_for_state(unsigned int state, int id)
311 unsigned long response = 0;
312 unsigned int timeout = 0x80000;
314 check_time[id] = USEC_TIMER;
316 while (1)
318 int ret = sd_command(SD_SEND_STATUS, currcard->rca, &response, CMDAT_RES_TYPE1);
319 long us;
321 if (ret < 0)
322 return ret*100 - id;
324 if (((response >> 9) & 0xf) == state)
326 MMC_SD_STATE = state;
327 return 0;
330 if (!sd_check_timeout(timeout, id))
331 return -EC_WAIT_STATE_FAILED*100 - id;
333 us = USEC_TIMER;
334 if (TIME_AFTER(us, next_yield))
336 yield();
337 timeout += USEC_TIMER - us;
338 next_yield = us + MIN_YIELD_PERIOD;
344 static inline bool card_detect_target(void)
346 #ifdef HAVE_HOTSWAP
347 #ifdef SANSA_E200
348 return (GPIOA_INPUT_VAL & 0x80) == 0; /* low active */
349 #elif defined SANSA_C200
350 return (GPIOL_INPUT_VAL & 0x08) != 0; /* high active */
351 #endif
352 #else
353 return false;
354 #endif
358 static inline void copy_read_sectors_fast(unsigned char **buf)
360 /* Copy one chunk of 16 words using best method for start alignment */
361 switch ( (intptr_t)*buf & 3 )
363 case 0:
364 asm volatile (
365 "ldmia %[data], { r2-r9 } \r\n"
366 "orr r2, r2, r3, lsl #16 \r\n"
367 "orr r4, r4, r5, lsl #16 \r\n"
368 "orr r6, r6, r7, lsl #16 \r\n"
369 "orr r8, r8, r9, lsl #16 \r\n"
370 "stmia %[buf]!, { r2, r4, r6, r8 } \r\n"
371 "ldmia %[data], { r2-r9 } \r\n"
372 "orr r2, r2, r3, lsl #16 \r\n"
373 "orr r4, r4, r5, lsl #16 \r\n"
374 "orr r6, r6, r7, lsl #16 \r\n"
375 "orr r8, r8, r9, lsl #16 \r\n"
376 "stmia %[buf]!, { r2, r4, r6, r8 } \r\n"
377 : [buf]"+&r"(*buf)
378 : [data]"r"(&MMC_DATA_FIFO)
379 : "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9"
381 break;
382 case 1:
383 asm volatile (
384 "ldmia %[data], { r2-r9 } \r\n"
385 "orr r3, r2, r3, lsl #16 \r\n"
386 "strb r3, [%[buf]], #1 \r\n"
387 "mov r3, r3, lsr #8 \r\n"
388 "strh r3, [%[buf]], #2 \r\n"
389 "mov r3, r3, lsr #16 \r\n"
390 "orr r3, r3, r4, lsl #8 \r\n"
391 "orr r3, r3, r5, lsl #24 \r\n"
392 "mov r5, r5, lsr #8 \r\n"
393 "orr r5, r5, r6, lsl #8 \r\n"
394 "orr r5, r5, r7, lsl #24 \r\n"
395 "mov r7, r7, lsr #8 \r\n"
396 "orr r7, r7, r8, lsl #8 \r\n"
397 "orr r7, r7, r9, lsl #24 \r\n"
398 "mov r2, r9, lsr #8 \r\n"
399 "stmia %[buf]!, { r3, r5, r7 } \r\n"
400 "ldmia %[data], { r3-r10 } \r\n"
401 "orr r2, r2, r3, lsl #8 \r\n"
402 "orr r2, r2, r4, lsl #24 \r\n"
403 "mov r4, r4, lsr #8 \r\n"
404 "orr r4, r4, r5, lsl #8 \r\n"
405 "orr r4, r4, r6, lsl #24 \r\n"
406 "mov r6, r6, lsr #8 \r\n"
407 "orr r6, r6, r7, lsl #8 \r\n"
408 "orr r6, r6, r8, lsl #24 \r\n"
409 "mov r8, r8, lsr #8 \r\n"
410 "orr r8, r8, r9, lsl #8 \r\n"
411 "orr r8, r8, r10, lsl #24 \r\n"
412 "mov r10, r10, lsr #8 \r\n"
413 "stmia %[buf]!, { r2, r4, r6, r8 } \r\n"
414 "strb r10, [%[buf]], #1 \r\n"
415 : [buf]"+&r"(*buf)
416 : [data]"r"(&MMC_DATA_FIFO)
417 : "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
419 break;
420 case 2:
421 asm volatile (
422 "ldmia %[data], { r2-r9 } \r\n"
423 "strh r2, [%[buf]], #2 \r\n"
424 "orr r3, r3, r4, lsl #16 \r\n"
425 "orr r5, r5, r6, lsl #16 \r\n"
426 "orr r7, r7, r8, lsl #16 \r\n"
427 "stmia %[buf]!, { r3, r5, r7 } \r\n"
428 "ldmia %[data], { r2-r8, r10 } \r\n"
429 "orr r2, r9, r2, lsl #16 \r\n"
430 "orr r3, r3, r4, lsl #16 \r\n"
431 "orr r5, r5, r6, lsl #16 \r\n"
432 "orr r7, r7, r8, lsl #16 \r\n"
433 "stmia %[buf]!, { r2, r3, r5, r7 } \r\n"
434 "strh r10, [%[buf]], #2 \r\n"
435 : [buf]"+&r"(*buf)
436 : [data]"r"(&MMC_DATA_FIFO)
437 : "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
439 break;
440 case 3:
441 asm volatile (
442 "ldmia %[data], { r2-r9 } \r\n"
443 "orr r3, r2, r3, lsl #16 \r\n"
444 "strb r3, [%[buf]], #1 \r\n"
445 "mov r3, r3, lsr #8 \r\n"
446 "orr r3, r3, r4, lsl #24 \r\n"
447 "mov r4, r4, lsr #8 \r\n"
448 "orr r5, r4, r5, lsl #8 \r\n"
449 "orr r5, r5, r6, lsl #24 \r\n"
450 "mov r6, r6, lsr #8 \r\n"
451 "orr r7, r6, r7, lsl #8 \r\n"
452 "orr r7, r7, r8, lsl #24 \r\n"
453 "mov r8, r8, lsr #8 \r\n"
454 "orr r2, r8, r9, lsl #8 \r\n"
455 "stmia %[buf]!, { r3, r5, r7 } \r\n"
456 "ldmia %[data], { r3-r10 } \r\n"
457 "orr r2, r2, r3, lsl #24 \r\n"
458 "mov r3, r3, lsr #8 \r\n"
459 "orr r4, r3, r4, lsl #8 \r\n"
460 "orr r4, r4, r5, lsl #24 \r\n"
461 "mov r5, r5, lsr #8 \r\n"
462 "orr r6, r5, r6, lsl #8 \r\n"
463 "orr r6, r6, r7, lsl #24 \r\n"
464 "mov r7, r7, lsr #8 \r\n"
465 "orr r8, r7, r8, lsl #8 \r\n"
466 "orr r8, r8, r9, lsl #24 \r\n"
467 "mov r9, r9, lsr #8 \r\n"
468 "orr r10, r9, r10, lsl #8 \r\n"
469 "stmia %[buf]!, { r2, r4, r6, r8 } \r\n"
470 "strh r10, [%[buf]], #2 \r\n"
471 "mov r10, r10, lsr #16 \r\n"
472 "strb r10, [%[buf]], #1 \r\n"
473 : [buf]"+&r"(*buf)
474 : [data]"r"(&MMC_DATA_FIFO)
475 : "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
477 break;
481 static inline void copy_read_sectors_slow(unsigned char** buf)
483 int cnt = FIFO_LEN;
484 int t;
486 /* Copy one chunk of 16 words */
487 asm volatile (
488 "1: \r\n"
489 "ldrh %[t], [%[data]] \r\n"
490 "strb %[t], [%[buf]], #1 \r\n"
491 "mov %[t], %[t], lsr #8 \r\n"
492 "strb %[t], [%[buf]], #1 \r\n"
493 "subs %[cnt], %[cnt], #1 \r\n"
494 "bgt 1b \r\n"
495 : [cnt]"+&r"(cnt), [buf]"+&r"(*buf),
496 [t]"=&r"(t)
497 : [data]"r"(&MMC_DATA_FIFO)
501 /* Writes have to be kept slow for now */
502 static inline void copy_write_sectors(const unsigned char** buf)
504 int cnt = FIFO_LEN - 1;
505 unsigned t;
506 long time;
508 time = USEC_TIMER + 3;
509 if (((intptr_t)*buf & 3) == 0)
511 asm volatile (
512 "ldmia %[buf]!, { r3, r5, r7, r9 } \r\n"
513 "mov r4, r3, lsr #16 \r\n"
514 "mov r6, r5, lsr #16 \r\n"
515 "mov r8, r7, lsr #16 \r\n"
516 "mov r10, r9, lsr #16 \r\n"
517 "stmia %[data], { r3-r10 } \r\n"
518 "ldmia %[buf]!, { r3, r5, r7, r9 } \r\n"
519 "mov r4, r3, lsr #16 \r\n"
520 "mov r6, r5, lsr #16 \r\n"
521 "mov r8, r7, lsr #16 \r\n"
522 "mov %[t], r9, lsr #16 \r\n"
523 "stmia %[data], { r3-r9 } \r\n"
524 : [buf]"+&r"(*buf), [t]"=&r"(t)
525 : [data]"r"(&MMC_DATA_FIFO)
526 : "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
529 else
533 t = *(*buf)++;
534 t |= *(*buf)++ << 8;
535 MMC_DATA_FIFO = t;
536 } while (--cnt > 0); /* tail loop is faster */
537 t = *(*buf)++;
538 t |= *(*buf)++ << 8;
540 /* Don't write the last word before at least 3 usec have elapsed since FIFO_EMPTY */
541 /* This prevents the 'two bytes inserted' bug. */
543 while (!TIME_AFTER(USEC_TIMER, time));
544 MMC_DATA_FIFO = t;
547 static int sd_select_bank(unsigned char bank)
549 unsigned char card_data[512];
550 const unsigned char* write_buf;
551 int i, ret;
553 memset(card_data, 0, 512);
555 ret = sd_wait_for_state(SD_TRAN, EC_TRAN_SEL_BANK);
556 if (ret < 0)
557 return ret;
559 MMC_BLKLEN = 512;
560 MMC_NUMBLK = 1;
562 ret = sd_command(35, 0, NULL, /* CMD35 is vendor specific */
563 0x1c00 | CMDAT_WR_RD | CMDAT_DATA_EN | CMDAT_RES_TYPE1);
564 if (ret < 0)
565 return ret;
567 MMC_SD_STATE = SD_PRG;
569 card_data[0] = bank;
571 /* Write the card data */
572 write_buf = card_data;
573 for (i = 0; i < SD_BLOCK_SIZE/2; i += FIFO_LEN)
575 /* Wait for the FIFO to empty */
576 if (sd_poll_status(STAT_XMIT_FIFO_EMPTY, 10000))
578 copy_write_sectors(&write_buf); /* Copy one chunk of 16 words */
579 continue;
582 return -EC_FIFO_SEL_BANK_EMPTY;
585 if (!sd_poll_status(STAT_PRG_DONE, 10000))
586 return -EC_FIFO_SEL_BANK_DONE;
588 currcard->current_bank = bank;
590 return 0;
593 static void sd_card_mux(int card_no)
595 /* Set the current card mux */
596 #if defined(SANSA_E200)
597 if (card_no == 0)
599 GPO32_VAL |= 0x4;
601 GPIO_CLEAR_BITWISE(GPIOA_ENABLE, 0x7a);
602 GPIO_CLEAR_BITWISE(GPIOA_OUTPUT_EN, 0x7a);
603 GPIO_SET_BITWISE(GPIOD_ENABLE, 0x1f);
604 GPIO_SET_BITWISE(GPIOD_OUTPUT_VAL, 0x1f);
605 GPIO_SET_BITWISE(GPIOD_OUTPUT_EN, 0x1f);
607 outl((inl(0x70000014) & ~(0x3ffff)) | 0x255aa, 0x70000014);
609 else
611 GPO32_VAL &= ~0x4;
613 GPIO_CLEAR_BITWISE(GPIOD_ENABLE, 0x1f);
614 GPIO_CLEAR_BITWISE(GPIOD_OUTPUT_EN, 0x1f);
615 GPIO_SET_BITWISE(GPIOA_ENABLE, 0x7a);
616 GPIO_SET_BITWISE(GPIOA_OUTPUT_VAL, 0x7a);
617 GPIO_SET_BITWISE( GPIOA_OUTPUT_EN, 0x7a);
619 outl(inl(0x70000014) & ~(0x3ffff), 0x70000014);
621 #elif defined(SANSA_C200)
622 if (card_no == 0)
624 GPO32_VAL |= 0x4;
626 GPIO_CLEAR_BITWISE(GPIOD_ENABLE, 0x1f);
627 GPIO_CLEAR_BITWISE(GPIOD_OUTPUT_EN, 0x1f);
628 GPIO_SET_BITWISE(GPIOA_ENABLE, 0x7a);
629 GPIO_SET_BITWISE(GPIOA_OUTPUT_VAL, 0x7a);
630 GPIO_SET_BITWISE( GPIOA_OUTPUT_EN, 0x7a);
632 outl(inl(0x70000014) & ~(0x3ffff), 0x70000014);
634 else
636 GPO32_VAL &= ~0x4;
638 GPIO_CLEAR_BITWISE(GPIOA_ENABLE, 0x7a);
639 GPIO_CLEAR_BITWISE(GPIOA_OUTPUT_EN, 0x7a);
640 GPIO_SET_BITWISE(GPIOD_ENABLE, 0x1f);
641 GPIO_SET_BITWISE(GPIOD_OUTPUT_VAL, 0x1f);
642 GPIO_SET_BITWISE(GPIOD_OUTPUT_EN, 0x1f);
644 outl((inl(0x70000014) & ~(0x3ffff)) | 0x255aa, 0x70000014);
646 #elif defined(PHILIPS_SA9200)
647 /* only 1 "card" (no external memory card) */
648 (void)card_no;
650 GPIO_SET_BITWISE(GPIOH_ENABLE, 0x80);
651 GPIO_SET_BITWISE(GPIOH_OUTPUT_EN, 0x80);
653 outl(0x255aa, 0x70000014);
655 GPIO_CLEAR_BITWISE(GPIOA_ENABLE, 0x04);
656 GPIO_CLEAR_BITWISE(GPIOA_OUTPUT_EN, 0x04);
658 GPIO_CLEAR_BITWISE(GPIOA_ENABLE, 0x7a);
659 GPIO_CLEAR_BITWISE(GPIOA_OUTPUT_EN, 0x7a);
661 GPIO_SET_BITWISE(GPIOH_OUTPUT_VAL, 0x80);
662 GPIO_SET_BITWISE(GPIOH_OUTPUT_EN, 0x80);
663 #endif
666 static void sd_init_device(int card_no)
668 /* SD Protocol registers */
669 #ifdef HAVE_HOTSWAP
670 unsigned long response = 0;
671 #endif
672 unsigned int i;
673 unsigned char carddata[512];
674 unsigned char *dataptr;
675 unsigned long temp_reg[4];
676 int ret;
678 /* Enable and initialise controller */
679 MMC_CLKRT = 6; /* switch to lowest clock rate */
681 /* Initialise card data as blank */
682 memset(currcard, 0, sizeof(*currcard));
684 /* Switch card mux to card to initialize */
685 sd_card_mux(card_no);
687 /* Init NAND */
688 MMC_INIT_1 |= (1 << 15);
689 MMC_INIT_2 |= (1 << 15);
690 MMC_INIT_2 &= ~(3 << 12);
691 MMC_INIT_2 |= (1 << 13);
692 MMC_INIT_1 &= ~(3 << 12);
693 MMC_INIT_1 |= (1 << 13);
695 DEV_EN |= DEV_ATA; /* Enable controller */
696 DEV_RS |= DEV_ATA; /* Reset controller */
697 DEV_RS &=~DEV_ATA; /* Clear Reset */
699 MMC_SD_STATE = SD_TRAN;
701 MMC_I_MASK = 0xf; /* disable interrupts */
703 ret = sd_command(SD_GO_IDLE_STATE, 0, NULL, 0x100);
704 if (ret < 0)
705 goto card_init_error;
707 check_time[EC_POWER_UP] = USEC_TIMER;
709 #ifdef HAVE_HOTSWAP
710 /* Check for SDHC:
711 - non-SDHC cards simply ignore SD_SEND_IF_COND (CMD8) and we get error -219,
712 which we can just ignore and assume we're dealing with standard SD.
713 - SDHC cards echo back the argument into the response. This is how we
714 tell if the card is SDHC.
716 ret = sd_command(SD_SEND_IF_COND,0x1aa, &response,
717 CMDAT_DATA_EN | CMDAT_RES_TYPE3);
718 if ( (ret < 0) && (ret!=-219) )
719 goto card_init_error;
720 #endif
722 while ((currcard->ocr & (1 << 31)) == 0) /* until card is powered up */
724 ret = sd_command(SD_APP_CMD, currcard->rca, NULL, CMDAT_RES_TYPE1);
725 if (ret < 0)
726 goto card_init_error;
728 #ifdef HAVE_HOTSWAP
729 if(response == 0x1aa)
731 /* SDHC */
732 ret = sd_command(SD_APP_OP_COND, (1<<30)|0x100000,
733 &currcard->ocr, CMDAT_RES_TYPE3);
735 else
736 #endif /* HAVE_HOTSWAP */
738 /* SD Standard */
739 ret = sd_command(SD_APP_OP_COND, 0x100000, &currcard->ocr,
740 CMDAT_RES_TYPE3);
743 if (ret < 0)
744 goto card_init_error;
746 if (!sd_check_timeout(5000000, EC_POWER_UP))
748 ret = -EC_POWER_UP;
749 goto card_init_error;
753 ret = sd_command(SD_ALL_SEND_CID, 0, temp_reg, CMDAT_RES_TYPE2);
754 if (ret < 0)
755 goto card_init_error;
757 for(i=0; i<4; i++)
758 currcard->cid[i] = temp_reg[3-i];
760 ret = sd_command(SD_SEND_RELATIVE_ADDR, 0, &currcard->rca, CMDAT_RES_TYPE1);
761 if (ret < 0)
762 goto card_init_error;
764 ret = sd_command(SD_SEND_CSD, currcard->rca, temp_reg, CMDAT_RES_TYPE2);
765 if (ret < 0)
766 goto card_init_error;
768 for(i=0; i<4; i++)
769 currcard->csd[i] = temp_reg[3-i];
771 sd_parse_csd(currcard);
773 MMC_CLKRT = 0; /* switch to highest clock rate */
775 ret = sd_command(SD_SELECT_CARD, currcard->rca, NULL,
776 0x80 | CMDAT_RES_TYPE1);
777 if (ret < 0)
778 goto card_init_error;
780 ret = sd_command(SD_APP_CMD, currcard->rca, NULL, CMDAT_RES_TYPE1);
781 if (ret < 0)
782 goto card_init_error;
784 ret = sd_command(SD_SET_BUS_WIDTH, currcard->rca | 2, NULL,
785 CMDAT_RES_TYPE1); /* 4 bit */
786 if (ret < 0)
787 goto card_init_error;
789 ret = sd_command(SD_SET_BLOCKLEN, currcard->blocksize, NULL,
790 CMDAT_RES_TYPE1);
791 if (ret < 0)
792 goto card_init_error;
794 MMC_BLKLEN = currcard->blocksize;
796 /* If this card is >4GB & not SDHC, then we need to enable bank switching */
797 if( (currcard->numblocks >= BLOCKS_PER_BANK) &&
798 ((currcard->ocr & (1<<30)) == 0) )
800 MMC_SD_STATE = SD_TRAN;
801 MMC_NUMBLK = 1;
803 ret = sd_command(SD_SWITCH_FUNC, 0x80ffffef, NULL,
804 0x1c00 | CMDAT_DATA_EN | CMDAT_RES_TYPE1);
805 if (ret < 0)
806 goto card_init_error;
808 /* Read 512 bytes from the card.
809 The first 512 bits contain the status information
810 TODO: Do something useful with this! */
811 dataptr = carddata;
812 for (i = 0; i < SD_BLOCK_SIZE/2; i += FIFO_LEN)
814 /* Wait for the FIFO to be full */
815 if (sd_poll_status(STAT_RECV_FIFO_FULL, 100000))
817 copy_read_sectors_slow(&dataptr);
818 continue;
821 ret = -EC_FIFO_ENA_BANK_EMPTY;
822 goto card_init_error;
826 currcard->initialized = 1;
827 return;
829 /* Card failed to initialize so disable it */
830 card_init_error:
831 currcard->initialized = ret;
834 /* lock must already be aquired */
835 static void sd_select_device(int card_no)
837 currcard = &card_info[card_no];
839 if (card_no == 0)
841 /* Main card always gets a chance */
842 sd_status[0].retry = 0;
845 if (currcard->initialized > 0)
847 /* This card is already initialized - switch to it */
848 sd_card_mux(card_no);
849 return;
852 if (currcard->initialized == 0)
854 /* Card needs (re)init */
855 sd_init_device(card_no);
859 /* API Functions */
861 int sd_read_sectors(IF_MD2(int drive,) unsigned long start, int incount,
862 void* inbuf)
864 #ifndef HAVE_MULTIDRIVE
865 const int drive = 0;
866 #endif
867 int ret;
868 unsigned char *buf, *buf_end;
869 unsigned int bank;
871 /* TODO: Add DMA support. */
873 mutex_lock(&sd_mtx);
874 sd_enable(true);
875 led(true);
877 sd_read_retry:
878 if (drive != 0 && !card_detect_target())
880 /* no external sd-card inserted */
881 ret = -EC_NOCARD;
882 goto sd_read_error;
885 sd_select_device(drive);
887 if (currcard->initialized < 0)
889 ret = currcard->initialized;
890 goto sd_read_error;
893 last_disk_activity = current_tick;
895 /* Only switch banks with non-SDHC cards */
896 if((currcard->ocr & (1<<30))==0)
898 bank = start / BLOCKS_PER_BANK;
900 if (currcard->current_bank != bank)
902 ret = sd_select_bank(bank);
903 if (ret < 0)
904 goto sd_read_error;
907 start -= bank * BLOCKS_PER_BANK;
910 ret = sd_wait_for_state(SD_TRAN, EC_TRAN_READ_ENTRY);
911 if (ret < 0)
912 goto sd_read_error;
914 MMC_NUMBLK = incount;
916 #ifdef HAVE_HOTSWAP
917 if(currcard->ocr & (1<<30) )
919 /* SDHC */
920 ret = sd_command(SD_READ_MULTIPLE_BLOCK, start, NULL,
921 0x1c00 | CMDAT_BUSY | CMDAT_DATA_EN | CMDAT_RES_TYPE1);
923 else
924 #endif
926 ret = sd_command(SD_READ_MULTIPLE_BLOCK, start * SD_BLOCK_SIZE, NULL,
927 0x1c00 | CMDAT_BUSY | CMDAT_DATA_EN | CMDAT_RES_TYPE1);
929 if (ret < 0)
930 goto sd_read_error;
932 /* TODO: Don't assume SD_BLOCK_SIZE == SECTOR_SIZE */
934 buf_end = (unsigned char *)inbuf + incount * currcard->blocksize;
935 for (buf = inbuf; buf < buf_end;)
937 /* Wait for the FIFO to be full */
938 if (sd_poll_status(STAT_RECV_FIFO_FULL, 0x80000))
940 copy_read_sectors_fast(&buf); /* Copy one chunk of 16 words */
941 /* TODO: Switch bank if necessary */
942 continue;
945 ret = -EC_FIFO_READ_FULL;
946 goto sd_read_error;
949 last_disk_activity = current_tick;
951 ret = sd_command(SD_STOP_TRANSMISSION, 0, NULL, CMDAT_RES_TYPE1);
952 if (ret < 0)
953 goto sd_read_error;
955 ret = sd_wait_for_state(SD_TRAN, EC_TRAN_READ_EXIT);
956 if (ret < 0)
957 goto sd_read_error;
959 while (1)
961 led(false);
962 sd_enable(false);
963 mutex_unlock(&sd_mtx);
965 return ret;
967 sd_read_error:
968 if (sd_status[drive].retry < sd_status[drive].retry_max
969 && ret != -EC_NOCARD)
971 sd_status[drive].retry++;
972 currcard->initialized = 0;
973 goto sd_read_retry;
978 int sd_write_sectors(IF_MD2(int drive,) unsigned long start, int count,
979 const void* outbuf)
981 /* Write support is not finished yet */
982 /* TODO: The standard suggests using ACMD23 prior to writing multiple blocks
983 to improve performance */
984 #ifndef HAVE_MULTIDRIVE
985 const int drive = 0;
986 #endif
987 int ret;
988 const unsigned char *buf, *buf_end;
989 unsigned int bank;
991 mutex_lock(&sd_mtx);
992 sd_enable(true);
993 led(true);
995 sd_write_retry:
996 if (drive != 0 && !card_detect_target())
998 /* no external sd-card inserted */
999 ret = -EC_NOCARD;
1000 goto sd_write_error;
1003 sd_select_device(drive);
1005 if (currcard->initialized < 0)
1007 ret = currcard->initialized;
1008 goto sd_write_error;
1011 /* Only switch banks with non-SDHC cards */
1012 if((currcard->ocr & (1<<30))==0)
1014 bank = start / BLOCKS_PER_BANK;
1016 if (currcard->current_bank != bank)
1018 ret = sd_select_bank(bank);
1019 if (ret < 0)
1020 goto sd_write_error;
1023 start -= bank * BLOCKS_PER_BANK;
1026 check_time[EC_WRITE_TIMEOUT] = USEC_TIMER;
1028 ret = sd_wait_for_state(SD_TRAN, EC_TRAN_WRITE_ENTRY);
1029 if (ret < 0)
1030 goto sd_write_error;
1032 MMC_NUMBLK = count;
1034 #ifdef HAVE_HOTSWAP
1035 if(currcard->ocr & (1<<30) )
1037 /* SDHC */
1038 ret = sd_command(SD_WRITE_MULTIPLE_BLOCK, start, NULL,
1039 CMDAT_WR_RD | CMDAT_DATA_EN | CMDAT_RES_TYPE1);
1041 else
1042 #endif
1044 ret = sd_command(SD_WRITE_MULTIPLE_BLOCK, start*SD_BLOCK_SIZE, NULL,
1045 CMDAT_WR_RD | CMDAT_DATA_EN | CMDAT_RES_TYPE1);
1047 if (ret < 0)
1048 goto sd_write_error;
1050 buf_end = outbuf + count * currcard->blocksize - 2*FIFO_LEN;
1052 for (buf = outbuf; buf <= buf_end;)
1054 if (buf == buf_end)
1056 /* Set MMC_SD_STATE to SD_PRG for the last buffer fill */
1057 MMC_SD_STATE = SD_PRG;
1060 copy_write_sectors(&buf); /* Copy one chunk of 16 words */
1061 /* TODO: Switch bank if necessary */
1063 /* Wait for the FIFO to empty */
1064 if (!sd_poll_status(STAT_XMIT_FIFO_EMPTY, 0x80000))
1066 ret = -EC_FIFO_WR_EMPTY;
1067 goto sd_write_error;
1071 last_disk_activity = current_tick;
1073 if (!sd_poll_status(STAT_PRG_DONE, 0x80000))
1075 ret = -EC_FIFO_WR_DONE;
1076 goto sd_write_error;
1079 ret = sd_command(SD_STOP_TRANSMISSION, 0, NULL, CMDAT_RES_TYPE1);
1080 if (ret < 0)
1081 goto sd_write_error;
1083 ret = sd_wait_for_state(SD_TRAN, EC_TRAN_WRITE_EXIT);
1084 if (ret < 0)
1085 goto sd_write_error;
1087 while (1)
1089 led(false);
1090 sd_enable(false);
1091 mutex_unlock(&sd_mtx);
1093 return ret;
1095 sd_write_error:
1096 if (sd_status[drive].retry < sd_status[drive].retry_max
1097 && ret != -EC_NOCARD)
1099 sd_status[drive].retry++;
1100 currcard->initialized = 0;
1101 goto sd_write_retry;
1106 static void sd_thread(void) __attribute__((noreturn));
1107 static void sd_thread(void)
1109 struct queue_event ev;
1110 bool idle_notified = false;
1112 while (1)
1114 queue_wait_w_tmo(&sd_queue, &ev, HZ);
1116 switch ( ev.id )
1118 #ifdef HAVE_HOTSWAP
1119 case SYS_HOTSWAP_INSERTED:
1120 case SYS_HOTSWAP_EXTRACTED:
1121 fat_lock(); /* lock-out FAT activity first -
1122 prevent deadlocking via disk_mount that
1123 would cause a reverse-order attempt with
1124 another thread */
1125 mutex_lock(&sd_mtx); /* lock-out card activity - direct calls
1126 into driver that bypass the fat cache */
1128 /* We now have exclusive control of fat cache and ata */
1130 disk_unmount(sd_first_drive+1); /* release "by force", ensure file
1131 descriptors aren't leaked and any busy
1132 ones are invalid if mounting */
1134 /* Force card init for new card, re-init for re-inserted one or
1135 * clear if the last attempt to init failed with an error. */
1136 card_info[1].initialized = 0;
1137 sd_status[1].retry = 0;
1139 if (ev.id == SYS_HOTSWAP_INSERTED)
1140 disk_mount(sd_first_drive+1);
1142 queue_broadcast(SYS_FS_CHANGED, 0);
1144 /* Access is now safe */
1145 mutex_unlock(&sd_mtx);
1146 fat_unlock();
1147 break;
1148 #endif
1149 case SYS_TIMEOUT:
1150 if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ)))
1152 idle_notified = false;
1154 else
1156 /* never let a timer wrap confuse us */
1157 next_yield = USEC_TIMER;
1159 if (!idle_notified)
1161 call_storage_idle_notifys(false);
1162 idle_notified = true;
1165 break;
1166 case SYS_USB_CONNECTED:
1167 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1168 /* Wait until the USB cable is extracted again */
1169 usb_wait_for_disconnect(&sd_queue);
1171 break;
1172 case SYS_USB_DISCONNECTED:
1173 usb_acknowledge(SYS_USB_DISCONNECTED_ACK);
1174 break;
1179 void sd_enable(bool on)
1181 if(on)
1183 DEV_EN |= DEV_ATA; /* Enable controller */
1185 else
1187 DEV_EN &= ~DEV_ATA; /* Disable controller */
1191 #ifdef HAVE_HOTSWAP
1192 void card_enable_monitoring_target(bool on)
1194 if (on)
1196 #ifdef SANSA_E200
1197 GPIO_SET_BITWISE(GPIOA_INT_EN, 0x80);
1198 #elif defined(SANSA_C200)
1199 GPIO_SET_BITWISE(GPIOL_INT_EN, 0x08);
1200 #endif
1202 else
1204 #ifdef SANSA_E200
1205 GPIO_CLEAR_BITWISE(GPIOA_INT_EN, 0x80);
1206 #elif defined(SANSA_C200)
1207 GPIO_CLEAR_BITWISE(GPIOL_INT_EN, 0x08);
1208 #endif
1211 #endif
1213 int sd_init(void)
1215 int ret = 0;
1217 if (!initialized)
1218 mutex_init(&sd_mtx);
1220 mutex_lock(&sd_mtx);
1222 led(false);
1224 if (!initialized)
1226 initialized = true;
1228 /* init controller */
1229 #if defined(PHILIPS_SA9200)
1230 GPIOA_ENABLE = 0x00;
1231 GPIO_SET_BITWISE(GPIOD_ENABLE, 0x01);
1232 #else
1233 outl(inl(0x70000088) & ~(0x4), 0x70000088);
1234 outl(inl(0x7000008c) & ~(0x4), 0x7000008c);
1235 GPO32_ENABLE |= 0x4;
1237 GPIO_SET_BITWISE(GPIOG_ENABLE, (0x3 << 5));
1238 GPIO_SET_BITWISE(GPIOG_OUTPUT_EN, (0x3 << 5));
1239 GPIO_SET_BITWISE(GPIOG_OUTPUT_VAL, (0x3 << 5));
1240 #endif
1242 #ifdef HAVE_HOTSWAP
1243 /* enable card detection port - mask interrupt first */
1244 #ifdef SANSA_E200
1245 GPIO_CLEAR_BITWISE(GPIOA_INT_EN, 0x80);
1247 GPIO_CLEAR_BITWISE(GPIOA_OUTPUT_EN, 0x80);
1248 GPIO_SET_BITWISE(GPIOA_ENABLE, 0x80);
1249 #elif defined SANSA_C200
1250 GPIO_CLEAR_BITWISE(GPIOL_INT_EN, 0x08);
1252 GPIO_CLEAR_BITWISE(GPIOL_OUTPUT_EN, 0x08);
1253 GPIO_SET_BITWISE(GPIOL_ENABLE, 0x08);
1254 #endif
1255 #endif
1256 sd_select_device(0);
1258 if (currcard->initialized < 0)
1259 ret = currcard->initialized;
1261 queue_init(&sd_queue, true);
1262 create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0,
1263 sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE)
1264 IF_COP(, CPU));
1266 /* enable interupt for the mSD card */
1267 sleep(HZ/10);
1268 #ifdef HAVE_HOTSWAP
1269 #ifdef SANSA_E200
1270 CPU_INT_EN = HI_MASK;
1271 CPU_HI_INT_EN = GPIO0_MASK;
1273 GPIOA_INT_LEV = (0x80 << 8) | (~GPIOA_INPUT_VAL & 0x80);
1275 GPIOA_INT_CLR = 0x80;
1276 #elif defined SANSA_C200
1277 CPU_INT_EN = HI_MASK;
1278 CPU_HI_INT_EN = GPIO2_MASK;
1280 GPIOL_INT_LEV = (0x08 << 8) | (~GPIOL_INPUT_VAL & 0x08);
1282 GPIOL_INT_CLR = 0x08;
1283 #endif
1284 #endif
1287 mutex_unlock(&sd_mtx);
1289 return ret;
1292 tCardInfo *card_get_info_target(int card_no)
1294 return &card_info[card_no];
1296 #ifdef HAVE_HOTSWAP
1297 static int sd1_oneshot_callback(struct timeout *tmo)
1299 (void)tmo;
1301 /* This is called only if the state was stable for 300ms - check state
1302 * and post appropriate event. */
1303 if (card_detect_target())
1304 queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
1305 else
1306 queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
1308 return 0;
1311 /* called on insertion/removal interrupt */
1312 void microsd_int(void)
1314 static struct timeout sd1_oneshot;
1316 #ifdef SANSA_E200
1317 GPIO_CLEAR_BITWISE(GPIOA_INT_EN, 0x80);
1318 GPIOA_INT_LEV = (0x80 << 8) | (~GPIOA_INPUT_VAL & 0x80);
1319 GPIOA_INT_CLR = 0x80;
1320 GPIO_SET_BITWISE(GPIOA_INT_EN, 0x80);
1322 #elif defined SANSA_C200
1323 GPIO_CLEAR_BITWISE(GPIOL_INT_EN, 0x08);
1324 GPIOL_INT_LEV = (0x08 << 8) | (~GPIOL_INPUT_VAL & 0x08);
1325 GPIOL_INT_CLR = 0x08;
1326 GPIO_SET_BITWISE(GPIOL_INT_EN, 0x08);
1327 #endif
1328 timeout_register(&sd1_oneshot, sd1_oneshot_callback, (3*HZ/10), 0);
1330 #endif /* HAVE_HOTSWAP */
1332 long sd_last_disk_activity(void)
1334 return last_disk_activity;
1337 #ifdef HAVE_HOTSWAP
1338 bool sd_removable(IF_MD_NONVOID(int drive))
1340 #ifndef HAVE_MULTIDRIVE
1341 const int drive=0;
1342 #endif
1343 return (drive==1);
1346 bool sd_present(IF_MD_NONVOID(int drive))
1348 #ifndef HAVE_MULTIDRIVE
1349 const int drive=0;
1350 #endif
1351 if(drive==0)
1353 return true;
1355 else
1357 return card_detect_target();
1360 #endif
1362 #ifdef CONFIG_STORAGE_MULTI
1363 int sd_num_drives(int first_drive)
1365 #ifdef HAVE_HOTSWAP
1366 /* Store which logical drive number(s) we have been assigned */
1367 sd_first_drive = first_drive;
1368 #else
1369 (void)first_drive;
1370 #endif
1372 #ifdef HAVE_MULTIDRIVE
1373 return 2;
1374 #else
1375 return 1;
1376 #endif
1378 #endif