source: rtems/cpukit/libblock/src/nvdisk.c @ f97536d

5
Last change on this file since f97536d was f97536d, checked in by Sebastian Huber <sebastian.huber@…>, on 10/16/15 at 06:21:48

basdefs.h: Add and use RTEMS_UNUSED

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