⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 psdev.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 4 页
字号:
        return -EINVAL;}static int presto_psdev_open(struct inode * inode, struct file * file){         struct upc_comm *upccom;         ENTRY;         if ( ! (upccom = presto_psdev_f2u(file)) ) {                 kdev_t dev = file->f_dentry->d_inode->i_rdev;                 printk("InterMezzo: %s, bad device %s\n",                        __FUNCTION__, kdevname(dev));                 EXIT;                 return -EINVAL;         }        MOD_INC_USE_COUNT;        CDEBUG(D_PSDEV, "Psdev_open: uc_pid: %d, caller: %d, flags: %d\n",               upccom->uc_pid, current->pid, file->f_flags);        EXIT;        return 0;}static int presto_psdev_release(struct inode * inode, struct file * file){        struct upc_comm *upccom;        struct upc_req *req;        struct list_head *lh;        ENTRY;        if ( ! (upccom = presto_psdev_f2u(file)) ) {                kdev_t dev = file->f_dentry->d_inode->i_rdev;                printk("InterMezzo: %s, bad device %s\n",                       __FUNCTION__, kdevname(dev));        }        if ( upccom->uc_pid != current->pid ) {                printk("psdev_release: Not lento.\n");                MOD_DEC_USE_COUNT;                return 0;        }        MOD_DEC_USE_COUNT;        CDEBUG(D_PSDEV, "Lento: pid %d\n", current->pid);        upccom->uc_pid = 0;        /* Wake up clients so they can return. */        CDEBUG(D_PSDEV, "Wake up clients sleeping for pending.\n");        lh = &upccom->uc_pending;        while ( (lh = lh->next) != &upccom->uc_pending) {                req = list_entry(lh, struct upc_req, rq_chain);                /* Async requests stay around for a new lento */                if (req->rq_flags & REQ_ASYNC) {                        continue;                }                /* the sleeper will free the req and data */                req->rq_flags |= REQ_DEAD;                 wake_up(&req->rq_sleep);        }        CDEBUG(D_PSDEV, "Wake up clients sleeping for processing\n");        lh = &upccom->uc_processing;        while ( (lh = lh->next) != &upccom->uc_processing) {                req = list_entry(lh, struct upc_req, rq_chain);                /* freeing of req and data is done by the sleeper */                req->rq_flags |= REQ_DEAD;                 wake_up(&req->rq_sleep);        }        CDEBUG(D_PSDEV, "Done.\n");        EXIT;        return 0;}static struct file_operations presto_psdev_fops = {        read:    presto_psdev_read,        write:   presto_psdev_write,        poll:    presto_psdev_poll,        ioctl:   presto_psdev_ioctl,        open:    presto_psdev_open,        release: presto_psdev_release};int  presto_psdev_init(void){        int i;#ifdef PRESTO_DEVEL        if (register_chrdev(PRESTO_PSDEV_MAJOR, "intermezzo_psdev_devel",                           &presto_psdev_fops)) {                printk(KERN_ERR "presto_psdev: unable to get major %d\n",                       PRESTO_PSDEV_MAJOR);                return -EIO;        }#else        if (register_chrdev(PRESTO_PSDEV_MAJOR, "intermezzo_psdev",                           &presto_psdev_fops)) {                printk("presto_psdev: unable to get major %d\n",                       PRESTO_PSDEV_MAJOR);                return -EIO;        }#endif        memset(&upc_comms, 0, sizeof(upc_comms));        for ( i = 0 ; i < MAX_PRESTODEV ; i++ ) {                char *name;                struct upc_comm *psdev = &upc_comms[i];                INIT_LIST_HEAD(&psdev->uc_pending);                INIT_LIST_HEAD(&psdev->uc_processing);                INIT_LIST_HEAD(&psdev->uc_cache_list);                init_waitqueue_head(&psdev->uc_waitq);                psdev->uc_hard = 0;                psdev->uc_no_filter = 0;                psdev->uc_no_journal = 0;                psdev->uc_no_upcall = 0;                psdev->uc_timeout = 30;                psdev->uc_errorval = 0;                psdev->uc_minor = i;                PRESTO_ALLOC(name, char *, strlen(PRESTO_PSDEV_NAME "256")+1);                if (!name) {                         printk("Unable to allocate memory for device name\n");                        continue;                }                sprintf(name, PRESTO_PSDEV_NAME "%d", i);                 psdev->uc_devname = name;        }        return 0;}void presto_psdev_cleanup(void){        int i;        for ( i = 0 ; i < MAX_PRESTODEV ; i++ ) {                struct upc_comm *psdev = &upc_comms[i];                struct list_head *lh;                if ( ! list_empty(&psdev->uc_pending)) {                         printk("Weird, tell Peter: module cleanup and pending list not empty dev %d\n", i);                }                if ( ! list_empty(&psdev->uc_processing)) {                         printk("Weird, tell Peter: module cleanup and processing list not empty dev %d\n", i);                }                if ( ! list_empty(&psdev->uc_cache_list)) {                         printk("Weird, tell Peter: module cleanup and cache listnot empty dev %d\n", i);                }                if (psdev->uc_devname) {                        PRESTO_FREE(psdev->uc_devname,                                    strlen(PRESTO_PSDEV_NAME "256")+1);                }                lh = psdev->uc_pending.next;                while ( lh != &psdev->uc_pending) {                        struct upc_req *req;                        req = list_entry(lh, struct upc_req, rq_chain);                        lh = lh->next;                        if ( req->rq_flags & REQ_ASYNC ) {                                list_del(&(req->rq_chain));                                CDEBUG(D_UPCALL, "free pending upcall type %d\n",                                       req->rq_opcode);                                PRESTO_FREE(req->rq_data, req->rq_bufsize);                                PRESTO_FREE(req, sizeof(struct upc_req));                        } else {                                req->rq_flags |= REQ_DEAD;                                 wake_up(&req->rq_sleep);                        }                }                lh = &psdev->uc_processing;                while ( (lh = lh->next) != &psdev->uc_processing ) {                        struct upc_req *req;                        req = list_entry(lh, struct upc_req, rq_chain);                        list_del(&(req->rq_chain));                        req->rq_flags |= REQ_DEAD;                         wake_up(&req->rq_sleep);                }        }}/* * lento_upcall and lento_downcall routines */static inline unsigned long lento_waitfor_upcall(struct upc_req *req,                                                 int minor){        DECLARE_WAITQUEUE(wait, current);        unsigned long posttime;        req->rq_posttime = posttime = jiffies;        add_wait_queue(&req->rq_sleep, &wait);        for (;;) {                if ( upc_comms[minor].uc_hard == 0 )                        current->state = TASK_INTERRUPTIBLE;                else                        current->state = TASK_UNINTERRUPTIBLE;                /* got a reply */                if ( req->rq_flags & (REQ_WRITE | REQ_DEAD) )                        break;                if ( !upc_comms[minor].uc_hard && signal_pending(current) ) {                        /* if this process really wants to die, let it go */                        if (sigismember(&(current->pending.signal), SIGKILL)||                            sigismember(&(current->pending.signal), SIGINT) )                                break;                        /* signal is present: after timeout always return                           really smart idea, probably useless ... */                        if ( time_after(jiffies, req->rq_posttime +                             upc_comms[minor].uc_timeout * HZ) )                                break;                }                schedule();        }      list_del(&req->rq_chain);       INIT_LIST_HEAD(&req->rq_chain);         remove_wait_queue(&req->rq_sleep, &wait);        current->state = TASK_RUNNING;        CDEBUG(D_SPECIAL, "posttime: %ld, returned: %ld\n",               posttime, jiffies-posttime);        return  (jiffies - posttime);}/* * lento_upcall will return an error in the case of * failed communication with Lento _or_ will peek at Lento * reply and return Lento's error. * * As lento has 2 types of errors, normal errors (positive) and internal * errors (negative), normal errors are negated, while internal errors * are all mapped to -EINTR, while showing a nice warning message. (jh) * * lento_upcall will always free buffer, either directly, when an upcall * is read (in presto_psdev_read), when the filesystem is unmounted, or * when the module is unloaded. */int lento_upcall(int minor, int bufsize, int *rep_size, union up_args *buffer,                 int async, struct upc_req *rq){        unsigned long runtime;        struct upc_comm *upc_commp;        union down_args *out;        struct upc_req *req;        int error = 0;        ENTRY;        upc_commp = &(upc_comms[minor]);        if (upc_commp->uc_no_upcall) {                EXIT;                goto exit_buf;        }        if (!upc_commp->uc_pid && !async) {                EXIT;                error = -ENXIO;                goto exit_buf;        }        /* Format the request message. */        CDEBUG(D_UPCALL, "buffer at %p, size %d\n", buffer, bufsize);        PRESTO_ALLOC(req, struct upc_req *, sizeof(struct upc_req));        if ( !req ) {                EXIT;                error = -ENOMEM;                goto exit_buf;        }        req->rq_data = (void *)buffer;        req->rq_flags = 0;        req->rq_bufsize = bufsize;        req->rq_rep_size = 0;        req->rq_opcode = ((union up_args *)buffer)->uh.opcode;        req->rq_unique = ++upc_commp->uc_seq;        init_waitqueue_head(&req->rq_sleep);        /* Fill in the common input args. */        ((union up_args *)buffer)->uh.unique = req->rq_unique;        /* Append msg to pending queue and poke Lento. */        list_add(&req->rq_chain, upc_commp->uc_pending.prev);        CDEBUG(D_UPCALL,               "Proc %d waking Lento %d for(opc,uniq) =(%d,%d) msg at %p.\n",               current->pid, upc_commp->uc_pid, req->rq_opcode,               req->rq_unique, req);        wake_up_interruptible(&upc_commp->uc_waitq);        if ( async ) {                req->rq_flags = REQ_ASYNC;                if( rq != NULL ) {                        *rq = *req; /* struct copying */                }                /* req, rq_data are freed in presto_psdev_read for async */                EXIT;                return 0;        }        /* We can be interrupted while we wait for Lento to process         * our request.  If the interrupt occurs before Lento has read         * the request, we dequeue and return. If it occurs after the         * read but before the reply, we dequeue, send a signal         * message, and return. If it occurs after the reply we ignore         * it. In no case do we want to restart the syscall.  If it         * was interrupted by a lento shutdown (psdev_close), return         * ENODEV.  */        /* Go to sleep.  Wake up on signals only after the timeout. */        runtime = lento_waitfor_upcall(req, minor);        CDEBUG(D_TIMING, "opc: %d time: %ld uniq: %d size: %d\n",               req->rq_opcode, jiffies - req->rq_posttime,               req->rq_unique, req->rq_rep_size);        CDEBUG(D_UPCALL,               "..process %d woken up by Lento for req at 0x%p, data at %p\n",               current->pid, req, req->rq_data);        if (upc_commp->uc_pid) {      /* i.e. Lento is still alive */          /* Op went through, interrupt or not we go on */            if (req->rq_flags & REQ_WRITE) {                    out = (union down_args *)req->rq_data;                    /* here we map positive Lento errors to kernel errors */                    if ( out->dh.result < 0 ) {                            printk("Tell Peter: Lento returns negative error %d, for oc %d!\n",                                   out->dh.result, out->dh.opcode);                          out->dh.result = EINVAL;                    }                    error = -out->dh.result;                    CDEBUG(D_UPCALL, "upcall: (u,o,r) (%d, %d, %d) out at %p\n",                           out->dh.unique, out->dh.opcode, out->dh.result, out);                    *rep_size = req->rq_rep_size;                    EXIT;                    goto exit_req;            }            /* Interrupted before lento read it. */            if ( !(req->rq_flags & REQ_READ) && signal_pending(current)) {                    CDEBUG(D_UPCALL,                           "Interrupt before read: (op,un)=(%d,%d), flags %x\n",                           req->rq_opcode, req->rq_unique, req->rq_flags);                    /* perhaps the best way to convince the app to give up? */                    error = -EINTR;                    EXIT;                    goto exit_req;            }            /* interrupted after Lento did its read, send signal */            if ( (req->rq_flags & REQ_READ) && signal_pending(current) ) {                    union up_args *sigargs;                    struct upc_req *sigreq;                    CDEBUG(D_UPCALL,"Sending for: op = %d.%d, flags = %x\n",                           req->rq_opcode, req->rq_unique, req->rq_flags);                    error = -EINTR;                    /* req, rq_data are freed in presto_psdev_read for async */                    PRESTO_ALLOC(sigreq, struct upc_req *,                                 sizeof (struct upc_req));                    if (!sigreq) {                            error = -ENOMEM;                            EXIT;                            goto exit_req;                    }                    PRESTO_ALLOC((sigreq->rq_data), char *,                                 sizeof(struct lento_up_hdr));                    if (!(sigreq->rq_data)) {                            PRESTO_FREE(sigreq, sizeof (struct upc_req));                            error = -ENOMEM;                            EXIT;                            goto exit_req;                    }                    sigargs = (union up_args *)sigreq->rq_data;                    sigargs->uh.opcode = LENTO_SIGNAL;                    sigargs->uh.unique = req->rq_unique;                    sigreq->rq_flags = REQ_ASYNC;                    sigreq->rq_opcode = sigargs->uh.opcode;                    sigreq->rq_unique = sigargs->uh.unique;                    sigreq->rq_bufsize = sizeof(struct lento_up_hdr);                    sigreq->rq_rep_size = 0;                    CDEBUG(D_UPCALL,                           "presto_upcall: enqueing signal msg (%d, %d)\n",                           sigreq->rq_opcode, sigreq->rq_unique);                    /* insert at head of queue! */                    list_add(&sigreq->rq_chain, &upc_commp->uc_pending);                    wake_up_interruptible(&upc_commp->uc_waitq);            } else {                  printk("Lento: Strange interruption - tell Peter.\n");                    error = -EINTR;            }        } else {        /* If lento died i.e. !UC_OPEN(upc_commp) */                printk("presto_upcall: Lento dead on (op,un) (%d.%d) flags %d\n",                       req->rq_opcode, req->rq_unique, req->rq_flags);                error = -ENODEV;        }exit_req:        PRESTO_FREE(req, sizeof(struct upc_req));exit_buf:        PRESTO_FREE(buffer, bufsize);        return error;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -