source: rtems/c/src/lib/libbsp/lm32/shared/milkymist_memcard/memcard.c @ 9b4422a2

4.115
Last change on this file since 9b4422a2 was 9b4422a2, checked in by Joel Sherrill <joel.sherrill@…>, on 05/03/12 at 15:09:24

Remove All CVS Id Strings Possible Using a Script

Script does what is expected and tries to do it as
smartly as possible.

+ remove occurrences of two blank comment lines

next to each other after Id string line removed.

+ remove entire comment blocks which only exited to

contain CVS Ids

+ If the processing left a blank line at the top of

a file, it was removed.

  • Property mode set to 100644
File size: 9.1 KB
Line 
1/*  memcard.c
2 *
3 *  Milkymist memory card driver for RTEMS
4 *
5 *  The license and distribution terms for this file may be
6 *  found in the file LICENSE in this distribution or at
7 *  http://www.rtems.com/license/LICENSE.
8 *
9 *  COPYRIGHT (c) 2010, 2011 Sebastien Bourdeauducq
10 */
11
12#define RTEMS_STATUS_CHECKS_USE_PRINTK
13
14#include <rtems.h>
15#include <rtems/libio.h>
16#include <rtems/diskdevs.h>
17#include <rtems/blkdev.h>
18#include <rtems/status-checks.h>
19#include <errno.h>
20#include <bsp.h>
21#include "../include/system_conf.h"
22#include "milkymist_memcard.h"
23
24//#define MEMCARD_DEBUG
25
26#define BLOCK_SIZE 512
27
28static void memcard_start_cmd_tx(void)
29{
30  MM_WRITE(MM_MEMCARD_ENABLE, MEMCARD_ENABLE_CMD_TX);
31}
32
33static void memcard_start_cmd_rx(void)
34{
35  MM_WRITE(MM_MEMCARD_PENDING, MEMCARD_PENDING_CMD_RX);
36  MM_WRITE(MM_MEMCARD_START, MEMCARD_START_CMD_RX);
37  MM_WRITE(MM_MEMCARD_ENABLE, MEMCARD_ENABLE_CMD_RX);
38}
39
40static void memcard_start_cmd_dat_rx(void)
41{
42  MM_WRITE(MM_MEMCARD_PENDING, MEMCARD_PENDING_CMD_RX|MEMCARD_PENDING_DAT_RX);
43  MM_WRITE(MM_MEMCARD_START, MEMCARD_START_CMD_RX|MEMCARD_START_DAT_RX);
44  MM_WRITE(MM_MEMCARD_ENABLE, MEMCARD_ENABLE_CMD_RX|MEMCARD_ENABLE_DAT_RX);
45}
46
47static void memcard_send_command(unsigned char cmd, unsigned int arg)
48{
49  unsigned char packet[6];
50  int a;
51  int i;
52  unsigned char data;
53  unsigned char crc;
54
55  packet[0] = cmd | 0x40;
56  packet[1] = ((arg >> 24) & 0xff);
57  packet[2] = ((arg >> 16) & 0xff);
58  packet[3] = ((arg >> 8) & 0xff);
59  packet[4] = (arg & 0xff);
60
61  crc = 0;
62  for(a=0;a<5;a++) {
63    data = packet[a];
64    for(i=0;i<8;i++) {
65      crc <<= 1;
66      if((data & 0x80) ^ (crc & 0x80))
67        crc ^= 0x09;
68      data <<= 1;
69    }
70  }
71  crc = (crc<<1) | 1;
72
73  packet[5] = crc;
74
75#ifdef MEMCARD_DEBUG
76  printk(">> %02x %02x %02x %02x %02x %02x\n",
77    packet[0], packet[1], packet[2], packet[3], packet[4], packet[5]);
78#endif
79
80  for(i=0;i<6;i++) {
81    MM_WRITE(MM_MEMCARD_CMD, packet[i]);
82    while(MM_READ(MM_MEMCARD_PENDING) & MEMCARD_PENDING_CMD_TX);
83  }
84}
85
86static void memcard_send_dummy(void)
87{
88  MM_WRITE(MM_MEMCARD_CMD, 0xff);
89  while(MM_READ(MM_MEMCARD_PENDING) & MEMCARD_PENDING_CMD_TX);
90}
91
92static bool memcard_receive_command(unsigned char *buffer, int len)
93{
94  int i;
95  int timeout;
96
97  for(i=0;i<len;i++) {
98    timeout = 2000000;
99    while(!(MM_READ(MM_MEMCARD_PENDING) & MEMCARD_PENDING_CMD_RX)) {
100      timeout--;
101      if(timeout == 0) {
102        #ifdef MEMCARD_DEBUG
103        printk("Command receive timeout\n");
104        #endif
105        return false;
106      }
107    }
108    buffer[i] = MM_READ(MM_MEMCARD_CMD);
109    MM_WRITE(MM_MEMCARD_PENDING, MEMCARD_PENDING_CMD_RX);
110  }
111
112  while(!(MM_READ(MM_MEMCARD_PENDING) & MEMCARD_PENDING_CMD_RX));
113
114  #ifdef MEMCARD_DEBUG
115  printk("<< ");
116  for(i=0;i<len;i++)
117    printk("%02x ", buffer[i]);
118  printk("\n");
119  #endif
120
121  return true;
122}
123
124static bool memcard_receive_command_data(unsigned char *command,
125  unsigned int *data)
126{
127  int i, j;
128  int timeout;
129
130  i = 0;
131  j = 0;
132  while(j < 128) {
133    timeout = 2000000;
134    while(!(MM_READ(MM_MEMCARD_PENDING) &
135      (MEMCARD_PENDING_CMD_RX|MEMCARD_PENDING_DAT_RX))) {
136      timeout--;
137      if(timeout == 0) {
138        #ifdef MEMCARD_DEBUG
139        printk("Command receive timeout\n");
140        #endif
141        return false;
142      }
143    }
144    if(MM_READ(MM_MEMCARD_PENDING) & MEMCARD_PENDING_CMD_RX) {
145      command[i++] = MM_READ(MM_MEMCARD_CMD);
146      MM_WRITE(MM_MEMCARD_PENDING, MEMCARD_PENDING_CMD_RX);
147      if(i == 6)
148        /* disable command RX */
149        MM_WRITE(MM_MEMCARD_ENABLE, MEMCARD_ENABLE_DAT_RX);
150    }
151    if(MM_READ(MM_MEMCARD_PENDING) & MEMCARD_PENDING_DAT_RX) {
152      data[j++] = MM_READ(MM_MEMCARD_DAT);
153      MM_WRITE(MM_MEMCARD_PENDING, MEMCARD_PENDING_DAT_RX);
154    }
155  }
156
157  /* Get CRC (ignored) */
158  for(i=0;i<2;i++) {
159    while(!(MM_READ(MM_MEMCARD_PENDING) & MEMCARD_PENDING_DAT_RX));
160    #ifdef MEMCARD_DEBUG
161    printk("CRC: %08x\n", MM_READ(MM_MEMCARD_DAT));
162    #endif
163    MM_WRITE(MM_MEMCARD_PENDING, MEMCARD_PENDING_DAT_RX);
164  }
165
166  while(!(MM_READ(MM_MEMCARD_PENDING) & MEMCARD_PENDING_DAT_RX));
167
168  #ifdef MEMCARD_DEBUG
169  printk("<< %02x %02x %02x %02x %02x %02x\n",
170    command[0], command[1], command[2], command[3], command[4], command[5]);
171  #endif
172
173  //for(i=0;i<128;i++)
174  //  printk("%08x ", data[i]);
175  //printk("\n");
176
177  return true;
178}
179
180static unsigned int block_count;
181
182static int memcard_disk_block_read(rtems_blkdev_request *r)
183{
184  unsigned char b[6];
185  unsigned int i, nblocks;
186  unsigned int block;
187
188  block = RTEMS_BLKDEV_START_BLOCK(r);
189  nblocks = r->bufnum;
190
191  for(i=0;i<nblocks;i++) {
192    /* CMD17 - read block */
193    memcard_start_cmd_tx();
194    memcard_send_command(17, (block+i)*BLOCK_SIZE);
195    memcard_start_cmd_dat_rx();
196    if(!memcard_receive_command_data(b, (unsigned int *)r->bufs[i].buffer))
197      return -RTEMS_IO_ERROR;
198  }
199
200  r->req_done(r->done_arg, RTEMS_SUCCESSFUL);
201
202  return 0;
203}
204
205static int memcard_disk_block_write(rtems_blkdev_request *r)
206{
207  return -RTEMS_IO_ERROR;
208}
209
210static rtems_status_code memcard_init(void)
211{
212  unsigned char b[17];
213  unsigned int rca;
214  unsigned int block_shift;
215  unsigned int c_size;
216  unsigned int c_size_mult;
217
218  MM_WRITE(MM_MEMCARD_CLK2XDIV, 250);
219
220  /* CMD0 */
221  memcard_start_cmd_tx();
222  memcard_send_command(0, 0);
223
224  memcard_send_dummy();
225
226  /* CMD8 */
227  memcard_send_command(8, 0x1aa);
228  memcard_start_cmd_rx();
229  if(!memcard_receive_command(b, 6)) return RTEMS_IO_ERROR;
230
231  /* ACMD41 - initialize */
232  while(1) {
233    memcard_start_cmd_tx();
234    memcard_send_command(55, 0);
235    memcard_start_cmd_rx();
236    if(!memcard_receive_command(b, 6)) return RTEMS_IO_ERROR;
237    memcard_start_cmd_tx();
238    memcard_send_command(41, 0x00300000);
239    memcard_start_cmd_rx();
240    if(!memcard_receive_command(b, 6)) return RTEMS_IO_ERROR;
241    if(b[1] & 0x80) break;
242    #ifdef MEMCARD_DEBUG
243    printk("Card is busy, retrying\n");
244    #endif
245  }
246
247  /* CMD2 - get CID */
248  memcard_start_cmd_tx();
249  memcard_send_command(2, 0);
250  memcard_start_cmd_rx();
251  if(!memcard_receive_command(b, 17)) return RTEMS_IO_ERROR;
252
253  /* CMD3 - get RCA */
254  memcard_start_cmd_tx();
255  memcard_send_command(3, 0);
256  memcard_start_cmd_rx();
257  if(!memcard_receive_command(b, 6)) return RTEMS_IO_ERROR;
258  rca = (((unsigned int)b[1]) << 8)|((unsigned int)b[2]);
259  #ifdef MEMCARD_DEBUG
260  printk("RCA: %04x\n", rca);
261  #endif
262
263  /* CMD9 - get CSD */
264  memcard_start_cmd_tx();
265  memcard_send_command(9, rca << 16);
266  memcard_start_cmd_rx();
267  if(!memcard_receive_command(b, 17)) return RTEMS_IO_ERROR;
268
269  if(((b)[0] >> 6) != 0)
270    return RTEMS_IO_ERROR;
271
272  block_shift = ((unsigned int)(b)[5] & 0xf);
273  c_size = ((((unsigned int)(b)[6] & 0x3) << 10)
274    + (((unsigned int)(b)[7]) << 2)
275    + ((((unsigned int)(b)[8]) >> 6) & 0x3));
276  c_size_mult = ((((b)[9] & 0x3) << 1) + (((b)[10] >> 7) & 0x1));
277  block_count = (c_size + 1) * (1U << (c_size_mult + 2));
278
279  /* convert to 512-byte blocks for the sake of simplicity */
280  if(block_shift < 9)
281    return RTEMS_IO_ERROR;
282  block_count <<= block_shift - 9;
283
284  /* CMD7 - select card */
285  memcard_start_cmd_tx();
286  memcard_send_command(7, rca << 16);
287  memcard_start_cmd_rx();
288  if(!memcard_receive_command(b, 6)) return RTEMS_IO_ERROR;
289
290  /* ACMD6 - set bus width */
291  memcard_start_cmd_tx();
292  memcard_send_command(55, rca << 16);
293  memcard_start_cmd_rx();
294  if(!memcard_receive_command(b, 6)) return RTEMS_IO_ERROR;
295  memcard_start_cmd_tx();
296  memcard_send_command(6, 2);
297  memcard_start_cmd_rx();
298  if(!memcard_receive_command(b, 6)) return RTEMS_IO_ERROR;
299
300  MM_WRITE(MM_MEMCARD_CLK2XDIV, 3);
301
302  return RTEMS_SUCCESSFUL;
303}
304
305static int memcard_disk_ioctl(rtems_disk_device *dd, uint32_t req, void *arg)
306{
307  if (req == RTEMS_BLKIO_REQUEST) {
308    rtems_blkdev_request *r = (rtems_blkdev_request *)arg;
309    switch (r->req) {
310      case RTEMS_BLKDEV_REQ_READ:
311        return memcard_disk_block_read(r);
312      case RTEMS_BLKDEV_REQ_WRITE:
313        return memcard_disk_block_write(r);
314      default:
315        errno = EINVAL;
316        return -1;
317    }
318  } else if (req == RTEMS_BLKIO_CAPABILITIES) {
319    *(uint32_t *)arg = RTEMS_BLKDEV_CAP_MULTISECTOR_CONT;
320    return 0;
321  } else {
322    errno = EINVAL;
323    return -1;
324  }
325}
326
327static rtems_status_code memcard_disk_init(
328  rtems_device_major_number major, rtems_device_minor_number minor,
329  void *arg)
330{
331  rtems_status_code sc;
332  dev_t dev;
333
334  sc = rtems_disk_io_initialize();
335  RTEMS_CHECK_SC(sc, "Initialize RTEMS disk IO");
336
337  dev = rtems_filesystem_make_dev_t(major, 0);
338
339  sc = memcard_init();
340  RTEMS_CHECK_SC(sc, "Initialize memory card");
341
342  sc = rtems_disk_create_phys(dev, BLOCK_SIZE, block_count, memcard_disk_ioctl,
343    NULL, "/dev/memcard");
344  RTEMS_CHECK_SC(sc, "Create disk device");
345
346  return RTEMS_SUCCESSFUL;
347}
348
349
350static const rtems_driver_address_table memcard_disk_ops = {
351  .initialization_entry = memcard_disk_init,
352  .open_entry = rtems_blkdev_generic_open,
353  .close_entry = rtems_blkdev_generic_close,
354  .read_entry = rtems_blkdev_generic_read,
355  .write_entry = rtems_blkdev_generic_write,
356  .control_entry = rtems_blkdev_generic_ioctl
357};
358
359rtems_status_code memcard_register(void)
360{
361  rtems_status_code sc = RTEMS_SUCCESSFUL;
362  rtems_device_major_number major = 0;
363
364  sc = rtems_io_register_driver(0, &memcard_disk_ops, &major);
365  RTEMS_CHECK_SC(sc, "Register disk memory card driver");
366
367  return RTEMS_SUCCESSFUL;
368}
Note: See TracBrowser for help on using the repository browser.