新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > ARM的嵌入式Linux移植體驗之設備驅動

        ARM的嵌入式Linux移植體驗之設備驅動

        作者: 時間:2012-11-13 來源:網絡 收藏

        static int write_cached_data (struct mtdblk_dev *mtdblk)
        {
         struct mtd_info *mtd = mtdblk->mtd;
         int ret;

         if (mtdblk->cache_state != STATE_DIRTY)
          return 0;

         DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: writing cached data for /"%s/" "
        "at 0x%lx, size 0x%x/n", mtd->name,
        mtdblk->cache_offset, mtdblk->cache_size);

         ret = erase_write (mtd, mtdblk->cache_offset,
        mtdblk->cache_size, mtdblk->cache_data);
         if (ret)
          return ret;

         mtdblk->cache_state = STATE_EMPTY;
         return 0;
        }

        static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos,
        int len, const char *buf)
        {
         …
        }

        static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos,
        int len, char *buf)
        {
         …
        }

        static int mtdblock_open(struct inode *inode, struct file *file)
        {
         …
        }

        static release_t mtdblock_release(struct inode *inode, struct file *file)
        {
         int dev;
         struct mtdblk_dev *mtdblk;
         DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release/n");

         if (inode == NULL)
          release_return(-ENODEV);

         dev = minor(inode->i_rdev);
         mtdblk = mtdblks[dev];

         down(mtdblk->cache_sem);
         write_cached_data(mtdblk);
         up(mtdblk->cache_sem);

         spin_lock(mtdblks_lock);
         if (!--mtdblk->count) {
          /* It was the last usage. Free the device */
          mtdblks[dev] = NULL;
          spin_unlock(mtdblks_lock);
          if (mtdblk->mtd->sync)
           mtdblk->mtd->sync(mtdblk->mtd);
           put_mtd_device(mtdblk->mtd);
           vfree(mtdblk->cache_data);
           kfree(mtdblk);
         } else {
          spin_unlock(mtdblks_lock);
         }

         DEBUG(MTD_DEBUG_LEVEL1, "ok/n");
         
         BLK_DEC_USE_COUNT;
         release_return(0);
        }

        /*
        * This is a special request_fn because it is executed in a process context
        * to be able to sleep independently of the caller. The
        * io_request_lock (for 2.5) or queue_lock (for >=2.5) is held upon entry
        * and exit. The head of our request queue is considered active so there is
        * no need to dequeue requests before we are done.
        */
        static void handle_mtdblock_request(void)
        {
         struct request *req;
         struct mtdblk_dev *mtdblk;
         unsigned int res;

         for (;;) {
          INIT_REQUEST;
          req = CURRENT;
          spin_unlock_irq(QUEUE_LOCK(QUEUE));
          mtdblk = mtdblks[minor(req->rq_dev)];
          res = 0;

          if (minor(req->rq_dev) >= MAX_MTD_DEVICES)
           panic("%s : minor out of bound", __FUNCTION__);

          if (!IS_REQ_CMD(req))
           goto end_req;

          if ((req->sector + req->current_nr_sectors) > (mtdblk->mtd->size >> 9))
           goto end_req;

          // Handle the request
          switch (rq_data_dir(req))
          {
           int err;

           case READ:
            down(mtdblk->cache_sem);
            err = do_cached_read (mtdblk, req->sector 9,
        req->current_nr_sectors 9,
        req->buffer);
            up(mtdblk->cache_sem);
            if (!err)
             res = 1;
            break;

           case WRITE:
            // Read only device
            if ( !(mtdblk->mtd->flags MTD_WRITEABLE) )
             break;

            // Do the write
            down(mtdblk->cache_sem);
            err = do_cached_write (mtdblk, req->sector 9,req->current_nr_sectors 9, req->buffer);
            up(mtdblk->cache_sem);
            if (!err)
             res = 1;
            break;
          }

         end_req:
         spin_lock_irq(QUEUE_LOCK(QUEUE));
         end_request(res);
        }
        }

        static volatile int leaving = 0;
        static DECLARE_MUTEX_LOCKED(thread_sem);
        static DECLARE_WAIT_QUEUE_HEAD(thr_wq);

        int mtdblock_thread(void *dummy)
        {
         …
        }

        #define RQFUNC_ARG request_queue_t *q

        static void mtdblock_request(RQFUNC_ARG)
        {
         /* Don't do anything, except wake the thread if necESSary */
         wake_up(thr_wq);
        }

        static int mtdblock_ioctl(struct inode * inode, struct file * file,
        unsigned int CMd, unsigned long arg)
        {
         struct mtdblk_dev *mtdblk;
         mtdblk = mtdblks[minor(inode->i_rdev)];
         switch (cMD) {
          case BLKGETSIZE: /* Return device size */
           return put_user((mtdblk->mtd->size >> 9), (unsigned long *) arg);

          case BLKFLSBUF:
           if(!capable(CAP_SYS_ADMIN))
            return -EACCES;
           fsync_dev(inode->i_rdev);
           invalidate_buffers(inode->i_rdev);
           down(mtdblk->cache_sem);
           write_cached_data(mtdblk);
           up(mtdblk->cache_sem);
           if (mtdblk->mtd->sync)
            mtdblk->mtd->sync(mtdblk->mtd);
            return 0;
          default:
           return -EINVAL;
         }
        }

        linux操作系統文章專題:linux操作系統詳解(linux不再難懂)

        linux相關文章:linux教程




        關鍵詞: ARM 嵌入式 Linux移植

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 易门县| 安康市| 三门县| 隆回县| 阿坝县| 宁陵县| 镶黄旗| 自治县| 泊头市| 伊金霍洛旗| 文成县| 万载县| 龙南县| 自贡市| 团风县| 重庆市| 三亚市| 东明县| 邵东县| 嘉善县| 基隆市| 德钦县| 莲花县| 永修县| 高雄县| 郧西县| 南通市| 彝良县| 砀山县| 都匀市| 五大连池市| 同心县| 吴堡县| 右玉县| 徐州市| 利津县| 华容县| 南阳市| 布拖县| 云浮市| 册亨县|