亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 2745 | 回復(fù): 0
打印 上一主題 下一主題

linux設(shè)備驅(qū)動之8250串口驅(qū)動2 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報(bào)告]
發(fā)表于 2010-01-25 15:03 |只看該作者 |倒序?yàn)g覽
static void autoconfig_irq(struct uart_8250_port *up)
{
     unsigned char save_mcr, save_ier;
     unsigned char save_ICP = 0;
     unsigned int ICP = 0;
     unsigned long irqs;
     int irq;

     if (up->port.flags & UPF_FOURPORT) {
         ICP = (up->port.iobase & 0xfe0) | 0x1f;
         save_ICP = inb_p(ICP);
         outb_p(0x80, ICP);
         (void) inb_p(ICP);
     }

     /* forget possible initially masked and pending IRQ */
     probe_irq_off(probe_irq_on());
     save_mcr = serial_inp(up, UART_MCR);
     save_ier = serial_inp(up, UART_IER);
     serial_outp(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);

     irqs = probe_irq_on();
     serial_outp(up, UART_MCR, 0);
     udelay(10);
     if (up->port.flags & UPF_FOURPORT) {
         serial_outp(up, UART_MCR,
                  UART_MCR_DTR | UART_MCR_RTS);
     } else {
         serial_outp(up, UART_MCR,
                  UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
     }
     serial_outp(up, UART_IER, 0x0f); /* enable all intrs */
     (void)serial_inp(up, UART_LSR);
     (void)serial_inp(up, UART_RX);
     (void)serial_inp(up, UART_IIR);
     (void)serial_inp(up, UART_MSR);
     serial_outp(up, UART_TX, 0xFF);
     udelay(20);
     irq = probe_irq_off(irqs);

     serial_outp(up, UART_MCR, save_mcr);
     serial_outp(up, UART_IER, save_ier);

     if (up->port.flags & UPF_FOURPORT)
         outb_p(save_ICP, ICP);

     up->port.irq = (irq > 0) ? irq : 0;
}
在上述代碼的操作中,先將8250相關(guān)中斷允許寄存器全打開.然后調(diào)用驅(qū)動使用的函數(shù), 當(dāng)它不得不探測來決定哪個(gè)中斷線被設(shè)備在使用.
probe_irq_on()將中斷暫時(shí)關(guān)掉,然后配置MCR寄存器使之發(fā)送DTR和RTS.之后再用probe_irq_off()來檢測IRQ號.如
果檢測成功,則值賦值給port->irq.
進(jìn)行到這里,conifg_port動作就完成了.
經(jīng)過這個(gè)config_port過程后,我們發(fā)現(xiàn),并沒有對serial8250_isa_devs->dev-> platform_data賦值,也就是說platform_driver->probe函數(shù)并無實(shí)質(zhì)性的處理.在第一次for循環(huán)的時(shí),就會因條件不符而退出.
四: startup操作
在前面分析uart驅(qū)動架構(gòu)的時(shí)候,曾說過,在open的時(shí)候,會調(diào)用port->startup().在本次分析的驅(qū)動中,對應(yīng)接口為serial8250_startup().分段分析如下:
static int serial8250_startup(struct uart_port *port)
{
     struct uart_8250_port *up = (struct uart_8250_port *)port;
     unsigned long flags;
     unsigned char lsr, iir;
     int retval;

     up->capabilities = uart_config[up->port.type].flags;
     up->mcr = 0;

     if (up->port.type == PORT_16C950) {
         /* Wake up and initialize UART */
         up->acr = 0;
         serial_outp(up, UART_LCR, 0xBF);
         serial_outp(up, UART_EFR, UART_EFR_ECB);
         serial_outp(up, UART_IER, 0);
         serial_outp(up, UART_LCR, 0);
         serial_icr_write(up, UART_CSR, 0); /* Reset the UART */
         serial_outp(up, UART_LCR, 0xBF);
         serial_outp(up, UART_EFR, UART_EFR_ECB);
         serial_outp(up, UART_LCR, 0);
     }

#ifdef CONFIG_SERIAL_8250_RSA
     /*
      * If this is an RSA port, see if we can kick it up to the
      * higher speed clock.
      */
     enable_rsa(up);
#endif

     /*
      * Clear the FIFO buffers and disable them.
      * (they will be reenabled in set_termios())
      */
     serial8250_clear_fifos(up);
上面的代碼都不是對應(yīng)8250芯片的情況
     /*
      * Clear the interrupt registers.
      */
     (void) serial_inp(up, UART_LSR);
     (void) serial_inp(up, UART_RX);
     (void) serial_inp(up, UART_IIR);
     (void) serial_inp(up, UART_MSR);
復(fù)位LSR,RX,IIR,MSR寄存器

     /*
      * At this point, there's no way the LSR could still be 0xff;
      * if it is, then bail out, because there's likely no UART
      * here.
      */
     if (!(up->port.flags & UPF_BUGGY_UART) &&
         (serial_inp(up, UART_LSR) == 0xff)) {
         printk("ttyS%d: LSR safety check engaged!\n", up->port.line);
         return -ENODEV;
     }
若LSR寄存器中的值為0xFF.異常
     /*
      * For a XR16C850, we need to set the trigger levels
      */
     if (up->port.type == PORT_16850) {
         unsigned char fctr;

         serial_outp(up, UART_LCR, 0xbf);

         fctr = serial_inp(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX);
         serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_RX);
         serial_outp(up, UART_TRG, UART_TRG_96);
         serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_TX);
         serial_outp(up, UART_TRG, UART_TRG_96);

         serial_outp(up, UART_LCR, 0);
     }
