source: rtems/cpukit/libblock/src/nvdisk.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: 21.9 KB
Line 
1/*
2 * nvdisk.c -- Non-volatile disk block device implementation
3 *
4 * Copyright (C) 2007 Chris Johns
5 *
6 * The license and distribution terms for this file may be
7 * found in the file LICENSE in this distribution or at
8 * http://www.rtems.com/license/LICENSE.
9 */
10
11#if HAVE_CONFIG_H
12#include "config.h"
13#endif
14
15#include <rtems.h>
16#include <rtems/libio.h>
17#include <errno.h>
18#include <stdlib.h>
19#include <stdio.h>
20#include <string.h>
21#include <inttypes.h>
22
23#include "rtems/blkdev.h"
24#include "rtems/diskdevs.h"
25#include "rtems/nvdisk.h"
26
27/**
28 * @note
29 *
30 * The use of pages can vary. The rtems_nvdisk_*_page set
31 * routines use an absolute page number relative to the segment
32 * while all other page numbera are relative to the number of
33 * page descriptor pages a segment has. You need to add the
34 * number of page descriptor pages (pages_desc) to the page number
35 * when call the rtems_nvdisk_*_page functions.
36 *
37 * You must always show the page number as relative in any trace
38 * or error message as device-page and if you have to
39 * the page number as absolute use device~page. This
40 * can be seen in the page copy routine.
41 *
42 * The code is like this to avoid needing the pass the pages_desc
43 * value around. It is only used in selected places and so the
44 * extra parameter was avoided.
45 */
46
47/**
48 * Control tracing. It can be compiled out of the code for small
49 * footprint targets. Leave in by default.
50 */
51#if !defined (RTEMS_NVDISK_TRACE)
52#define RTEMS_NVDISK_TRACE 0
53#endif
54
55/**
56 * NV Device Control holds the segment controls
57 */
58typedef struct rtems_nvdisk_device_ctl
59{
60  /**
61   * The device this segment resides on.
62   */
63  uint32_t device;
64
65  /**
66   * Total number of pages in the device.
67   */
68  uint32_t pages;
69
70  /**
71   * Number of pages used for page checksums.
72   */
73  uint32_t pages_desc;
74
75  /**
76   * First block number for this device.
77   */
78  uint32_t block_base;
79
80  /**
81   * Device descriptor.
82   */
83  const rtems_nvdisk_device_desc* descriptor;
84} rtems_nvdisk_device_ctl;
85
86/**
87 * The NV disk control structure for a single disk. There is one
88 * for each minor disk in the system.
89 */
90typedef struct rtems_mvdisk
91{
92  rtems_device_major_number major;        /**< The driver's major number. */
93  rtems_device_minor_number minor;        /**< The driver's minor number. */
94  uint32_t                  flags;        /**< configuration flags. */
95  uint32_t                  block_size;   /**< The block size for this disk. */
96  uint32_t                  block_count;  /**< The number of available blocks. */
97  rtems_nvdisk_device_ctl*  devices;      /**< The NV devices for this disk. */
98  uint32_t                  device_count; /**< The number of NV devices. */
99  uint32_t                  cs_pages;     /**< The num of pages of checksums. */
100  rtems_id                  lock;         /**< Mutex for threading protection.*/
101  uint32_t info_level;                    /**< The info trace level. */
102} rtems_nvdisk;
103
104/**
105 * The array of NV disks we support.
106 */
107static rtems_nvdisk* rtems_nvdisks;
108
109/**
110 * The number of NV disks we have.
111 */
112static uint32_t rtems_nvdisk_count;
113
114/**
115 * The CRC16 factor table. Created during initialisation.
116 */
117static uint16_t* rtems_nvdisk_crc16_factor;
118
119/**
120 * Calculate the CRC16 checksum.
121 *
122 * @param _b The byte to checksum.
123 * @param _c The current checksum.
124 */
125#define rtems_nvdisk_calc_crc16(_b, _c) \
126  rtems_nvdisk_crc16_factor[((_b) ^ ((_c) & 0xff)) & 0xff] ^ (((_c) >> 8) & 0xff)
127
128/**
129 * Generate the CRC table.
130 *
131 * @param pattern The seed pattern for the table of factors.
132 * @relval RTEMS_SUCCESSFUL The table was generated.
133 * @retval RTEMS_NO_MEMORY The table could not be allocated from the heap.
134 */
135static rtems_status_code
136rtems_nvdisk_crc16_gen_factors (uint16_t pattern)
137{
138  uint32_t b;
139
140  rtems_nvdisk_crc16_factor = malloc (sizeof (uint16_t) * 256);
141  if (!rtems_nvdisk_crc16_factor)
142    return RTEMS_NO_MEMORY;
143
144  for (b = 0; b < 256; b++)
145  {
146    uint32_t i;
147    uint16_t v = b;
148    for (i = 8; i--;)
149      v = v & 1 ? (v >> 1) ^ pattern : v >> 1;
150    rtems_nvdisk_crc16_factor[b] = v & 0xffff;
151  }
152  return RTEMS_SUCCESSFUL;
153}
154
155#if RTEMS_NVDISK_TRACE
156/**
157 * Print a message to the nvdisk output and flush it.
158 *
159 * @param nvd The nvdisk control structure.
160 * @param format The format string. See printf for details.
161 * @param ... The arguments for the format text.
162 * @return int The number of bytes written to the output.
163 */
164static int
165rtems_nvdisk_printf (const rtems_nvdisk* nvd, const char *format, ...)
166{
167  int ret = 0;
168  if (nvd->info_level >= 3)
169  {
170    va_list args;
171    va_start (args, format);
172    fprintf (stdout, "nvdisk:");
173    ret =  vfprintf (stdout, format, args);
174    fprintf (stdout, "\n");
175    fflush (stdout);
176    va_end (args);
177  }
178  return ret;
179}
180
181/**
182 * Print a info message to the nvdisk output and flush it.
183 *
184 * @param nvd The nvdisk control structure.
185 * @param format The format string. See printf for details.
186 * @param ... The arguments for the format text.
187 * @return int The number of bytes written to the output.
188 */
189static int
190rtems_nvdisk_info (const rtems_nvdisk* nvd, const char *format, ...)
191{
192  int ret = 0;
193  if (nvd->info_level >= 2)
194  {
195    va_list args;
196    va_start (args, format);
197    fprintf (stdout, "nvdisk:");
198    ret =  vfprintf (stdout, format, args);
199    fprintf (stdout, "\n");
200    fflush (stdout);
201    va_end (args);
202  }
203  return ret;
204}
205
206/**
207 * Print a warning to the nvdisk output and flush it.
208 *
209 * @param nvd The nvdisk control structure.
210 * @param format The format string. See printf for details.
211 * @param ... The arguments for the format text.
212 * @return int The number of bytes written to the output.
213 */
214static int
215rtems_nvdisk_warning (const rtems_nvdisk* nvd, const char *format, ...)
216{
217  int ret = 0;
218  if (nvd->info_level >= 1)
219  {
220    va_list args;
221    va_start (args, format);
222    fprintf (stdout, "nvdisk:warning:");
223    ret =  vfprintf (stdout, format, args);
224    fprintf (stdout, "\n");
225    fflush (stdout);
226    va_end (args);
227  }
228  return ret;
229}
230#endif
231
232/**
233 * Print an error to the nvdisk output and flush it.
234 *
235 * @param format The format string. See printf for details.
236 * @param ... The arguments for the format text.
237 * @return int The number of bytes written to the output.
238 */
239static int
240rtems_nvdisk_error (const char *format, ...)
241{
242  int ret;
243  va_list args;
244  va_start (args, format);
245  fprintf (stderr, "nvdisk:error:");
246  ret =  vfprintf (stderr, format, args);
247  fprintf (stderr, "\n");
248  fflush (stderr);
249  va_end (args);
250  return ret;
251}
252
253/**
254 * Get the descriptor for a device.
255 */
256static const rtems_nvdisk_device_desc*
257rtems_nvdisk_device_descriptor (const rtems_nvdisk* nvd, uint32_t device)
258{
259  return nvd->devices[device].descriptor;
260}
261
262/**
263 * Read a block of data from a device.
264 */
265static int
266rtems_nvdisk_device_read (const rtems_nvdisk* nvd,
267                          uint32_t            device,
268                          uint32_t            offset,
269                          void*               buffer,
270                          uint32_t            size)
271{
272  const rtems_nvdisk_device_desc*     dd;
273  const rtems_nvdisk_driver_handlers* ops;
274  dd  = rtems_nvdisk_device_descriptor (nvd, device);
275  ops = nvd->devices[device].descriptor->nv_ops;
276#if RTEMS_NVDISK_TRACE
277  rtems_nvdisk_printf (nvd, "  dev-read: %02d-%08x: s=%d",
278                      device, offset, size);
279#endif
280  return ops->read (device, dd->flags, dd->base, offset, buffer, size);
281}
282
283/**
284 * Write a block of data to a device.
285 */
286static int
287rtems_nvdisk_device_write (const rtems_nvdisk* nvd,
288                           uint32_t            device,
289                           uint32_t            offset,
290                           const void*         buffer,
291                           uint32_t            size)
292{
293  const rtems_nvdisk_device_desc*     dd;
294  const rtems_nvdisk_driver_handlers* ops;
295  dd  = rtems_nvdisk_device_descriptor (nvd, device);
296  ops = nvd->devices[device].descriptor->nv_ops;
297#if RTEMS_NVDISK_TRACE
298  rtems_nvdisk_printf (nvd, "  dev-write: %02d-%08x: s=%d",
299                      device, offset, size);
300#endif
301  return ops->write (device, dd->flags, dd->base, offset, buffer, size);
302}
303
304#if NOT_USED
305/**
306 * Verify the data with the data in a segment.
307 */
308static int
309rtems_nvdisk_device_verify (const rtems_nvdisk* nvd,
310                            uint32_t            device,
311                            uint32_t            offset,
312                            const void*         buffer,
313                            uint32_t            size)
314{
315  const rtems_nvdisk_device_desc*     dd;
316  const rtems_nvdisk_driver_handlers* ops;
317  dd  = rtems_nvdisk_device_descriptor (nvd, device);
318  ops = nvd->devices[device].descriptor->nv_ops;
319#if RTEMS_NVDISK_TRACE
320  rtems_nvdisk_printf (nvd, "  seg-verify: %02d-%08x: s=%d",
321                      device, offset, size);
322#endif
323  return ops->verify (device, dd->flags, dd->base, offset, buffer, size);
324}
325#endif
326
327/**
328 * Read a page of data from the device.
329 */
330static int
331rtems_nvdisk_read_page (const rtems_nvdisk* nvd,
332                        uint32_t            device,
333                        uint32_t            page,
334                        void*               buffer)
335{
336  return rtems_nvdisk_device_read (nvd, device,
337                                   page * nvd->block_size, buffer,
338                                   nvd->block_size);
339}
340
341/**
342 * Write a page of data to a device.
343 */
344static int
345rtems_nvdisk_write_page (const rtems_nvdisk* nvd,
346                         uint32_t            device,
347                         uint32_t            page,
348                         const void*         buffer)
349{
350  return rtems_nvdisk_device_write (nvd, device,
351                                    page * nvd->block_size,
352                                    buffer, nvd->block_size);
353}
354
355/**
356 * Read the checksum from the device.
357 */
358static int
359rtems_nvdisk_read_checksum (const rtems_nvdisk* nvd,
360                            uint32_t            device,
361                            uint32_t            page,
362                            uint16_t*           cs)
363{
364  return rtems_nvdisk_device_read (nvd, device,
365                                   page * sizeof (uint16_t),
366                                   cs, sizeof (uint16_t));
367}
368
369/**
370 * Write the checksum to the device.
371 */
372static int
373rtems_nvdisk_write_checksum (const rtems_nvdisk* nvd,
374                             uint32_t            device,
375                             uint32_t            page,
376                             const uint16_t      cs)
377{
378  return rtems_nvdisk_device_write (nvd, device,
379                                    page * sizeof (uint16_t),
380                                    &cs, sizeof (uint16_t));
381}
382
383/**
384 * Calculate the pages in a device give the device descriptor and the
385 * page size.
386 *
387 * @param dd The device descriptor.
388 * @param page_size The page size in bytes.
389 */
390static uint32_t
391rtems_nvdisk_pages_in_device (const rtems_nvdisk*             nvd,
392                              const rtems_nvdisk_device_desc* dd)
393{
394  return dd->size / nvd->block_size;
395}
396
397/**
398 * Calculate the number of pages needed to hold the page descriptors.
399 * The calculation need to round up.
400 */
401static uint32_t
402rtems_nvdisk_page_desc_pages (const rtems_nvdisk*             nvd,
403                              const rtems_nvdisk_device_desc* dd)
404{
405  uint32_t pages = rtems_nvdisk_pages_in_device (nvd, dd);
406  uint32_t bytes = pages * sizeof (uint16_t);
407  return ((bytes - 1) / nvd->block_size) + 1;
408}
409
410/**
411 * Calculate the checksum of a page.
412 */
413static uint16_t
414rtems_nvdisk_page_checksum (const uint8_t* buffer, uint32_t page_size)
415{
416  uint16_t cs = 0xffff;
417  uint32_t i;
418
419  for (i = 0; i < page_size; i++, buffer++)
420    cs = rtems_nvdisk_calc_crc16 (cs, *buffer);
421
422  return cs;
423}
424
425/**
426 * Map a block to a device.
427 */
428static rtems_nvdisk_device_ctl*
429rtems_nvdisk_get_device (rtems_nvdisk* nvd, uint32_t block)
430{
431  uint32_t device;
432
433  if (block >= nvd->block_count)
434  {
435    rtems_nvdisk_error ("read-block: bad block: %d", block);
436    return NULL;
437  }
438
439  for (device = 0; device < nvd->device_count; device++)
440  {
441    rtems_nvdisk_device_ctl* dc = &nvd->devices[device];
442    if ((block >= dc->block_base) &&
443        (block < (dc->block_base + dc->pages - dc->pages_desc)))
444      return dc;
445  }
446
447  rtems_nvdisk_error ("map-block:%d: no device/page map found", block);
448
449  return NULL;
450}
451
452/**
453 * Get the page for a block in a device.
454 */
455static uint32_t
456rtems_nvdisk_get_page (rtems_nvdisk_device_ctl* dc,
457                       uint32_t                 block)
458{
459  return block - dc->block_base;
460}
461
462/**
463 * Read a block. The block is checked to see if the page referenced
464 * is valid and the page has a valid crc.
465 *
466 * @param nvd The rtems_nvdisk control table.
467 * @param block The block number to read.
468 * @param buffer The buffer to write the data into.
469 * @return 0 No error.
470 * @return EIO Invalid block number or crc.
471 */
472static int
473rtems_nvdisk_read_block (rtems_nvdisk* nvd, uint32_t block, uint8_t* buffer)
474{
475  rtems_nvdisk_device_ctl* dc;
476  uint32_t                 page;
477  uint16_t                 crc;
478  uint16_t                 cs;
479  int                      ret;
480
481  dc = rtems_nvdisk_get_device (nvd, block);
482
483  if (!dc)
484    return EIO;
485
486  page = rtems_nvdisk_get_page (dc, block);
487
488#if RTEMS_NVDISK_TRACE
489  rtems_nvdisk_info (nvd, " read-block:%d=>%02d-%03d, cs:%04x",
490                     block, dc->device, page, crc);
491#endif
492
493  ret = rtems_nvdisk_read_checksum (nvd, dc->device, page, &crc);
494
495  if (ret)
496    return ret;
497
498  if (crc == 0xffff)
499  {
500#if RTEMS_NVDISK_TRACE
501    rtems_nvdisk_warning (nvd, "read-block: crc not set: %d", block);
502#endif
503    memset (buffer, 0, nvd->block_size);
504    return 0;
505  }
506
507  ret = rtems_nvdisk_read_page (nvd, dc->device, page + dc->pages_desc, buffer);
508
509  if (ret)
510    return ret;
511
512  cs = rtems_nvdisk_page_checksum (buffer, nvd->block_size);
513
514  if (cs != crc)
515  {
516    rtems_nvdisk_error ("read-block: crc failure: %d: buffer:%04x page:%04x",
517                        block, cs, crc);
518    return EIO;
519  }
520
521  return 0;
522}
523
524/**
525 * Write a block.
526 *
527 * @param nvd The rtems_nvdisk control table.
528 * @param block The block number to read.
529 * @param block_size The size of the block. Must match what we have.
530 * @param buffer The buffer to write the data into.
531 * @return 0 No error.
532 * @return EIO Invalid block size, block number, segment pointer, crc,
533 *             page flags.
534 */
535static int
536rtems_nvdisk_write_block (rtems_nvdisk*        nvd,
537                          uint32_t             block,
538                          const unsigned char* buffer)
539{
540  rtems_nvdisk_device_ctl* dc;
541  uint32_t                 page;
542  uint16_t                 cs;
543  int                      ret;
544
545  dc = rtems_nvdisk_get_device (nvd, block);
546
547  if (!dc)
548    return EIO;
549
550  page = rtems_nvdisk_get_page (dc, block);
551
552  cs = rtems_nvdisk_page_checksum (buffer, nvd->block_size);
553
554#if RTEMS_NVDISK_TRACE
555  rtems_nvdisk_info (nvd, " write-block:%d=>%02d-%03d", block, dc->device, page);
556#endif
557
558  ret = rtems_nvdisk_write_page (nvd, dc->device, page + dc->pages_desc, buffer);
559
560  if (ret)
561    return ret;
562
563  return rtems_nvdisk_write_checksum (nvd, dc->device, page, cs);
564}
565
566/**
567 * Disk READ request handler. This primitive copies data from the
568 * flash disk to the supplied buffer and invoke the callout function
569 * to inform upper layer that reading is completed.
570 *
571 * @param req Pointer to the READ block device request info.
572 * @retval int The ioctl return value.
573 */
574static int
575rtems_nvdisk_read (rtems_nvdisk* nvd, rtems_blkdev_request* req)
576{
577  rtems_blkdev_sg_buffer* sg = req->bufs;
578  uint32_t                bufs;
579  int                     ret = 0;
580
581#if RTEMS_NVDISK_TRACE
582  rtems_nvdisk_info (nvd, "read: blocks=%d", req->bufnum);
583#endif
584
585  for (bufs = 0; (ret == 0) && (bufs < req->bufnum); bufs++, sg++)
586  {
587    uint8_t* data;
588    uint32_t nvb;
589    uint32_t b;
590    nvb = sg->length / nvd->block_size;
591    data = sg->buffer;
592    for (b = 0; b < nvb; b++, data += nvd->block_size)
593    {
594      ret = rtems_nvdisk_read_block (nvd, sg->block + b, data);
595      if (ret)
596        break;
597    }
598  }
599
600  req->status = ret ? RTEMS_IO_ERROR : RTEMS_SUCCESSFUL;
601  req->req_done (req->done_arg, req->status);
602
603  return ret;
604}
605
606/**
607 * Flash disk WRITE request handler. This primitive copies data from
608 * supplied buffer to NV disk and invoke the callout function to inform
609 * upper layer that writing is completed.
610 *
611 * @param req Pointers to the WRITE block device request info.
612 * @retval int The ioctl return value.
613 */
614static int
615rtems_nvdisk_write (rtems_nvdisk* nvd, rtems_blkdev_request* req)
616{
617  rtems_blkdev_sg_buffer* sg = req->bufs;
618  uint32_t                bufs;
619  int                     ret = 0;
620
621#if RTEMS_NVDISK_TRACE
622  rtems_nvdisk_info (nvd, "write: blocks=%d", req->bufnum);
623#endif
624
625  for (bufs = 0; (ret == 0) && (bufs < req->bufnum); bufs++, sg++)
626  {
627    uint8_t* data;
628    uint32_t nvb;
629    uint32_t b;
630    nvb = sg->length / nvd->block_size;
631    data = sg->buffer;
632    for (b = 0; b < nvb; b++, data += nvd->block_size)
633    {
634      ret = rtems_nvdisk_write_block (nvd, sg->block + b, data);
635      if (ret)
636        break;
637    }
638  }
639
640  req->status = ret ? RTEMS_IO_ERROR : RTEMS_SUCCESSFUL;
641  req->req_done (req->done_arg, req->status);
642
643  return 0;
644}
645
646/**
647 * NV disk erase disk sets all the checksums for 0xffff.
648 *
649 * @param nvd The nvdisk data.
650 * @retval int The ioctl return value.
651 */
652static int
653rtems_nvdisk_erase_disk (rtems_nvdisk* nvd)
654{
655  uint32_t device;
656
657#if RTEMS_NVDISK_TRACE
658  rtems_nvdisk_info (nvd, "erase-disk");
659#endif
660
661  for (device = 0; device < nvd->device_count; device++)
662  {
663    rtems_nvdisk_device_ctl* dc = &nvd->devices[device];
664    uint32_t                 page;
665    for (page = 0; page < (dc->pages - dc->pages_desc); page++)
666    {
667      int ret = rtems_nvdisk_write_checksum (nvd, dc->device, page, 0xffff);
668      if (ret)
669        return ret;
670    }
671  }
672
673  return 0;
674}
675
676/**
677 * NV disk IOCTL handler.
678 *
679 * @param dd Disk device.
680 * @param req IOCTL request code.
681 * @param argp IOCTL argument.
682 * @retval The IOCTL return value
683 */
684static int
685rtems_nvdisk_ioctl (rtems_disk_device *dd, uint32_t req, void* argp)
686{
687  dev_t                     dev = rtems_disk_get_device_identifier (dd);
688  rtems_device_minor_number minor = rtems_filesystem_dev_minor_t (dev);
689  rtems_blkdev_request*     r = argp;
690  rtems_status_code         sc;
691
692  if (minor >= rtems_nvdisk_count)
693  {
694    errno = ENODEV;
695    return -1;
696  }
697
698  if (rtems_nvdisks[minor].device_count == 0)
699  {
700    errno = ENODEV;
701    return -1;
702  }
703
704  errno = 0;
705
706  sc = rtems_semaphore_obtain (rtems_nvdisks[minor].lock, RTEMS_WAIT, 0);
707  if (sc != RTEMS_SUCCESSFUL)
708    errno = EIO;
709  else
710  {
711    errno = 0;
712    switch (req)
713    {
714      case RTEMS_BLKIO_REQUEST:
715        switch (r->req)
716        {
717          case RTEMS_BLKDEV_REQ_READ:
718            errno = rtems_nvdisk_read (&rtems_nvdisks[minor], r);
719            break;
720
721          case RTEMS_BLKDEV_REQ_WRITE:
722            errno = rtems_nvdisk_write (&rtems_nvdisks[minor], r);
723            break;
724
725          default:
726            errno = EINVAL;
727            break;
728        }
729        break;
730
731      case RTEMS_NVDISK_IOCTL_ERASE_DISK:
732        errno = rtems_nvdisk_erase_disk (&rtems_nvdisks[minor]);
733        break;
734
735      case RTEMS_NVDISK_IOCTL_INFO_LEVEL:
736        rtems_nvdisks[minor].info_level = (uintptr_t) argp;
737        break;
738
739      default:
740        rtems_blkdev_ioctl (dd, req, argp);
741        break;
742    }
743
744    sc = rtems_semaphore_release (rtems_nvdisks[minor].lock);
745    if (sc != RTEMS_SUCCESSFUL)
746      errno = EIO;
747  }
748
749  return errno == 0 ? 0 : -1;
750}
751
752/**
753 * NV disk device driver initialization.
754 *
755 * @todo Memory clean up on error is really badly handled.
756 *
757 * @param major NV disk major device number.
758 * @param minor Minor device number, not applicable.
759 * @param arg Initialization argument, not applicable.
760 */
761rtems_device_driver
762rtems_nvdisk_initialize (rtems_device_major_number major,
763                        rtems_device_minor_number minor,
764                        void*                     arg __attribute__((unused)))
765{
766  const rtems_nvdisk_config* c = rtems_nvdisk_configuration;
767  rtems_nvdisk*              nvd;
768  rtems_status_code          sc;
769
770  sc = rtems_disk_io_initialize ();
771  if (sc != RTEMS_SUCCESSFUL)
772    return sc;
773
774  sc = rtems_nvdisk_crc16_gen_factors (0x8408);
775  if (sc != RTEMS_SUCCESSFUL)
776      return sc;
777
778  rtems_nvdisks = calloc (rtems_nvdisk_configuration_size,
779                          sizeof (rtems_nvdisk));
780
781  if (!rtems_nvdisks)
782    return RTEMS_NO_MEMORY;
783
784  for (minor = 0; minor < rtems_nvdisk_configuration_size; minor++, c++)
785  {
786    char     name[] = RTEMS_NVDISK_DEVICE_BASE_NAME "a";
787    dev_t    dev = rtems_filesystem_make_dev_t (major, minor);
788    uint32_t device;
789    uint32_t blocks = 0;
790
791    nvd = &rtems_nvdisks[minor];
792
793    name [sizeof(RTEMS_NVDISK_DEVICE_BASE_NAME)] += minor;
794
795    nvd->major        = major;
796    nvd->minor        = minor;
797    nvd->flags        = c->flags;
798    nvd->block_size   = c->block_size;
799    nvd->info_level   = c->info_level;
800
801    nvd->devices = calloc (c->device_count, sizeof (rtems_nvdisk_device_ctl));
802    if (!nvd->devices)
803      return RTEMS_NO_MEMORY;
804
805    for (device = 0; device < c->device_count; device++)
806    {
807      rtems_nvdisk_device_ctl* dc = &nvd->devices[device];
808
809      dc->device     = device;
810      dc->pages      = rtems_nvdisk_pages_in_device (nvd, &c->devices[device]);
811      dc->pages_desc = rtems_nvdisk_page_desc_pages (nvd, &c->devices[device]);
812      dc->block_base = blocks;
813
814      blocks += dc->pages - dc->pages_desc;
815
816      dc->descriptor = &c->devices[device];
817    }
818
819    nvd->block_count  = blocks;
820    nvd->device_count = c->device_count;
821
822    sc = rtems_disk_create_phys(dev, c->block_size, blocks,
823                                rtems_nvdisk_ioctl, NULL, name);
824    if (sc != RTEMS_SUCCESSFUL)
825    {
826      rtems_nvdisk_error ("disk create phy failed");
827      return sc;
828    }
829
830    sc = rtems_semaphore_create (rtems_build_name ('N', 'V', 'D', 'K'), 1,
831                                 RTEMS_PRIORITY | RTEMS_BINARY_SEMAPHORE |
832                                 RTEMS_INHERIT_PRIORITY, 0, &nvd->lock);
833    if (sc != RTEMS_SUCCESSFUL)
834    {
835      rtems_nvdisk_error ("disk lock create failed");
836      return sc;
837    }
838  }
839
840  rtems_nvdisk_count = rtems_nvdisk_configuration_size;
841
842  return RTEMS_SUCCESSFUL;
843}
Note: See TracBrowser for help on using the repository browser.