| /**************************************************************************** |
| * apps/testing/nand_sim/nand_sim_main.c |
| * |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. The |
| * ASF licenses this file to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance with the |
| * License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations |
| * under the License. |
| * |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Included Files |
| ****************************************************************************/ |
| |
| #include <debug.h> |
| #include <stdio.h> |
| |
| #include <nuttx/drivers/drivers.h> |
| #include <nuttx/mtd/nand.h> |
| #include <nuttx/mtd/nand_scheme.h> |
| #include <nuttx/mtd/nand_ram.h> |
| #include <nuttx/mtd/nand_wrapper.h> |
| |
| /**************************************************************************** |
| * Pre-processor Definitions |
| ****************************************************************************/ |
| |
| #define NAND_SIM_NAME "nand" |
| #define NAND_SIM_PATH "/dev/" NAND_SIM_NAME |
| |
| /**************************************************************************** |
| * Private Types |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Private Data |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Public Data |
| ****************************************************************************/ |
| |
| FAR struct mtd_dev_s *g_nand_sim_mtd_wrapper; |
| FAR struct mtd_dev_s *g_nand_sim_mtd_under; |
| FAR struct nand_raw_s *g_nand_mtd_raw; |
| |
| /**************************************************************************** |
| * External Functions |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Private Functions |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Public Functions |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Name: wrapper_init |
| * |
| * Description: |
| * Initializes the wrapper by allocating memory and assiging the methods. |
| * |
| * Returned Value: |
| * 0: Successful |
| * -ENOMEM: No memory left to allocate device |
| * |
| ****************************************************************************/ |
| |
| int wrapper_init(void) |
| { |
| struct nand_dev_s *under; |
| struct nand_dev_s *wrapper; |
| |
| g_nand_sim_mtd_wrapper = kmm_zalloc(sizeof(struct nand_wrapper_dev_s)); |
| if (g_nand_sim_mtd_wrapper == NULL) |
| { |
| return -ENOMEM; |
| } |
| |
| under = &((struct nand_wrapper_dev_s *)g_nand_sim_mtd_wrapper)->under; |
| wrapper = &((struct nand_wrapper_dev_s *)g_nand_sim_mtd_wrapper)->wrapper; |
| |
| memcpy(under, g_nand_sim_mtd_under, sizeof(struct nand_dev_s)); |
| memcpy(wrapper, g_nand_sim_mtd_under, sizeof(struct nand_dev_s)); |
| |
| nand_wrapper_initialize(); |
| |
| ((struct mtd_dev_s *)wrapper)->name = NAND_SIM_NAME; |
| ((struct mtd_dev_s *)wrapper)->erase = nand_wrapper_erase; |
| ((struct mtd_dev_s *)wrapper)->bread = nand_wrapper_bread; |
| ((struct mtd_dev_s *)wrapper)->bwrite = nand_wrapper_bwrite; |
| ((struct mtd_dev_s *)wrapper)->ioctl = nand_wrapper_ioctl; |
| ((struct mtd_dev_s *)wrapper)->isbad = nand_wrapper_isbad; |
| ((struct mtd_dev_s *)wrapper)->markbad = nand_wrapper_markbad; |
| |
| return OK; |
| } |
| |
| /**************************************************************************** |
| * Name: terminate |
| * |
| * Description: |
| * Handles the SIGTERM signal by exitting gracefully. |
| * |
| ****************************************************************************/ |
| |
| void terminate(int sig) |
| { |
| kmm_free(g_nand_sim_mtd_under); |
| kmm_free(g_nand_sim_mtd_wrapper); |
| |
| unregister_mtddriver(NAND_SIM_PATH); |
| syslog(LOG_DEBUG, "Exited!\n"); |
| } |
| |
| /**************************************************************************** |
| * Name: nand_sim_main |
| * |
| * Description: |
| * Entry point of the device emulator. |
| * |
| ****************************************************************************/ |
| |
| int main(int argc, FAR char *argv[]) |
| { |
| int ret; |
| pid_t pid; |
| |
| /* Daemon */ |
| |
| pid = fork(); |
| |
| if (pid > 0) |
| { |
| return OK; |
| } |
| |
| if (daemon(0, 1) == -1) |
| { |
| ret = EXIT_FAILURE; |
| goto errout; |
| } |
| |
| /* Signal Handlers */ |
| |
| signal(SIGTERM, terminate); |
| |
| /* Initializers */ |
| |
| /* Raw NAND MTD Device */ |
| |
| g_nand_mtd_raw = kmm_zalloc(sizeof(struct nand_raw_s)); |
| if (g_nand_mtd_raw == NULL) |
| { |
| ret = -ENOMEM; |
| goto errout_with_logs; |
| } |
| |
| g_nand_sim_mtd_under = nand_ram_initialize(g_nand_mtd_raw); |
| if (g_nand_sim_mtd_under == NULL) |
| { |
| ret = -EINVAL; |
| goto errout_with_raw_s; |
| } |
| |
| ret = wrapper_init(); |
| if (ret < 0) |
| { |
| goto errout_with_mtd_under; |
| } |
| |
| /* Under device driver is already copied to wrapper, so free. */ |
| |
| kmm_free(g_nand_sim_mtd_under); |
| |
| ret = register_mtddriver(NAND_SIM_PATH, |
| g_nand_sim_mtd_wrapper, |
| 0777, NULL); |
| if (ret < 0) |
| { |
| goto errout_with_mtd_wrapper; |
| } |
| |
| printf("Driver running!\n"); |
| |
| /* To keep the daemon still running. All events are handled by signals */ |
| |
| while (1) |
| { |
| sleep(1); |
| } |
| |
| /* Won't reach this point */ |
| |
| return OK; |
| |
| errout_with_mtd_wrapper: |
| kmm_free(g_nand_sim_mtd_wrapper); |
| |
| errout_with_mtd_under: |
| kmm_free(g_nand_sim_mtd_under); |
| |
| errout_with_raw_s: |
| kmm_free(g_nand_mtd_raw); |
| |
| errout_with_logs: |
| unregister_mtddriver(NAND_SIM_PATH); |
| |
| errout: |
| return ret; |
| } |