16850系列芯片的處理,忽略

     if (is_real_interrupt(up->port.irq)) {
         /*
          * Test for UARTs that do not reassert THRE when the
          * transmitter is idle and the interrupt has already
          * been cleared.  Real 16550s should always reassert
          * this interrupt whenever the transmitter is idle and
          * the interrupt is enabled.  Delays are necessary to
          * allow register changes to become visible.
          */
         spin_lock_irqsave(&up->port.lock, flags);

         wait_for_xmitr(up, UART_LSR_THRE);
         serial_out_sync(up, UART_IER, UART_IER_THRI);
          udelay(1); /* allow THRE to set */
         serial_in(up, UART_IIR);
         serial_out(up, UART_IER, 0);
         serial_out_sync(up, UART_IER, UART_IER_THRI);
         udelay(1); /* allow a working UART time to re-assert THRE */
         iir = serial_in(up, UART_IIR);
         serial_out(up, UART_IER, 0);

         spin_unlock_irqrestore(&up->port.lock, flags);

         /*
          * If the interrupt is not reasserted, setup a timer to
          * kick the UART on a regular basis.
          */
         if (iir & UART_IIR_NO_INT) {
              pr_debug("ttyS%d - using backup timer\n", port->line);
              up->timer.function = serial8250_backup_timeout;
              up->timer.data = (unsigned long)up;
              mod_timer(&up->timer, jiffies +
                   poll_timeout(up->port.timeout) + HZ / 5);
         }
     }
如果中斷號有效,還要進(jìn)一步判斷這個(gè)中斷號是否有效.具體操作為,先等待8250發(fā)送寄存器空.然后允許發(fā)送中斷空的中斷.然后判斷IIR寄存器是否收到
中斷.如果有沒有收到中斷,則說明這根中斷線無效.只能采用輪詢的方式.關(guān)于輪詢方式,我們在之后再以獨(dú)立章節(jié)的形式給出分析
       /*
      * If the "interrupt" for this port doesn't correspond with any
      * hardware interrupt, we use a timer-based system.  The original
      * driver used to do this with IRQ0.
      */
     if (!is_real_interrupt(up->port.irq)) {
         up->timer.data = (unsigned long)up;
         mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
     } else {
         retval = serial_link_irq_chain(up);
         if (retval)
              return retval;
     }
