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

📄 tl16c750.c

📁 此程序为串口芯片tl16c750在uClinux + s3c44b0环境下的驱动程序.tl16c750R FIFO设置为64BYTES, 除此之外,此程序还能缓存20条已经收到的串口数据.即存储数据量
💻 C
📖 第 1 页 / 共 2 页
字号:
    {
#ifdef DEBUG
        printk("we will send msg directly\n");
        printk("coping msg from user... ...");
#endif
        copy_from_user( txMsg,  buf , count ) ;
#ifdef DEBUG
        printk("done\n");
        printk("%u chars copied!\n", count );
        printk("writing tl16c760 THR\n");
#endif
        for ( i = 0 ; i <count ; i ++ )
        {
            TL16C750_FIFO = txMsg[i];
#ifdef  DEBUG
            printk("0x%x ", txMsg[ i ]);
#endif
        }
#ifdef  DEBUG
            printk("done\n");
#endif
        enable_tl16c750_thre_int( );        /*enable THRE interrup of tl16c750*/
    }
    else
    {
        if( query_queue_full( &txQueue ) != 1 )
        {
#ifdef DEBUG
            printk("the transimitter is busy!\n we will write msg into txQueue!\n");
            printk("coping msg from user... ...");
#endif
            copy_from_user( txMsg,  buf , count ) ;
#ifdef DEBUG
            printk("done\n");
            printk("writing msg into txQueue\n");
#endif

            for( i = 0 ; i < count ; i ++ )
        	{
                txQueue.data[ txQueue.rear ][ i ] == txMsg[ i ];
#ifdef DEBUG
                printk("0x%x ", txQueue.data[ txQueue.rear ][ i ]);
#endif
        	}

#ifdef DEBUG
            printk("\n");
#endif          
            txQueue.len[ txQueue.rear ] = count ;
#ifdef DEBUG
            printk("txQueue.len[ %u ] = %u\n", txQueue.rear ,count );
            printk("in txQueue... ... ");
#endif

            in_queue( &txQueue );               /*maintanence of  the rxQueue*/
#ifdef DEBUG
            printk("done\n");
            printk("txQueue.front = %u, txQueue.rear = %u",txQueue.front, txQueue.rear);
#endif
        }
        else
        {
            count = 0;  
        }
    
    }
        
    enable_irq( IRQ_TL16C750 );     /*enable tl16c750 interrupt on ARM*/    

    printk("exit write!\n\n");
    
    return count;
}


/*=====================================================
Description:    1.register chrdev and IRQ.
            2.configure the tl16c750.
Returns:    0--OK       	
======================================================*/    
static int tl16c750_open(struct inode *inode, struct file *filp)
{
    int ret = 0 ;
    
    if ((ret = request_irq( IRQ_TL16C750, tl16c750_handler, SA_INTERRUPT, 
                        TL16C750_NAME, dev_idkp)))
    {
        printk("tl16c750 interrrupt: failed to register IRQ\n");
        
        free_irq(IRQ_TL16C750, dev_idkp);
        
        return ret;
    }

#ifdef DEBUG
    printk("Successful to open TL16C750!\n");
#endif

    disable_irq(IRQ_TL16C750);          /*disable tl16c750 interrupt on ARM */

    lstCmdReqSN = -1 ;
    lstStsRepSN = 63 ;

    reset_queue( &rxQueue );        /*to initialze rxQueue*/
    reset_queue( &txQueue );            /*to initialze rxQueue*/

    config_tl16c750();              /*to initialize tl6c750*/

    enable_irq(IRQ_TL16C750);           /*enable tl16c750 interrupt on ARM*/
    
    MOD_INC_USE_COUNT;  	

    return 0;
}


/*=====================================================
Description:   close a device.
Returns:    0--OK       	
======================================================*/    
static int tl16c750_release(struct inode *inode, struct file *filp)
{
    free_irq(IRQ_TL16C750, dev_idkp);
    
    reset_queue( &rxQueue); 
    reset_queue( &txQueue);

    MOD_DEC_USE_COUNT;  

#ifdef DEBUG
    printk("Successful to close TL16C750!\n");
#endif  
    return 0;
}


