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

📄 16550a.c

📁 xenomai 很好的linux实时补丁
💻 C
📖 第 1 页 / 共 3 页
字号:
        rtdm_lock_put_irqrestore(&ctx->lock, lock_ctx);    }    if (testbits(config->config_mask, RTSER_SET_EVENT_MASK)) {        /* change event mask atomically */        rtdm_lock_get_irqsave(&ctx->lock, lock_ctx);        ctx->config.event_mask = config->event_mask & EVENT_MASK;        ctx->ioc_events = 0;        if (testbits(config->event_mask, RTSER_EVENT_RXPEND) &&            (ctx->in_npend > 0))            ctx->ioc_events |= RTSER_EVENT_RXPEND;        if (testbits(config->event_mask, RTSER_EVENT_ERRPEND) && ctx->status)            ctx->ioc_events |= RTSER_EVENT_ERRPEND;        if (testbits(config->event_mask,                     RTSER_EVENT_MODEMHI | RTSER_EVENT_MODEMLO))            /* enable modem status interrupt */            ctx->ier_status |= IER_TX;        else            /* disable modem status interrupt */            ctx->ier_status &= ~IER_TX;        outb(ctx->ier_status, IER(ctx->dev_id));        rtdm_lock_put_irqrestore(&ctx->lock, lock_ctx);    }    if (testbits(config->config_mask, RTSER_SET_HANDSHAKE)) {        /* change handshake atomically */        rtdm_lock_get_irqsave(&ctx->lock, lock_ctx);        ctx->config.handshake = config->handshake;        switch (ctx->config.handshake) {            case RTSER_RTSCTS_HAND:                // ...?            default: /* RTSER_NO_HAND */                ctx->mcr_status =                    RTSER_MCR_DTR | RTSER_MCR_RTS | RTSER_MCR_OUT2;                break;        }        outb(ctx->mcr_status, MCR(dev_id));        rtdm_lock_put_irqrestore(&ctx->lock, lock_ctx);    }    return ret;}void rt_16550_cleanup_ctx(struct rt_16550_context *ctx){    rtdm_event_destroy(&ctx->in_event);    rtdm_event_destroy(&ctx->out_event);    rtdm_event_destroy(&ctx->ioc_event);    rtdm_mutex_destroy(&ctx->out_lock);}int rt_16550_open(struct rtdm_dev_context *context,                  rtdm_user_info_t *user_info, int oflags){    struct rt_16550_context *ctx;    int                     dev_id = context->device->device_id;    int                     ret;    uint64_t                *dummy;    rtdm_lockctx_t          lock_ctx;    ctx = (struct rt_16550_context *)context->dev_private;    /* IPC initialisation - cannot fail with used parameters */    rtdm_lock_init(&ctx->lock);    rtdm_event_init(&ctx->in_event, 0);    rtdm_event_init(&ctx->out_event, 0);    rtdm_event_init(&ctx->ioc_event, 0);    rtdm_mutex_init(&ctx->out_lock);    ctx->dev_id         = dev_id;    ctx->in_head        = 0;    ctx->in_tail        = 0;    ctx->in_npend       = 0;    ctx->in_nwait       = 0;    ctx->in_lock        = 0;    ctx->in_history     = NULL;    ctx->out_head       = 0;    ctx->out_tail       = 0;    ctx->out_npend      = 0;    ctx->ioc_events     = 0;    ctx->ioc_event_lock = 0;    ctx->status         = 0;    rt_16550_set_config(ctx, &default_config, &dummy);    ret = rtdm_irq_request(&ctx->irq_handle, irq[dev_id], rt_16550_interrupt,                           RTDM_IRQTYPE_SHARED | RTDM_IRQTYPE_EDGE,                           context->device->proc_name, ctx);    if (ret < 0) {        /* reset DTR and RTS */        outb(0, MCR(dev_id));        rt_16550_cleanup_ctx(ctx);        return ret;    }    rtdm_irq_enable(&ctx->irq_handle);    rtdm_lock_get_irqsave(&ctx->lock, lock_ctx);    /* enable IRQ interrupts */    ctx->ier_status = IER_RX;    outb(IER_RX, IER(dev_id));    rtdm_lock_put_irqrestore(&ctx->lock, lock_ctx);    return 0;}int rt_16550_close(struct rtdm_dev_context *context,                   rtdm_user_info_t *user_info){    struct rt_16550_context *ctx;    int                     dev_id;    uint64_t                *in_history;    rtdm_lockctx_t          lock_ctx;    ctx    = (struct rt_16550_context *)context->dev_private;    dev_id = ctx->dev_id;    rtdm_lock_get_irqsave(&ctx->lock, lock_ctx);    /* reset DTR and RTS */    outb(0, MCR(dev_id));    /* mask all UART interrupts and clear pending ones. */    outb(0, IER(dev_id));    inb(IIR(dev_id));    inb(LSR(dev_id));    inb(RHR(dev_id));    inb(MSR(dev_id));    in_history      = ctx->in_history;    ctx->in_history = NULL;    rtdm_lock_put_irqrestore(&ctx->lock, lock_ctx);    /* We should disable the line now, but this requires counting     * enable/disable, something not yet implemented by the core.     * At the moment this call could starve other users sharing the     * same line.    rtdm_irq_disable(&ctx->irq_handle); */    rtdm_irq_free(&ctx->irq_handle);    rt_16550_cleanup_ctx(ctx);    if (in_history) {        if (test_bit(RTDM_CREATED_IN_NRT, &context->context_flags))            kfree(in_history);        else            rtdm_free(in_history);    }    return 0;}int rt_16550_ioctl(struct rtdm_dev_context *context,                   rtdm_user_info_t *user_info, int request, void *arg){    struct rt_16550_context *ctx;    int                     ret = 0;    int                     dev_id = context->device->device_id;    ctx = (struct rt_16550_context *)context->dev_private;    switch (request) {        case RTSER_RTIOC_GET_CONFIG:            if (user_info) {                if (!rtdm_rw_user_ok(user_info, arg,                                     sizeof(struct rtser_config)) ||                    rtdm_copy_to_user(user_info, arg, &ctx->config,                                      sizeof(struct rtser_config)))                    return -EFAULT;            } else                memcpy(arg, &ctx->config, sizeof(struct rtser_config));            break;        case RTSER_RTIOC_SET_CONFIG: {            struct rtser_config *config;            struct rtser_config config_buf;            uint64_t            *hist_buf = NULL;            config = (struct rtser_config *)arg;            if (user_info) {                if (!rtdm_read_user_ok(user_info, arg,                                       sizeof(struct rtser_config)) ||                    rtdm_copy_from_user(user_info, &config_buf, arg,                                        sizeof(struct rtser_config)))                    return -EFAULT;                config = &config_buf;            }            if (testbits(config->config_mask, RTSER_SET_BAUD) &&                (config->baud_rate > baud_base[dev_id])) {                /* the baudrate is to high for this port */                return -EINVAL;            }            if (testbits(config->config_mask, RTSER_SET_TIMESTAMP_HISTORY)) {                if (test_bit(RTDM_CREATED_IN_NRT, &context->context_flags) &&                    rtdm_in_rt_context()) {                    /* already fail if we MAY allocate or release a non-RT                     * buffer in RT context */                    return -EPERM;                }                if (testbits(config->timestamp_history,                             RTSER_RX_TIMESTAMP_HISTORY)) {                    if (test_bit(RTDM_CREATED_IN_NRT,                                 &context->context_flags))                        hist_buf = kmalloc(IN_BUFFER_SIZE * sizeof(uint64_t),                                           GFP_KERNEL);                    else                        hist_buf =                            rtdm_malloc(IN_BUFFER_SIZE * sizeof(uint64_t));                    if (!hist_buf)                        return -ENOMEM;                }            }            rt_16550_set_config(ctx, config, &hist_buf);            if (hist_buf) {                if (test_bit(RTDM_CREATED_IN_NRT, &context->context_flags))                    kfree(hist_buf);                else                    rtdm_free(hist_buf);            }            break;        }        case RTSER_RTIOC_GET_STATUS: {            rtdm_lockctx_t lock_ctx;            if (user_info) {                struct rtser_status status_buf;                status_buf.line_status  = inb(LSR(ctx->dev_id));                status_buf.modem_status = inb(MSR(ctx->dev_id));                if (!rtdm_rw_user_ok(user_info, arg,                                     sizeof(struct rtser_status)) ||                    rtdm_copy_to_user(user_info, arg, &status_buf,                                      sizeof(struct rtser_status)))                    return -EFAULT;            } else {                ((struct rtser_status *)arg)->line_status  =                    inb(LSR(ctx->dev_id));                ((struct rtser_status *)arg)->modem_status =                    inb(MSR(ctx->dev_id));            }            rtdm_lock_get_irqsave(&ctx->lock, lock_ctx);            ctx->status = 0;            ctx->ioc_events &= ~RTSER_EVENT_ERRPEND;            rtdm_lock_put_irqrestore(&ctx->lock, lock_ctx);            break;        }        case RTSER_RTIOC_GET_CONTROL:            if (user_info) {                if (!rtdm_rw_user_ok(user_info, arg, sizeof(int)) ||                    rtdm_copy_to_user(user_info, arg, &ctx->mcr_status,                                      sizeof(int)))                    ret = -EFAULT;            } else                *(int *)arg = ctx->mcr_status;            break;        case RTSER_RTIOC_SET_CONTROL: {            long            new_mcr;            rtdm_lockctx_t  lock_ctx;            new_mcr = (long)arg;            rtdm_lock_get_irqsave(&ctx->lock, lock_ctx);            ctx->mcr_status = new_mcr;            outb(new_mcr, MCR(ctx->dev_id));            rtdm_lock_put_irqrestore(&ctx->lock, lock_ctx);            break;        }        case RTSER_RTIOC_WAIT_EVENT: {            struct rtser_event  ev = { rxpend_timestamp: 0 };            rtdm_lockctx_t      lock_ctx;            rtdm_toseq_t        timeout_seq;            if (!rtdm_in_rt_context())                return -ENOSYS;            /* only one waiter allowed, stop any further attempts here */            if (test_and_set_bit(0, &ctx->ioc_event_lock))                return -EBUSY;            rtdm_toseq_init(&timeout_seq, ctx->config.event_timeout);            rtdm_lock_get_irqsave(&ctx->lock, lock_ctx);            while (!ctx->ioc_events) {                /* enable error interrupt only when the user waits for it */                if (testbits(ctx->config.event_mask, RTSER_EVENT_ERRPEND)) {                    ctx->ier_status |= IER_STAT;                    outb(ctx->ier_status, IER(ctx->dev_id));                }                rtdm_lock_put_irqrestore(&ctx->lock, lock_ctx);                ret = rtdm_event_timedwait(&ctx->ioc_event,                                           ctx->config.event_timeout,                                           &timeout_seq);                if (ret < 0) {                    clear_bit(0, &ctx->ioc_event_lock);                    if (ret == -EIDRM)  /* device has been closed */                        ret = -EBADF;                    goto wait_unlock_out;                }                rtdm_lock_get_irqsave(&ctx->lock, lock_ctx);            }            ev.events = ctx->ioc_events;            ctx->ioc_events &= ~(RTSER_EVENT_MODEMHI | RTSER_EVENT_MODEMLO);            ev.last_timestamp = ctx->last_timestamp;            ev.rx_pending     = ctx->in_npend;            if (ctx->in_history)                ev.rxpend_timestamp = ctx->in_history[ctx->in_head];            rtdm_lock_put_irqrestore(&ctx->lock, lock_ctx);            if (user_info) {                if (!rtdm_rw_user_ok(user_info, arg,                                     sizeof(struct rtser_event)) ||                    rtdm_copy_to_user(user_info, arg, &ev,                                      sizeof(struct rtser_event)))                    ret = -EFAULT;            } else                memcpy(arg, &ev, sizeof(struct rtser_event));          wait_unlock_out:            /* release the simple event waiter lock */            clear_bit(0, &ctx->ioc_event_lock);            break;        }        default:            ret = -ENOTTY;    }    return ret;}ssize_t rt_16550_read(struct rtdm_dev_context *context,                      rtdm_user_info_t *user_info, void *buf, size_t nbyte){    struct rt_16550_context *ctx;    int                     dev_id;    rtdm_lockctx_t          lock_ctx;

⌨️ 快捷键说明

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