如果沒有設(shè)置中斷號,則采用輪詢方式.如果中斷后有效.流程轉(zhuǎn)入serial_link_irq_chain().在這個(gè)里面.會注冊中斷處理函數(shù).
/*
      * Now, initialize the UART
      */
     serial_outp(up, UART_LCR, UART_LCR_WLEN8);

     spin_lock_irqsave(&up->port.lock, flags);
     if (up->port.flags & UPF_FOURPORT) {
         if (!is_real_interrupt(up->port.irq))
              up->port.mctrl |= TIOCM_OUT1;
     } else
         /*
          * Most PC uarts need OUT2 raised to enable interrupts.
          */
         if (is_real_interrupt(up->port.irq))
              up->port.mctrl |= TIOCM_OUT2;

     serial8250_set_mctrl(&up->port, up->port.mctrl);

     /*
      * Do a quick test to see if we receive an
      * interrupt when we enable the TX irq.
      */
     serial_outp(up, UART_IER, UART_IER_THRI);
     lsr = serial_in(up, UART_LSR);
     iir = serial_in(up, UART_IIR);
     serial_outp(up, UART_IER, 0);

     if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
         if (!(up->bugs & UART_BUG_TXEN)) {
              up->bugs |= UART_BUG_TXEN;
              pr_debug("ttyS%d - enabling bad tx status workarounds\n",
                    port->line);
         }
     } else {
         up->bugs &= ~UART_BUG_TXEN;
     }

     spin_unlock_irqrestore(&up->port.lock, flags);

     /*
      * Clear the interrupt registers again for luck, and clear the
      * saved flags to avoid getting false values from polling
      * routines or the previous session.
      */
     serial_inp(up, UART_LSR);
     serial_inp(up, UART_RX);
     serial_inp(up, UART_IIR);
     serial_inp(up, UART_MSR);
     up->lsr_saved_flags = 0;
     up->msr_saved_flags = 0;

     /*
      * Finally, enable interrupts.  Note: Modem status interrupts
      * are set via set_termios(), which will be occurring imminently
      * anyway, so we don't enable them here.
      */
     up->ier = UART_IER_RLSI | UART_IER_RDI;
     serial_outp(up, UART_IER, up->ier);

     if (up->port.flags & UPF_FOURPORT) {
         unsigned int icp;
         /*
          * Enable interrupts on the AST Fourport board
          */
         icp = (up->port.iobase & 0xfe0) | 0x01f;
         outb_p(0x80, icp);
         (void) inb_p(icp);
     }

     return 0;
}
最后,就是對8250芯片的初始化了.包括:在LCR中設(shè)置數(shù)據(jù)格式,在MCR中設(shè)置允許中斷到8259.在IER中設(shè)置相關(guān)允許位.
另外在open的時(shí)候,還會調(diào)用port-> enable_ms ()接口,在本例中對應(yīng)為: serial8250_enable_ms().代碼如下:
static void serial8250_enable_ms(struct uart_port *port)
{
     struct uart_8250_port *up = (struct uart_8250_port *)port;

     /* no MSR capabilities */
     if (up->bugs & UART_BUG_NOMSR)
         return;

     up->ier |= UART_IER_MSI;
     serial_out(up, UART_IER, up->ier);
}
即允許moden中斷
  