/*=====================================================
Description:   1.disable all the interrupt of tl16c750.
            2.according to the value of IIR, we can get the source of 
            interrupt.
            3.there are only three types of interrupt that we used here: 
            char time out, receiver line status and transmitter holding 
            register empty.
Returns:    0--OK       
            <0--Faiure.
======================================================*/    
static void tl16c750_handler(int irq, void *dev_idkp, struct pt_regs *regs)
{
    unsigned char   iir_val = 0 ;                   /*IIR's value*/

    unsigned char   i = 0 ;

    
    disable_irq(IRQ_TL16C750);                  /*disable tl16c750 interrupt on ARM*/

    iir_val = TL16C750_IIR; /*get IIR*/

    printk("enter tl16c750 interrupt!\n");

    printk("IIR = 0x%x\n", iir_val);    

    switch( iir_val & 0x0f )
    {
        case IIR_RDA_INT:   /*receiver data available*/

            /*excute the same actinon as IIR_CTOI_INT*/
        	
        case IIR_CTOI_INT :     /*char time out indicater*/
            printk("char time out interrupt!\n");
            if ( query_queue_full( &rxQueue ) == 0) 
            {			
                i = 0;

#ifdef DEBUG        	
                printk("reading msg from tl16c750 receive FIFO......\n");
#endif  
        
                while ( ( TL16C750_LSR & LSR_DATA_READY ) == 1 )
            	{
                    rxQueue.data[ rxQueue.rear ][ i ] = TL16C750_FIFO;
#ifdef DEBUG        	
                    printk("0x%x ",rxQueue.data[ rxQueue.rear ][ i ]);
#endif
                    i ++ ;
            	}
#ifdef DEBUG        		
                printk("done\n");
#endif      
        
                rxQueue.len[ rxQueue.rear ] = i ;
#ifdef DEBUG        	
                printk("rxQueue.len[ %u ] = %u\n",  rxQueue.rear , rxQueue.len[ rxQueue.rear ]);
                printk("in rxQueue... ...");
#endif  

                in_queue( &rxQueue );   
#ifdef DEBUG        	
                printk("done!\n");
#endif  
        	}
            else
        	{
#ifdef DEBUG        	
                printk("rxQueue is full\n");
#endif
            }		
            break;
        case IIR_RLS_INT:   /*receiver line status*/
                            /*Overrun error, parity error,framing error or break interrupt*/
                            /*so we do not need to return this status to ARM*/
                            /*deal with it right now!*/
            TL16C750_LCR = TL16C750_LCR | LCR_DLAB  ;   /* DLAB = 1 */
            TL16C750_FCR = FCR_64_BYTE_MODE | FCR_56_TRIGGER_LEVEL_64 | FCR_FIFO_ENALBE| FCR_CLR_RX_FIFO |FCR_CLR_TX_FIFO ;     		
                			
            printk("line status interrupt!\n");
                			
            break;
        case IIR_THRE_INT:  /*transmitter holding register empty*/
        	
            printk("thre interrupt!\n");

            if (query_queue_empty( &txQueue ) != 1)
        	{
#ifdef DEBUG        	
                printk("txQueue is not empty\n");
#endif
                for ( i = 0 ; i < txQueue.len[ txQueue.front ] ; i ++ )
            	{
                    TL16C750_FIFO = txQueue.data[ txQueue.front][ i ];
#ifdef DEBUG        	
                    printk("0x%x ",  txQueue.data[ txQueue.front][ i ]);
#endif
            	}

#ifdef DEBUG        	
                printk("done \n");
                printk("out txQueue... ...");
#endif          	
                out_queue( &txQueue );
#ifdef DEBUG        	
                printk("done \n");
                printk("txQueue.front = %u, txQueue.rear = %u\n", txQueue.front , txQueue.rear );
#endif
        	}
            else
        	{
#ifdef DEBUG        	
                printk("txQueue is empty, so we disable THRE.\n");
#endif
                disable_tl16c750_thre_int();    /*disable THRE interrupt*/
            }			

            break;
        default:
            break;
    }

    enable_irq(IRQ_TL16C750);                   /*enable tl16c750 interrupt on ARM*/
    
    printk("exit tl16c750 interrupt!\n\n"); 
}


/*=====================================================
 Description:   init this module.
Returns:    0--OK       
            <0--Faiure.
======================================================*/    
int __init tl16c750_init(void)
{
    int ret = 0 ;

    /*register the char device*/
    if ((ret=register_chrdev(TL16C750_MAJOR, TL16C750_NAME, &tl16c750_fops))!=0)
    {
        printk("Failed to register "TL16C750_NAME "\n");    
        return ret;
    }

#ifdef DEBUG        
    printk("TL16C750 driver initialized\n");
#endif

    return 0;
}


/*=====================================================
 Description:   1.cleanup the module.
            2.remove the registered irq and chrdev.
Returns:    0--OK       
            <0--Faiure.
======================================================*/    
void __exit tl16c750_cleanup(void)
{

    //free_irq(IRQ_TL16C750, dev_idkp); 

    unregister_chrdev(TL16C750_MAJOR, TL16C750_NAME);   
    
#ifdef DEBUG
    printk("TL16C750 has been removed\n");
#endif

}

module_init(tl16c750_init); 
module_exit(tl16c750_cleanup);

EXPORT_NO_SYMBOLS;

MODULE_DESCRIPTION("The driver for TL16C750");
MODULE_SUPPORTED_DEVICE("uClinux 2.4.x Digital Jet Printer Machine");
MODULE_AUTHOR("Zhang Dahai");
MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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