新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > linux設備模型之uart驅動架構分析

        linux設備模型之uart驅動架構分析

        作者: 時間:2016-10-08 來源:網絡 收藏

        tty->alt_speed = 0;

        state->info->tty = tty;

        /*

        * If the port is in the middle of closing, bail out now.

        */

        if (tty_hung_up_p(filp)) {

        retval = -EAGAIN;

        state->count--;

        mutex_unlock(state->mutex);

        goto fail;

        }

        /*

        * Make sure the device is in D0 state.

        */

        if (state->count == 1)

        uart_change_pm(state, 0);

        /*

        * Start up the serial port.

        */

        retval = uart_startup(state, 0);

        /*

        * If we succeeded, wait until the port is ready.

        */

        if (retval == 0)

        retval = uart_block_til_ready(filp, state);

        mutex_unlock(state->mutex);

        /*

        * If this is the first open to succeed, adjust things to suit.

        */

        if (retval == 0 !(state->info->flags UIF_NORMAL_ACTIVE)) {

        state->info->flags |= UIF_NORMAL_ACTIVE;

        uart_update_termios(state);

        }

        fail:

        return retval;

        }

        int ret = 0;

        state = drv->state + line;

        if (mutex_lock_interruptible(state->mutex)) {

        ret = -ERESTARTSYS;

        goto err;

        }

        state->count++;

        if (!state->port || state->port->flags UPF_DEAD) {

        ret = -ENXIO;

        goto err_unlock;

        }

        if (!state->info) {

        state->info = kzalloc(sizeof(struct uart_info), GFP_KERNEL);

        if (state->info) {

        init_waitqueue_head(state->info->open_wait);

        init_waitqueue_head(state->info->delta_msr_wait);

        /*

        * Link the info into the other structures.

        */

        state->port->info = state->info;

        tasklet_init(state->info->tlet, uart_tasklet_action,

        (unsigned long)state);

        } else {

        ret = -ENOMEM;

        goto err_unlock;

        }

        }

        return state;

        err_unlock:

        state->count--;

        mutex_unlock(state->mutex);

        err:

        return ERR_PTR(ret);

        }

        從代碼中可以看出。這里注要是操作是初始化state->info.注意port->info就是state->info的一個副本。即port直接通過port->info可以找到它要操作的緩存區。

        uart_startup()代碼如下:

        static int uart_startup(struct uart_state *state, int init_hw)

        {

        struct uart_info *info = state->info;

        struct uart_port *port = state->port;

        unsigned long page;

        int retval = 0;

        if (info->flags UIF_INITIALIZED)

        return 0;

        /*

        * Set the TTY IO error marker - we will only clear this

        * once we have successfully opened the port. Also set

        * up the tty->alt_speed kludge

        */

        set_bit(TTY_IO_ERROR, info->tty->flags);

        if (port->type == PORT_UNKNOWN)

        return 0;

        /*

        * Initialise and allocate the transmit and temporary

        * buffer.

        */

        if (!info->xmit.buf) {

        page = get_zeroed_page(GFP_KERNEL);

        if (!page)

        return -ENOMEM;

        info->xmit.buf = (unsigned char *) page;

        uart_circ_clear(info->xmit);

        }

        retval = port->ops->startup(port);

        if (retval == 0) {

        if (init_hw) {

        /*

        * Initialise the hardware port settings.

        */

        uart_change_speed(state, NULL);

        /*

        * Setup the RTS and DTR signals once the

        * port is open and ready to respond.

        */

        if (info->tty->termios->c_cflag CBAUD)

        uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR);

        }

        if (info->flags UIF_CTS_FLOW) {

        spin_lock_irq(port->lock);

        if (!(port->ops->get_mctrl(port) TIOCM_CTS))

        info->tty->hw_stopped = 1;

        spin_unlock_irq(port->lock);

        }

        info->flags |= UIF_INITIALIZED;

        clear_bit(TTY_IO_ERROR, info->tty->flags);

        }

        if (retval capable(CAP_SYS_ADMIN))

        retval = 0;

        return retval;

        }

        在這里,注要完成對環形緩沖,即info->xmit的初始化。然后調用port->ops->startup( )將這個port帶入到工作狀態。其它的是一個可調參數的設置,就不詳細講解了。

        七:設備節點的write操作

        Write操作對應的操作接口為uart_write( )。代碼如下:

        static int

        uart_write(struct tty_struct *tty, const unsigned char *buf, int count)

        {

        struct uart_state *state = tty->driver_data;

        struct uart_port *port;

        struct circ_buf *circ;

        unsigned long flags;

        int c, ret = 0;

        /*

        * This means you called this function _after_ the port was

        * closed. No cookie for you.

        */

        if (!state || !state->info) {

        WARN_ON(1);

        return -EL3HLT;

        }

        port = state->port;



        關鍵詞:

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 南宫市| 乌审旗| 甘谷县| 万安县| 都江堰市| 绵阳市| 黄冈市| 舟曲县| 来安县| 类乌齐县| 驻马店市| 旬邑县| 科技| 敦化市| 株洲县| 常宁市| 衡阳市| 巴东县| 社旗县| 松原市| 延吉市| 鄂温| 商南县| 邓州市| 开化县| 泾阳县| 连州市| 翼城县| 陇西县| 弋阳县| 永嘉县| 开阳县| 东乌珠穆沁旗| 同德县| 咸丰县| 凤山市| 休宁县| 崇信县| 翁牛特旗| 巴南区| 加查县|