五:數(shù)據(jù)發(fā)送的操作
在uart驅(qū)動架構(gòu)中分析過,在發(fā)送數(shù)據(jù)的時(shí)候,uart層先會將數(shù)據(jù)放入circ_buffer.最后再調(diào)用port-> start_tx().
在這里,這個(gè)接口對應(yīng)為serial8250_start_tx().代碼如下:
static void serial8250_start_tx(struct uart_port *port)
{
     struct uart_8250_port *up = (struct uart_8250_port *)port;

     if (!(up->ier & UART_IER_THRI)) {
         up->ier |= UART_IER_THRI;
         serial_out(up, UART_IER, up->ier);

         if (up->bugs & UART_BUG_TXEN) {
            , ;  unsigned char lsr, iir;
              lsr = serial_in(up, UART_LSR);
              up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
              iir = serial_in(up, UART_IIR) & 0x0f;
              if ((up->port.type == PORT_RM9000) ?
                   (lsr & UART_LSR_THRE &&
                   (iir == UART_IIR_NO_INT || iir == UART_IIR_THRI)) :
                   (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT))
                   transmit_chars(up);
         }
     }

     /*
      * Re-enable the transmitter if we disabled it.
      */
     if (up->port.type == PORT_16C950 && up->acr & UART_ACR_TXDIS) {
         up->acr &= ~UART_ACR_TXDIS;
         serial_icr_write(up, UART_ACR, up->acr);
     }
}
這個(gè)函數(shù)非常簡單.如果沒有定義發(fā)送空中斷.則在IER中打開這個(gè)中斷.關(guān)于TXEN上的bug修復(fù)和16C950類型的芯片不是我們所關(guān)注的部份.
那,這里只是打開了這個(gè)中斷.寫數(shù)據(jù)到芯片的這個(gè)過程是在什么地方完成的呢?
是在中斷處理中.如果是發(fā)送空的中斷,就將circ buffer中的數(shù)據(jù)寫出發(fā)送寄存器.跟蹤一下代碼.中斷處理函數(shù)為serial8250_interrupt().
static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
{
     struct irq_info *i = dev_id;
     struct list_head *l, *end = NULL;
     int pass_counter = 0, handled = 0;

     DEBUG_INTR("serial8250_interrupt(%d)...", irq);

     spin_lock(&i->lock);

     l = i->head;
     do {
         struct uart_8250_port *up;
         unsigned int iir;

         up = list_entry(l, struct uart_8250_port, list);

         iir = serial_in(up, UART_IIR);
         if (!(iir & UART_IIR_NO_INT)) {
              serial8250_handle_port(up);

              handled = 1;

              end = NULL;
         } else if (up->port.iotype == UPIO_DWAPB &&
                (iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
              /* The DesignWare APB UART has an Busy Detect (0x07)
               * interrupt meaning an LCR write attempt occured while the
               * UART was busy. The interrupt must be cleared by reading
               * the UART status register (USR) and the LCR re-written. */
              unsigned int status;
              status = *(volatile u32 *)up->port.private_data;
              serial_out(up, UART_LCR, up->lcr);

              handled = 1;

              end = NULL;
         } else if (end == NULL)
              end = l;

         l = l->next;

         if (l == i->head && pass_counter++ > PASS_LIMIT) {
              /* If we hit this, we're dead. */
              printk(KERN_ERR "serial8250: too much work for "
                   "irq%d\n", irq);
              break;
         }
     } while (l != end);

     spin_unlock(&i->lock);

     DEBUG_INTR("end.\n");

     return IRQ_RETVAL(handled);
}
這里可能有個(gè)疑問的地方,掛在這個(gè)鏈表上的到底是什么.這我們要從serial_link_irq_chain()來說起.該函數(shù)代碼如下:
static int serial_link_irq_chain(struct uart_8250_port *up)
{
     struct irq_info *i = irq_lists + up->port.irq;
     int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;

     spin_lock_irq(&i->lock);

     if (i->head) {
         list_add(&up->list, i->head);
         spin_unlock_irq(&i->lock);

         ret = 0;
     } else {
         INIT_LIST_HEAD(&up->list);
         i->head = &up->list;
         spin_unlock_irq(&i->lock);

         ret = request_irq(up->port.irq, serial8250_interrupt,
                     irq_flags, "serial", i);
         if (ret  0)
              serial_do_unlink(i, up);
     }

     return ret;
}
從這里看到,注冊中斷處理函數(shù)的參數(shù)i就是對應(yīng)irq_lists + up->port.irq.即對應(yīng)在irq_lists數(shù)組中的port->irq項(xiàng).隨后,將注冊的uart_8250_port添加到了這個(gè)鏈表.
奇怪了,為什么要這么做了?我們返回old_serial_port的定義看看:
static const struct old_serial_port old_serial_port[] = {
     SERIAL_PORT_DFNS /* defined in asm/serial.h */
};
#define SERIAL_PORT_DFNS            
     /* UART CLK   PORT IRQ     FLAGS        */            
     { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS },     /* ttyS0 */  
     { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS },     /* ttyS1 */  
     { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS },     /* ttyS2 */  
     { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS },    /* ttyS3 */
在這里,注意到同一個(gè)IRQ號會對應(yīng)兩個(gè)port.
IRQ中發(fā)生中斷的時(shí)候,怎么去判斷是哪一個(gè)port所引起的.當(dāng)然方法有多種多樣.在這里,8250驅(qū)動的作者是將不同的port鏈入到IRQ對應(yīng)的鏈
表來完成的.這樣,如果IRQ產(chǎn)生了中斷了,就判斷掛在該鏈表中的port,看中斷是否由它產(chǎn)生.
  
經(jīng)過這個(gè)分析之后,我們應(yīng)該很清楚serial8250_interrupt()中的處理流程了.對應(yīng)產(chǎn)生IRQ的port,流程會轉(zhuǎn)入serial8250_handle_port()中.代碼如下:
static inline void
serial8250_handle_port(struct uart_8250_port *up)
{
     unsigned int status;
     unsigned long flags;

     spin_lock_irqsave(&up->port.lock, flags);

     status = serial_inp(up, UART_LSR);

     DEBUG_INTR("status = %x...", status);

     if (status & UART_LSR_DR)
         receive_chars(up, &status);
     check_modem_status(up);
     if (status & UART_LSR_THRE)
         transmit_chars(up);

     spin_unlock_irqrestore(&up->port.lock, flags);
}
對于產(chǎn)生中斷的情況下,判斷發(fā)送緩存區(qū)是否為空,如果為空,就可以發(fā)送數(shù)據(jù)了.對應(yīng)的處理在transmit_chars(up).如果接收緩存區(qū)滿,就那接收數(shù)據(jù),這是在receive_chars()中處理的.對于接收數(shù)據(jù),我們在下一節(jié)再分析.
transmit_chars()代碼如下: static void transmit_chars(struct uart_8250_port *up)
{
     struct circ_buf *xmit = &up->port.info->xmit;
     int count;

     if (up->port.x_char) {
         serial_outp(up, UART_TX, up->port.x_char);
         up->port.icount.tx++;
         up->port.x_char = 0;
         return;
     }
     if (uart_tx_stopped(&up->port)) {
         serial8250_stop_tx(&up->port);
         return;
     }
     if (uart_circ_empty(xmit)) {
         __stop_tx(up);
         return;
     }

     count = up->tx_loadsz;
     do {
         serial_out(up, UART_TX, xmit->buf[xmit->tail]);
         xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
         up->port.icount.tx++;
         if (uart_circ_empty(xmit))
              break;
     } while (--count > 0);

     if (uart_circ_chars_pending(xmit)  WAKEUP_CHARS)
         uart_write_wakeup(&up->port);

     DEBUG_INTR("THRE...");

     if (uart_circ_empty(xmit))
         __stop_tx(up);
}
從上面的代碼看出.會從xmit中取出數(shù)據(jù),然后將其寫入到發(fā)送寄存器中.特別的,在8250芯片的情況下, up->tx_loadsz等于1.也就是說,一次只能傳送1個(gè)字節(jié).
如果緩存區(qū)的數(shù)據(jù)傳輸玩了之后,就會調(diào)用__stop_tx().代碼如下: static inline void __stop_tx(struct uart_8250_port *p)
{
     if (p->ier & UART_IER_THRI) {
         p->ier &= ~UART_IER_THRI;
         serial_out(p, UART_IER, p->ier);
     }
}
對應(yīng)的,在IER中,將發(fā)送緩存區(qū)空的中斷關(guān)掉.
  
六:數(shù)據(jù)讀取操作
在前面的tty驅(qū)動架構(gòu)分析中,曾說過,在
tty_driver中并末提供read接口.上層的read操作是直接到ldsic的緩存區(qū)中讀數(shù)據(jù)的.那ldsic的數(shù)據(jù)是怎么送入進(jìn)去的呢?繼續(xù)看
中斷處理中的數(shù)據(jù)接收流程.即為: receive_chars().代碼片段如下:
tatic void
receive_chars(struct uart_8250_port *up, unsigned int *status)
{
     ……
     ……
     uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);
}
最后流據(jù)會轉(zhuǎn)入uart_inset_char().這個(gè)函數(shù)是uart層提供的一個(gè)接口,代碼如下:
static inline void
uart_insert_char(struct uart_port *port, unsigned int status,
          unsigned int overrun, unsigned int ch, unsigned int flag)
{
     struct tty_struct *tty = port->info->tty;

     if ((status & port->ignore_status_mask & ~overrun) == 0)
         tty_insert_flip_char(tty, ch, flag);

     /*
      * Overrun is special.  Since it's reported immediately,
      * it doesn't affect the current character.
      */
     if (status & ~port->ignore_status_mask & overrun)
         tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
Tty_insert_filp()函數(shù)的代碼我們在之前已經(jīng)分析過,這里不再贅述.就這樣,數(shù)據(jù)就直接交給了ldisc.
  
七:輪詢操作
在前面已經(jīng)分析到,如果沒有定義irq或者沒有控測到irq號,就會采用輪詢.在代碼,采用定時(shí)器的方式.去判斷是否有數(shù)據(jù)到來,或者將數(shù)據(jù)寫入8250.定時(shí)器對應(yīng)的運(yùn)行函數(shù)為serial8250_backup_timeout().代碼如下:
static void serial8250_backup_timeout(unsigned long data)
{
     struct uart_8250_port *up = (struct uart_8250_port *)data;
     unsigned int iir, ier = 0, lsr;
     unsigned long flags;

     /*
      * Must disable interrupts or else we risk racing with the interrupt
      * based handler.
      */
     if (is_real_interrupt(up->port.irq)) {
         ier = serial_in(up, UART_IER);
         serial_out(up, UART_IER, 0);
     }

     iir = serial_in(up, UART_IIR);

     /*
      * This should be a safe test for anyone who doesn't trust the
      * IIR bits on their UART, but it's specifically designed for
      * the "Diva" UART used on the management processor on many HP
      * ia64 and parisc boxes.
      */
     spin_lock_irqsave(&up->port.lock, flags);
     lsr = serial_in(up, UART_LSR);
     up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
     spin_unlock_irqrestore(&up->port.lock, flags);
     if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) &&
         (!uart_circ_empty(&up->port.info->xmit) || up->port.x_char) &&
         (lsr & UART_LSR_THRE)) {
         iir &= ~(UART_IIR_ID | UART_IIR_NO_INT);
         iir |= UART_IIR_THRI;
     }

     if (!(iir & UART_IIR_NO_INT))
         serial8250_handle_port(up);

     if (is_real_interrupt(up->port.irq))
         serial_out(up, UART_IER, ier);

     /* Standard timer interval plus 0.2s to keep the port running */
     mod_timer(&up->timer,
         jiffies + poll_timeout(up->port.timeout) + HZ / 5);
}
如果IRQ線有效,先在IER中禁用全部中斷.等定時(shí)器處理函數(shù)處理完后,再恢復(fù)IER中的內(nèi)容.這樣主要是為了防止會產(chǎn)生發(fā)送緩存區(qū)空的中斷.
流程最后還是會轉(zhuǎn)入到serial8250_handle_port()中.這個(gè)函數(shù)我們在上面已經(jīng)分析過了.
  
八:小結(jié)
分析完了這個(gè)驅(qū)動,我們可以看到.專業(yè)的開發(fā)人員思維是多么的縝密.真是滴水不漏.該代碼里有很多非常精彩的處理,需要細(xì)細(xì)揣摩.


本文來自ChinaUnix博客,如果查看原文請點(diǎn):http://blog.chinaunix.net/u3/92500/showart_2159909.html
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報(bào)專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP