Rev 1271 Rev 1858
1 /*-----------------------------------------------------------------------*/ 1 /*-----------------------------------------------------------------------*/
2 /* MMC/SDC (in SPI mode) control module (C)ChaN, 2006 */ 2 /* MMC/SDC (in SPI mode) control module (C)ChaN, 2006 */
3 /*-----------------------------------------------------------------------*/ 3 /*-----------------------------------------------------------------------*/
4 /* Only rcvr_spi(), xmit_spi(), disk_timerproc(), disk_initialize () and */ 4 /* Only rcvr_spi(), xmit_spi(), disk_timerproc(), disk_initialize () and */
5 /* some macros are platform dependent. */ 5 /* some macros are platform dependent. */
6 /*-----------------------------------------------------------------------*/ 6 /*-----------------------------------------------------------------------*/
7   7  
8   8  
9 #include <avr/io.h> 9 #include <avr/io.h>
10 #include "diskio.h" 10 #include "diskio.h"
11   11  
12   12  
13 /* Definitions for MMC/SDC command */ 13 /* Definitions for MMC/SDC command */
14 #define CMD0 (0x40+0) /* GO_IDLE_STATE */ 14 #define CMD0 (0x40+0) /* GO_IDLE_STATE */
15 #define CMD1 (0x40+1) /* SEND_OP_COND */ 15 #define CMD1 (0x40+1) /* SEND_OP_COND */
16 #define CMD8 (0x40+8) /* SEND_IF_COND */ 16 #define CMD8 (0x40+8) /* SEND_IF_COND */
17 #define CMD9 (0x40+9) /* SEND_CSD */ 17 #define CMD9 (0x40+9) /* SEND_CSD */
18 #define CMD10 (0x40+10) /* SEND_CID */ 18 #define CMD10 (0x40+10) /* SEND_CID */
19 #define CMD12 (0x40+12) /* STOP_TRANSMISSION */ 19 #define CMD12 (0x40+12) /* STOP_TRANSMISSION */
20 #define CMD16 (0x40+16) /* SET_BLOCKLEN */ 20 #define CMD16 (0x40+16) /* SET_BLOCKLEN */
21 #define CMD17 (0x40+17) /* READ_SINGLE_BLOCK */ 21 #define CMD17 (0x40+17) /* READ_SINGLE_BLOCK */
22 #define CMD18 (0x40+18) /* READ_MULTIPLE_BLOCK */ 22 #define CMD18 (0x40+18) /* READ_MULTIPLE_BLOCK */
23 #define CMD23 (0x40+23) /* SET_BLOCK_COUNT */ 23 #define CMD23 (0x40+23) /* SET_BLOCK_COUNT */
24 #define CMD24 (0x40+24) /* WRITE_BLOCK */ 24 #define CMD24 (0x40+24) /* WRITE_BLOCK */
25 #define CMD25 (0x40+25) /* WRITE_MULTIPLE_BLOCK */ 25 #define CMD25 (0x40+25) /* WRITE_MULTIPLE_BLOCK */
26 #define CMD41 (0x40+41) /* SEND_OP_COND (ACMD) */ 26 #define CMD41 (0x40+41) /* SEND_OP_COND (ACMD) */
27 #define CMD55 (0x40+55) /* APP_CMD */ 27 #define CMD55 (0x40+55) /* APP_CMD */
28 #define CMD58 (0x40+58) /* READ_OCR */ 28 #define CMD58 (0x40+58) /* READ_OCR */
29   29  
30   30  
31 /* Control signals (Platform dependent) */ 31 /* Control signals (Platform dependent) */
32 #define SELECT() PORTB &= ~_BV(PB2) /* MMC CS = L */ 32 #define SELECT() PORTB &= ~_BV(PB2) /* MMC CS = L */
33 #define DESELECT() PORTB |= _BV(PB2) /* MMC CS = H */ 33 #define DESELECT() PORTB |= _BV(PB2) /* MMC CS = H */
34   34  
35 #define SOCKPORT PINB /* Socket contact port */ 35 #define SOCKPORT PINB /* Socket contact port */
36 #define SOCKINS 0x01 /* Card detect switch (PB0) */ 36 #define SOCKINS 0x01 /* Card detect switch (PB0) */
37   37  
38   38  
39   39  
40 /*-------------------------------------------------------------------------- 40 /*--------------------------------------------------------------------------
41   41  
42 Module Private Functions 42 Module Private Functions
43   43  
44 ---------------------------------------------------------------------------*/ 44 ---------------------------------------------------------------------------*/
45   45  
46 static volatile 46 static volatile
47 DSTATUS Stat = STA_NOINIT; /* Disk status */ 47 DSTATUS Stat = STA_NOINIT; /* Disk status */
48   48  
49 static volatile 49 static volatile
50 BYTE Timer1, Timer2; /* 100Hz decrement timer */ 50 BYTE Timer1, Timer2; /* 100Hz decrement timer */
51   51  
52 static 52 static
53 BYTE CardType; /* b0:MMC, b1:SDC, b2:Block addressing */ 53 BYTE CardType; /* b0:MMC, b1:SDC, b2:Block addressing */
54   54  
55   55  
56   56  
57 /*-----------------------------------------------------------------------*/ 57 /*-----------------------------------------------------------------------*/
58 /* Transmit a byte to MMC via SPI (Platform dependent) */ 58 /* Transmit a byte to MMC via SPI (Platform dependent) */
59 /*-----------------------------------------------------------------------*/ 59 /*-----------------------------------------------------------------------*/
60   60  
61 #define xmit_spi(dat) SPDR=(dat); loop_until_bit_is_set(SPSR,SPIF) 61 #define xmit_spi(dat) SPDR=(dat); loop_until_bit_is_set(SPSR,SPIF)
62   62  
63   63  
64   64  
65 /*-----------------------------------------------------------------------*/ 65 /*-----------------------------------------------------------------------*/
66 /* Receive a byte from MMC via SPI (Platform dependent) */ 66 /* Receive a byte from MMC via SPI (Platform dependent) */
67 /*-----------------------------------------------------------------------*/ 67 /*-----------------------------------------------------------------------*/
68   68  
69 static 69 static
70 BYTE rcvr_spi (void) 70 BYTE rcvr_spi (void)
71 { 71 {
72 SPDR = 0xFF; 72 SPDR = 0xFF;
73 loop_until_bit_is_set(SPSR, SPIF); 73 loop_until_bit_is_set(SPSR, SPIF);
74 return SPDR; 74 return SPDR;
75 } 75 }
76   76  
77 /* Alternative macro to receive data fast */ 77 /* Alternative macro to receive data fast */
78 #define rcvr_spi_m(dst) SPDR=0xFF; loop_until_bit_is_set(SPSR,SPIF); *(dst)=SPDR 78 #define rcvr_spi_m(dst) SPDR=0xFF; loop_until_bit_is_set(SPSR,SPIF); *(dst)=SPDR
79   79  
80   80  
81   81  
82 /*-----------------------------------------------------------------------*/ 82 /*-----------------------------------------------------------------------*/
83 /* Wait for card ready */ 83 /* Wait for card ready */
84 /*-----------------------------------------------------------------------*/ 84 /*-----------------------------------------------------------------------*/
85   85  
86 static 86 static
87 BYTE wait_ready (void) 87 BYTE wait_ready (void)
88 { 88 {
89 BYTE res; 89 BYTE res;
90   90  
91   91  
92 Timer2 = 50; /* Wait for ready in timeout of 500ms */ 92 Timer2 = 50; /* Wait for ready in timeout of 500ms */
93 rcvr_spi(); 93 rcvr_spi();
94 do 94 do
95 res = rcvr_spi(); 95 res = rcvr_spi();
96 while ((res != 0xFF) && Timer2); 96 while ((res != 0xFF) && Timer2);
97   97  
98 return res; 98 return res;
99 } 99 }
100   100  
101   101  
102   102  
103 /*-----------------------------------------------------------------------*/ 103 /*-----------------------------------------------------------------------*/
104 /* Receive a data packet from MMC */ 104 /* Receive a data packet from MMC */
105 /*-----------------------------------------------------------------------*/ 105 /*-----------------------------------------------------------------------*/
106   106  
107 static 107 static
108 BOOL rcvr_datablock ( 108 BOOL rcvr_datablock (
109 BYTE *buff, /* Data buffer to store received data */ 109 BYTE *buff, /* Data buffer to store received data */
110 UINT btr /* Byte count (must be even number) */ 110 UINT btr /* Byte count (must be even number) */
111 ) 111 )
112 { 112 {
113 BYTE token; 113 BYTE token;
114   114  
115   115  
116 Timer1 = 10; 116 Timer1 = 10;
117 do { /* Wait for data packet in timeout of 100ms */ 117 do { /* Wait for data packet in timeout of 100ms */
118 token = rcvr_spi(); 118 token = rcvr_spi();
119 } while ((token == 0xFF) && Timer1); 119 } while ((token == 0xFF) && Timer1);
120 if(token != 0xFE) return FALSE; /* If not valid data token, retutn with error */ 120 if(token != 0xFE) return FALSE; /* If not valid data token, retutn with error */
121   121  
122 do { /* Receive the data block into buffer */ 122 do { /* Receive the data block into buffer */
123 rcvr_spi_m(buff++); 123 rcvr_spi_m(buff++);
124 rcvr_spi_m(buff++); 124 rcvr_spi_m(buff++);
125 } while (btr -= 2); 125 } while (btr -= 2);
126 rcvr_spi(); /* Discard CRC */ 126 rcvr_spi(); /* Discard CRC */
127 rcvr_spi(); 127 rcvr_spi();
128   128  
129 return TRUE; /* Return with success */ 129 return TRUE; /* Return with success */
130 } 130 }
131   131  
132   132  
133   133  
134 /*-----------------------------------------------------------------------*/ 134 /*-----------------------------------------------------------------------*/
135 /* Send a data packet to MMC */ 135 /* Send a data packet to MMC */
136 /*-----------------------------------------------------------------------*/ 136 /*-----------------------------------------------------------------------*/
137   137  
138 #if _READONLY == 0 138 #if _READONLY == 0
139 static 139 static
140 BOOL xmit_datablock ( 140 BOOL xmit_datablock (
141 const BYTE *buff, /* 512 byte data block to be transmitted */ 141 const BYTE *buff, /* 512 byte data block to be transmitted */
142 BYTE token /* Data/Stop token */ 142 BYTE token /* Data/Stop token */
143 ) 143 )
144 { 144 {
145 BYTE resp, wc; 145 BYTE resp, wc;
146   146  
147   147  
148 if (wait_ready() != 0xFF) return FALSE; 148 if (wait_ready() != 0xFF) return FALSE;
149   149  
150 xmit_spi(token); /* Xmit data token */ 150 xmit_spi(token); /* Xmit data token */
151 if (token != 0xFD) { /* Is data token */ 151 if (token != 0xFD) { /* Is data token */
152 wc = 0; 152 wc = 0;
153 do { /* Xmit the 512 byte data block to MMC */ 153 do { /* Xmit the 512 byte data block to MMC */
154 xmit_spi(*buff++); 154 xmit_spi(*buff++);
155 xmit_spi(*buff++); 155 xmit_spi(*buff++);
156 } while (--wc); 156 } while (--wc);
157 xmit_spi(0xFF); /* CRC (Dummy) */ 157 xmit_spi(0xFF); /* CRC (Dummy) */
158 xmit_spi(0xFF); 158 xmit_spi(0xFF);
159 resp = rcvr_spi(); /* Reveive data response */ 159 resp = rcvr_spi(); /* Reveive data response */
160 if ((resp & 0x1F) != 0x05) /* If not accepted, return with error */ 160 if ((resp & 0x1F) != 0x05) /* If not accepted, return with error */
161 return FALSE; 161 return FALSE;
162 } 162 }
163   163  
164 return TRUE; 164 return TRUE;
165 } 165 }
166 #endif /* _READONLY */ 166 #endif /* _READONLY */
167   167  
168   168  
169   169  
170 /*-----------------------------------------------------------------------*/ 170 /*-----------------------------------------------------------------------*/
171 /* Send a command packet to MMC */ 171 /* Send a command packet to MMC */
172 /*-----------------------------------------------------------------------*/ 172 /*-----------------------------------------------------------------------*/
173   173  
174 static 174 static
175 BYTE send_cmd ( 175 BYTE send_cmd (
176 BYTE cmd, /* Command byte */ 176 BYTE cmd, /* Command byte */
177 DWORD arg /* Argument */ 177 DWORD arg /* Argument */
178 ) 178 )
179 { 179 {
180 BYTE n, res; 180 BYTE n, res;
181   181  
182   182  
183 if (wait_ready() != 0xFF) return 0xFF; 183 if (wait_ready() != 0xFF) return 0xFF;
184   184  
185 /* Send command packet */ 185 /* Send command packet */
186 xmit_spi(cmd); /* Command */ 186 xmit_spi(cmd); /* Command */
187 xmit_spi((BYTE)(arg >> 24)); /* Argument[31..24] */ 187 xmit_spi((BYTE)(arg >> 24)); /* Argument[31..24] */
188 xmit_spi((BYTE)(arg >> 16)); /* Argument[23..16] */ 188 xmit_spi((BYTE)(arg >> 16)); /* Argument[23..16] */
189 xmit_spi((BYTE)(arg >> 8)); /* Argument[15..8] */ 189 xmit_spi((BYTE)(arg >> 8)); /* Argument[15..8] */
190 xmit_spi((BYTE)arg); /* Argument[7..0] */ 190 xmit_spi((BYTE)arg); /* Argument[7..0] */
191 n = 0; 191 n = 0;
192 if (cmd == CMD0) n = 0x95; /* CRC for CMD0(0) */ 192 if (cmd == CMD0) n = 0x95; /* CRC for CMD0(0) */
193 if (cmd == CMD8) n = 0x87; /* CRC for CMD8(0x1AA) */ 193 if (cmd == CMD8) n = 0x87; /* CRC for CMD8(0x1AA) */
194 xmit_spi(n); 194 xmit_spi(n);
195   195  
196 /* Receive command response */ 196 /* Receive command response */
197 if (cmd == CMD12) rcvr_spi(); /* Skip a stuff byte when stop reading */ 197 if (cmd == CMD12) rcvr_spi(); /* Skip a stuff byte when stop reading */
198 n = 10; /* Wait for a valid response in timeout of 10 attempts */ 198 n = 10; /* Wait for a valid response in timeout of 10 attempts */
199 do 199 do
200 res = rcvr_spi(); 200 res = rcvr_spi();
201 while ((res & 0x80) && --n); 201 while ((res & 0x80) && --n);
202   202  
203 return res; /* Return with the response value */ 203 return res; /* Return with the response value */
204 } 204 }
205   205  
206   206  
207   207  
208   208  
209 /*-------------------------------------------------------------------------- 209 /*--------------------------------------------------------------------------
210   210  
211 Public Functions 211 Public Functions
212   212  
213 ---------------------------------------------------------------------------*/ 213 ---------------------------------------------------------------------------*/
214   214  
215   215  
216 /*-----------------------------------------------------------------------*/ 216 /*-----------------------------------------------------------------------*/
217 /* Initialize Disk Drive */ 217 /* Initialize Disk Drive */
218 /*-----------------------------------------------------------------------*/ 218 /*-----------------------------------------------------------------------*/
219   219  
220 DSTATUS disk_initialize ( 220 DSTATUS disk_initialize (
221 BYTE drv /* Physical drive nmuber (0) */ 221 BYTE drv /* Physical drive nmuber (0) */
222 ) 222 )
223 { 223 {
224 BYTE n, ty, ocr[4]; 224 BYTE n, ty, ocr[4];
225   225  
226   226  
227 if (drv) return STA_NOINIT; /* Supports only single drive */ 227 if (drv) return STA_NOINIT; /* Supports only single drive */
228 if (Stat & STA_NODISK) return Stat; /* No card in the socket */ 228 if (Stat & STA_NODISK) return Stat; /* No card in the socket */
229   229  
230 for (n = 10; n; n--) rcvr_spi(); /* 80 dummy clocks */ 230 for (n = 10; n; n--) rcvr_spi(); /* 80 dummy clocks */
231   231  
232 SELECT(); /* CS = L */ 232 SELECT(); /* CS = L */
233 ty = 0; 233 ty = 0;
234 if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */ 234 if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
235 Timer1 = 100; /* Initialization timeout of 1000 msec */ 235 Timer1 = 100; /* Initialization timeout of 1000 msec */
236 if (send_cmd(CMD8, 0x1AA) == 1) { /* SDC Ver2+ */ 236 if (send_cmd(CMD8, 0x1AA) == 1) { /* SDC Ver2+ */
237 for (n = 0; n < 4; n++) ocr[n] = rcvr_spi(); 237 for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
238 if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */ 238 if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
239 do { 239 do {
240 if (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 1UL << 30) == 0) break; /* ACMD41 with HCS bit */ 240 if (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 1UL << 30) == 0) break; /* ACMD41 with HCS bit */
241 } while (Timer1); 241 } while (Timer1);
242 if (Timer1 && send_cmd(CMD58, 0) == 0) { /* Check CCS bit */ 242 if (Timer1 && send_cmd(CMD58, 0) == 0) { /* Check CCS bit */
243 for (n = 0; n < 4; n++) ocr[n] = rcvr_spi(); 243 for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
244 ty = (ocr[0] & 0x40) ? 6 : 2; 244 ty = (ocr[0] & 0x40) ? 6 : 2;
245 } 245 }
246 } 246 }
247 } else { /* SDC Ver1 or MMC */ 247 } else { /* SDC Ver1 or MMC */
248 ty = (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 0) <= 1) ? 2 : 1; /* SDC : MMC */ 248 ty = (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 0) <= 1) ? 2 : 1; /* SDC : MMC */
249 do { 249 do {
250 if (ty == 2) { 250 if (ty == 2) {
251 if (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 0) == 0) break; /* ACMD41 */ 251 if (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 0) == 0) break; /* ACMD41 */
252 } else { 252 } else {
253 if (send_cmd(CMD1, 0) == 0) break; /* CMD1 */ 253 if (send_cmd(CMD1, 0) == 0) break; /* CMD1 */
254 } 254 }
255 } while (Timer1); 255 } while (Timer1);
256 if (!Timer1 || send_cmd(CMD16, 512) != 0) /* Select R/W block length */ 256 if (!Timer1 || send_cmd(CMD16, 512) != 0) /* Select R/W block length */
257 ty = 0; 257 ty = 0;
258 } 258 }
259 } 259 }
260 CardType = ty; 260 CardType = ty;
261 DESELECT(); /* CS = H */ 261 DESELECT(); /* CS = H */
262 rcvr_spi(); /* Idle (Release DO) */ 262 rcvr_spi(); /* Idle (Release DO) */
263   263  
264 if (ty) { /* Initialization succeded */ 264 if (ty) { /* Initialization succeded */
265 Stat &= ~STA_NOINIT; /* Clear STA_NOINIT */ 265 Stat &= ~STA_NOINIT; /* Clear STA_NOINIT */
266 } else { /* Initialization failed */ 266 } else { /* Initialization failed */
267 Stat |= STA_NOINIT; /* Set STA_NOINIT */ 267 Stat |= STA_NOINIT; /* Set STA_NOINIT */
268 } 268 }
269   269  
270 return Stat; 270 return Stat;
271 } 271 }
272   272  
273   273  
274   274  
275 /*-----------------------------------------------------------------------*/ 275 /*-----------------------------------------------------------------------*/
276 /* Get Disk Status */ 276 /* Get Disk Status */
277 /*-----------------------------------------------------------------------*/ 277 /*-----------------------------------------------------------------------*/
278   278  
279 DSTATUS disk_status ( 279 DSTATUS disk_status (
280 BYTE drv /* Physical drive nmuber (0) */ 280 BYTE drv /* Physical drive nmuber (0) */
281 ) 281 )
282 { 282 {
283 if (drv) return STA_NOINIT; /* Supports only single drive */ 283 if (drv) return STA_NOINIT; /* Supports only single drive */
284 return Stat; 284 return Stat;
285 } 285 }
286   286  
287   287  
288   288  
289 /*-----------------------------------------------------------------------*/ 289 /*-----------------------------------------------------------------------*/
290 /* Read Sector(s) */ 290 /* Read Sector(s) */
291 /*-----------------------------------------------------------------------*/ 291 /*-----------------------------------------------------------------------*/
292   292  
293 DRESULT disk_read ( 293 DRESULT disk_read (
294 BYTE drv, /* Physical drive nmuber (0) */ 294 BYTE drv, /* Physical drive nmuber (0) */
295 BYTE *buff, /* Pointer to the data buffer to store read data */ 295 BYTE *buff, /* Pointer to the data buffer to store read data */
296 DWORD sector, /* Start sector number (LBA) */ 296 DWORD sector, /* Start sector number (LBA) */
297 BYTE count /* Sector count (1..255) */ 297 BYTE count /* Sector count (1..255) */
298 ) 298 )
299 { 299 {
300 if (drv || !count) return RES_PARERR; 300 if (drv || !count) return RES_PARERR;
301 if (Stat & STA_NOINIT) return RES_NOTRDY; 301 if (Stat & STA_NOINIT) return RES_NOTRDY;
302   302  
303 if (!(CardType & 4)) sector *= 512; /* Convert to byte address if needed */ 303 if (!(CardType & 4)) sector *= 512; /* Convert to byte address if needed */
304   304  
305 SELECT(); /* CS = L */ 305 SELECT(); /* CS = L */
306   306  
307 if (count == 1) { /* Single block read */ 307 if (count == 1) { /* Single block read */
308 if ((send_cmd(CMD17, sector) == 0) /* READ_SINGLE_BLOCK */ 308 if ((send_cmd(CMD17, sector) == 0) /* READ_SINGLE_BLOCK */
309 && rcvr_datablock(buff, 512)) 309 && rcvr_datablock(buff, 512))
310 count = 0; 310 count = 0;
311 } 311 }
312 else { /* Multiple block read */ 312 else { /* Multiple block read */
313 if (send_cmd(CMD18, sector) == 0) { /* READ_MULTIPLE_BLOCK */ 313 if (send_cmd(CMD18, sector) == 0) { /* READ_MULTIPLE_BLOCK */
314 do { 314 do {
315 if (!rcvr_datablock(buff, 512)) break; 315 if (!rcvr_datablock(buff, 512)) break;
316 buff += 512; 316 buff += 512;
317 } while (--count); 317 } while (--count);
318 send_cmd(CMD12, 0); /* STOP_TRANSMISSION */ 318 send_cmd(CMD12, 0); /* STOP_TRANSMISSION */
319 } 319 }
320 } 320 }
321   321  
322 DESELECT(); /* CS = H */ 322 DESELECT(); /* CS = H */
323 rcvr_spi(); /* Idle (Release DO) */ 323 rcvr_spi(); /* Idle (Release DO) */
324   324  
325 return count ? RES_ERROR : RES_OK; 325 return count ? RES_ERROR : RES_OK;
326 } 326 }
327   327  
328   328  
329   329  
330 /*-----------------------------------------------------------------------*/ 330 /*-----------------------------------------------------------------------*/
331 /* Write Sector(s) */ 331 /* Write Sector(s) */
332 /*-----------------------------------------------------------------------*/ 332 /*-----------------------------------------------------------------------*/
333   333  
334 #if _READONLY == 0 334 #if _READONLY == 0
335 DRESULT disk_write ( 335 DRESULT disk_write (
336 BYTE drv, /* Physical drive nmuber (0) */ 336 BYTE drv, /* Physical drive nmuber (0) */
337 const BYTE *buff, /* Pointer to the data to be written */ 337 const BYTE *buff, /* Pointer to the data to be written */
338 DWORD sector, /* Start sector number (LBA) */ 338 DWORD sector, /* Start sector number (LBA) */
339 BYTE count /* Sector count (1..255) */ 339 BYTE count /* Sector count (1..255) */
340 ) 340 )
341 { 341 {
342 if (drv || !count) return RES_PARERR; 342 if (drv || !count) return RES_PARERR;
343 if (Stat & STA_NOINIT) return RES_NOTRDY; 343 if (Stat & STA_NOINIT) return RES_NOTRDY;
344 if (Stat & STA_PROTECT) return RES_WRPRT; 344 if (Stat & STA_PROTECT) return RES_WRPRT;
345   345  
346 if (!(CardType & 4)) sector *= 512; /* Convert to byte address if needed */ 346 if (!(CardType & 4)) sector *= 512; /* Convert to byte address if needed */
347   347  
348 SELECT(); /* CS = L */ 348 SELECT(); /* CS = L */
349   349  
350 if (count == 1) { /* Single block write */ 350 if (count == 1) { /* Single block write */
351 if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */ 351 if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */
352 && xmit_datablock(buff, 0xFE)) 352 && xmit_datablock(buff, 0xFE))
353 count = 0; 353 count = 0;
354 } 354 }
355 else { /* Multiple block write */ 355 else { /* Multiple block write */
356 if (CardType & 2) { 356 if (CardType & 2) {
357 send_cmd(CMD55, 0); send_cmd(CMD23, count); /* ACMD23 */ 357 send_cmd(CMD55, 0); send_cmd(CMD23, count); /* ACMD23 */
358 } 358 }
359 if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */ 359 if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */
360 do { 360 do {
361 if (!xmit_datablock(buff, 0xFC)) break; 361 if (!xmit_datablock(buff, 0xFC)) break;
362 buff += 512; 362 buff += 512;
363 } while (--count); 363 } while (--count);
364 if (!xmit_datablock(0, 0xFD)) /* STOP_TRAN token */ 364 if (!xmit_datablock(0, 0xFD)) /* STOP_TRAN token */
365 count = 1; 365 count = 1;
366 } 366 }
367 } 367 }
368   368  
369 DESELECT(); /* CS = H */ 369 DESELECT(); /* CS = H */
370 rcvr_spi(); /* Idle (Release DO) */ 370 rcvr_spi(); /* Idle (Release DO) */
371   371  
372 return count ? RES_ERROR : RES_OK; 372 return count ? RES_ERROR : RES_OK;
373 } 373 }
374 #endif /* _READONLY */ 374 #endif /* _READONLY */
375   375  
376   376  
377   377  
378 /*-----------------------------------------------------------------------*/ 378 /*-----------------------------------------------------------------------*/
379 /* Miscellaneous Functions */ 379 /* Miscellaneous Functions */
380 /*-----------------------------------------------------------------------*/ 380 /*-----------------------------------------------------------------------*/
381   381  
382 DRESULT disk_ioctl ( 382 DRESULT disk_ioctl (
383 BYTE drv, /* Physical drive nmuber (0) */ 383 BYTE drv, /* Physical drive nmuber (0) */
384 BYTE ctrl, /* Control code */ 384 BYTE ctrl, /* Control code */
385 void *buff /* Buffer to send/receive data block */ 385 void *buff /* Buffer to send/receive data block */
386 ) 386 )
387 { 387 {
388 DRESULT res; 388 DRESULT res;
389 BYTE n, csd[16], *ptr = buff; 389 BYTE n, csd[16], *ptr = buff;
390 WORD csize; 390 WORD csize;
391   391  
392   392  
393 if (drv) return RES_PARERR; 393 if (drv) return RES_PARERR;
394   394  
395 SELECT(); /* CS = L */ 395 SELECT(); /* CS = L */
396   396  
397 res = RES_ERROR; 397 res = RES_ERROR;
398 switch (ctrl) { 398 switch (ctrl) {
399 case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */ 399 case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */
400 if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) { 400 if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
401 if ((csd[0] >> 6) == 1) { /* SDC ver 2.00 */ 401 if ((csd[0] >> 6) == 1) { /* SDC ver 2.00 */
402 csize = csd[9] + ((WORD)csd[8] << 8) + 1; 402 csize = csd[9] + ((WORD)csd[8] << 8) + 1;
403 *(DWORD*)buff = (DWORD)csize << 10; 403 *(DWORD*)buff = (DWORD)csize << 10;
404 } else { /* MMC or SDC ver 1.XX */ 404 } else { /* MMC or SDC ver 1.XX */
405 n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2; 405 n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
406 csize = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1; 406 csize = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;
407 *(DWORD*)buff = (DWORD)csize << (n - 9); 407 *(DWORD*)buff = (DWORD)csize << (n - 9);
408 } 408 }
409 res = RES_OK; 409 res = RES_OK;
410 } 410 }
411 break; 411 break;
412   412  
413 case GET_SECTOR_SIZE : /* Get sectors on the disk (WORD) */ 413 case GET_SECTOR_SIZE : /* Get sectors on the disk (WORD) */
414 *(WORD*)buff = 512; 414 *(WORD*)buff = 512;
415 res = RES_OK; 415 res = RES_OK;
416 break; 416 break;
417   417  
418 case CTRL_SYNC : /* Make sure that data has been written */ 418 case CTRL_SYNC : /* Make sure that data has been written */
419 if (wait_ready() == 0xFF) 419 if (wait_ready() == 0xFF)
420 res = RES_OK; 420 res = RES_OK;
421 break; 421 break;
422   422  
423 case MMC_GET_CSD : /* Receive CSD as a data block (16 bytes) */ 423 case MMC_GET_CSD : /* Receive CSD as a data block (16 bytes) */
424 if (Stat & STA_NOINIT) return RES_NOTRDY; 424 if (Stat & STA_NOINIT) return RES_NOTRDY;
425 if ((send_cmd(CMD9, 0) == 0) /* READ_CSD */ 425 if ((send_cmd(CMD9, 0) == 0) /* READ_CSD */
426 && rcvr_datablock(ptr, 16)) 426 && rcvr_datablock(ptr, 16))
427 res = RES_OK; 427 res = RES_OK;
428 break; 428 break;
429   429  
430 case MMC_GET_CID : /* Receive CID as a data block (16 bytes) */ 430 case MMC_GET_CID : /* Receive CID as a data block (16 bytes) */
431 if (Stat & STA_NOINIT) return RES_NOTRDY; 431 if (Stat & STA_NOINIT) return RES_NOTRDY;
432 if ((send_cmd(CMD10, 0) == 0) /* READ_CID */ 432 if ((send_cmd(CMD10, 0) == 0) /* READ_CID */
433 && rcvr_datablock(ptr, 16)) 433 && rcvr_datablock(ptr, 16))
434 res = RES_OK; 434 res = RES_OK;
435 break; 435 break;
436   436  
437 case MMC_GET_OCR : /* Receive OCR as an R3 resp (4 bytes) */ 437 case MMC_GET_OCR : /* Receive OCR as an R3 resp (4 bytes) */
438 if (Stat & STA_NOINIT) return RES_NOTRDY; 438 if (Stat & STA_NOINIT) return RES_NOTRDY;
439 if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */ 439 if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */
440 for (n = 0; n < 4; n++) 440 for (n = 0; n < 4; n++)
441 *ptr++ = rcvr_spi(); 441 *ptr++ = rcvr_spi();
442 res = RES_OK; 442 res = RES_OK;
443 } 443 }
444 break; 444 break;
445   445  
446 default: 446 default:
447 res = RES_PARERR; 447 res = RES_PARERR;
448 } 448 }
449   449  
450 DESELECT(); /* CS = H */ 450 DESELECT(); /* CS = H */
451 rcvr_spi(); /* Idle (Release DO) */ 451 rcvr_spi(); /* Idle (Release DO) */
452   452  
453 return res; 453 return res;
454 } 454 }
455   455  
456   456  
457   457  
458 /*---------------------------------------*/ 458 /*---------------------------------------*/
459 /* Device timer interrupt procedure */ 459 /* Device timer interrupt procedure */
460 /* This must be called in period of 10ms */ 460 /* This must be called in period of 10ms */
461 /* (Platform dependent) */ 461 /* (Platform dependent) */
462   462  
463 void disk_timerproc (void) 463 void disk_timerproc (void)
464 { 464 {
465 static BYTE pv; 465 static BYTE pv;
466 BYTE n, s; 466 BYTE n, s;
467   467  
468   468  
469 n = Timer1; /* 100Hz decrement timer */ 469 n = Timer1; /* 100Hz decrement timer */
470 if (n) Timer1 = --n; 470 if (n) Timer1 = --n;
471 n = Timer2; 471 n = Timer2;
472 if (n) Timer2 = --n; 472 if (n) Timer2 = --n;
473   473  
474 n = pv; 474 n = pv;
475 pv = SOCKPORT & (SOCKINS); /* Sample socket switch */ 475 pv = SOCKPORT & (SOCKINS); /* Sample socket switch */
476   476  
477 if (n == pv) { /* Have contacts stabled? */ 477 if (n == pv) { /* Have contacts stabled? */
478 s = Stat; 478 s = Stat;
479 if (pv & SOCKINS) /* INS = H (Socket empty) */ 479 if (pv & SOCKINS) /* INS = H (Socket empty) */
480 s |= (STA_NODISK | STA_NOINIT); 480 s |= (STA_NODISK | STA_NOINIT);
481 else /* INS = L (Card inserted) */ 481 else /* INS = L (Card inserted) */
482 s &= ~STA_NODISK; 482 s &= ~STA_NODISK;
483   483  
484 Stat = s; 484 Stat = s;
485 } 485 }
486 } 486 }
487   487