📄 tl16c750.c
字号:
{
#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 + -