📄 at2041_inf.~c
字号:
if (mux_full) { /* acknowledge for data ready message */ *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x8803; mux_full = 0; } return 0;}static ssize_t demuxfifo_write(struct file *file,const char *buffer, size_t length, loff_t * offset){ down(&demuxfifo_write_sem); copy_from_user(demux_buf[demux_wr_cnt], buffer, length); demux_size_buf[demux_wr_cnt] = length; /* de-multiplex ring buffer control */ if (!demux_ring_cnt) { demux_wr_cnt ++; if (demux_wr_cnt == MAX_BUF_NUM) { demux_ring_cnt ++; demux_wr_cnt = 0; } } else if (demux_ring_cnt && demux_wr_cnt < demux_rd_cnt) { demux_wr_cnt ++; } return 0;}static int at2041_open(struct inode* inode, struct file* filp){ printk("the AT2041 Open!!!\n"); MOD_INC_USE_COUNT; return 0;}static int at2041_release(struct inode* inode, struct file* filp){ printk("the AT2041 Release!!!\n"); MOD_DEC_USE_COUNT; return 0;}/* the AT2041 file operations */static struct file_operations at2041_fops = { read: muxfifo_read, write: demuxfifo_write, ioctl: at2041_ioctl, open: at2041_open, release: at2041_release,};static void at2041_interrupt_handle(int irq, void *dev_id, struct pt_regs * regs){ unsigned short tx_data; unsigned short temp; unsigned int data_size = 0; //printk("now at2042 interrupt handle\n"); /* data read from Tx_FIFO of the AT2041 */ tx_data = *((unsigned short *)((unsigned int)pt + AT2041_TX_FIFO_ADDR)); udelay(10);//printk("read_rx_id= 0x%x\n", tx_data); /* check whether first tx message is 'data ready message' * or 'data request message' */ if ((tx_data & 0x0001) == 0x0000){ // read data from tx_fifo udelay(10); /* check tx fifo empty */ if ( !(*((unsigned short *)((unsigned int)pt + AT2041_STATUS_REG_ADDR)) & 0x100) ) { // read DATA /* data read from Tx_FIFO of the AT2041 */ tx_data = *((unsigned short *)((unsigned int)pt + AT2041_TX_FIFO_ADDR));//printk("read_reg_data= 0x%x\n", tx_data); } /* TxACK command */ *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x8003; } else if (tx_data == 0x8803) { // read message from tx_fifo : data ready message(Encoder) /* if first tx message is 'data ready message', * read three tx message sequentially. * the contents of second tx_message are 'data type', 'channel ID', * 'skip', 'loss' and 'output buffer full', etc. */ /* check tx fifo empty */ if ( !(*((unsigned short *)((unsigned int)pt + AT2041_STATUS_REG_ADDR)) & 0x100) ) { /* read the second parameter of Tx_FIFO */ mux_buf[mux_wr_cnt][0] = *((unsigned short *)((unsigned int)pt + AT2041_TX_FIFO_ADDR)); } else { printk("[saa7146] It can't read tx0 register\n"); /* TxACK command */ *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x8003; } if ( !(*((unsigned short *)((unsigned int)pt + AT2041_STATUS_REG_ADDR)) & 0x100) ) { /* read the third parameter of Tx_FIFO */ /* the contents of the third tx_message are 'output data size' */ mux_buf[mux_wr_cnt][1] = *((unsigned short *)((unsigned int)pt + AT2041_TX_FIFO_ADDR)); } else { printk("[saa7146] It can't read tx1 register\n"); /* TxACK command */ *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x8003; } if ( !(*((unsigned short *)((unsigned int)pt + AT2041_STATUS_REG_ADDR)) & 0x100) ) { /* read the fourth parameter of Tx_FIFO */ /* the contents of the fourth tx_message are 'reserved' */ mux_buf[mux_wr_cnt][2] = *((unsigned short *)((unsigned int)pt + AT2041_TX_FIFO_ADDR)); } else { printk("[saa7146] It can't read tx2 register\n"); } /* calculate data size to transfer */ *size_buf[mux_wr_cnt] = mux_buf[mux_wr_cnt][1]; data_size = ((*size_buf[mux_wr_cnt] & 0xffff) << 4) + enc_txmsg_size; /* data read from multiplex FIFO of the AT2041 */ /* write multiplex data from the AT2041 to d/d's buffer */ for (ii = enc_txmsg_size; ii < data_size; ii ++) { mux_buf[mux_wr_cnt][ii] = *((unsigned short *)((unsigned int)pt + AT2041_MUX_FIFO_ADDR)); } up(&muxfifo_read_sem); /* multiplex ring buffer control */ if (!mux_ring_cnt) { mux_wr_cnt ++; if (mux_wr_cnt == MAX_BUF_NUM) { mux_ring_cnt ++; mux_wr_cnt = 0; } } else if (mux_ring_cnt && mux_wr_cnt < mux_rd_cnt) { mux_wr_cnt ++; } else { printk("!!![MUX][%02d][%02d][%02d]\n", mux_wr_cnt, mux_rd_cnt, mux_ring_cnt); } /* TxACK command */ *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x8003; if (mux_ring_cnt && mux_wr_cnt == mux_rd_cnt) { mux_full = 1; printk("!!!!!!!! MUX FULL !!!!!!!!!\n"); } else { /* acknowledge for data ready message */ *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x8803; }/* TxACK command */ *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x8003; /* acknowledge for data ready message */ *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x8803; } /* data write to de-multiplex FIFO of the AT2041 */ else if (tx_data == 0x9003) { // read message from txfifo : data request(Decoding) if (!demux_ring_cnt && (demux_wr_cnt == demux_rd_cnt)) { /* check tx fifo empty */ if (!(*((unsigned short *)((unsigned int)pt + AT2041_STATUS_REG_ADDR)) & 0x100)) { /* txfifo ring buffer control */ temp = *((unsigned short *)((unsigned int)pt + AT2041_TX_FIFO_ADDR)); } else { printk("[saa7146] It can't read tx0 register\n"); /* TxACK command */ *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x8003; } /* TxACK command */ *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x8003; /* acknowledge for data request message */ *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x9003; return; } /* check tx fifo empty */ if (!(*((unsigned short *)((unsigned int)pt + AT2041_STATUS_REG_ADDR)) & 0x100)) { /* txfifo ring buffer control */ temp = *((unsigned short *)((unsigned int)pt + AT2041_TX_FIFO_ADDR)); } else { printk("[saa7146] It can't read tx0 register\n"); *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x8003; } /* write de-multiplex data from d/d's buffer to the AT2041 */ for (ii = 0; ii < (demux_size_buf[demux_rd_cnt] + 256) / 2; ii ++) { if ((ii == 0) && (demux_buf[demux_rd_cnt][ii] != 0x0000)) printk("data[%d] header error\n", ii); else if ((ii == 1) && (demux_buf[demux_rd_cnt][ii] != 0x01e0)) printk("data[%d] header error\n", ii); *((unsigned short *)((unsigned int)pt + AT2041_DEMUX_FIFO_ADDR)) = demux_buf[demux_rd_cnt][ii]; } /* de-multiplex ring buffer control */ if (!demux_ring_cnt && demux_rd_cnt <= demux_wr_cnt) { demux_rd_cnt ++; if (demux_rd_cnt == MAX_BUF_NUM) { demux_ring_cnt --; demux_rd_cnt = 0; } } else if (demux_ring_cnt) { demux_rd_cnt ++; if (demux_rd_cnt == MAX_BUF_NUM) { demux_ring_cnt --; demux_rd_cnt = 0; } } up(&demuxfifo_write_sem); /* TxACK command */ *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x8003; /* acknowledge for data request message */ *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x9003; } else { /* TxACK command */ *((unsigned short *)((unsigned int)pt + AT2041_RX_FIFO_ADDR)) = 0x8003; }}int at2041_init_module(void){ int ret, kk; (unsigned short *)pt = (unsigned short *)ioremap(AT2042_BASE, AT2042_REMAP_SIZE); printk("init_at2042 0x%p ==> 0x%x\n", pt, (unsigned int)pt+AT2042_REMAP_SIZE); ret = register_chrdev(AT2041_MAJOR, "at2041", &at2041_fops); init_MUTEX_LOCKED(&muxfifo_read_sem); sema_init(&demuxfifo_write_sem, MAX_BUF_NUM); if (ret < 0) { printk("at2042: at2042 register failed\n"); return ret; } /* mux_buf & demux_buf allocation */ for (kk = 0; kk < MAX_BUF_NUM; kk ++){ if (!(mux_buf[kk] = (unsigned short *) kmalloc(MAX_BUF_SIZE + (enc_txmsg_size << 1), GFP_KERNEL))) { printk("AT2041 : mux_buf kmalloc failed...\n"); return -ENOMEM; } if (!(demux_buf[kk] = (unsigned short *) kmalloc(MAX_BUF_SIZE, GFP_KERNEL))) { printk("AT2041 : demux_buf kmalloc failed...\n"); return -ENOMEM; } if (!(size_buf[kk] = (unsigned short *) vmalloc(sizeof(unsigned short)))) { printk("AT2041 : size_buf kmalloc failed...\n"); return -ENOMEM; } } printk("the AT2041 driver initialized...\n");#if 0 /* Enable interrupts for EINT0/GPF0 */ /*HJT*/ printk ("__INTERRUPT_AVAILABLE__\n"); /*HJT*/ //(volatile unsigned long) (rINTMSK) &= ~0x00000001; //Intservice MASK ==> AVAILABLE /*HJT*/ (volatile unsigned long) (rINTMSK) &= ~0x00000004; //Intservice MASK ==> AVAILABLE /*HJT*/ #endif /* AT2041_IRQ = 25, Fast interrupt, No interrupt sharing */ //printk ("0x%x : 0x%x\n", SA_INTERRUPT, SA_SHIRQ); if(request_irq(IRQ_EINT2, at2041_interrupt_handle, SA_INTERRUPT, "at2042", NULL)) //if(request_irq(IRQ_EINT2, at2041_interrupt_handle, SA_SHIRQ, "at2042", NULL)) //if(request_irq(IRQ_EINT2, at2041_interrupt_handle, 0, "at2042", NULL)) { printk("at2042 : cannot register IRQ %d\n", IRQ_EINT2); return -EIO; } printk("at2042 : register IRQ %d\n", IRQ_EINT2); return 0;}void at2041_cleanup_module(void){ volatile int ret; free_irq(IRQ_EINT2, NULL); ret = unregister_chrdev(AT2041_MAJOR, "at2042"); if (ret < 0) { printk("at2042: at2042 unregister failed\n"); return; } for (ii = 0; ii < MAX_BUF_NUM; ii ++) { kfree(mux_buf[ii]); kfree(demux_buf[ii]); vfree(size_buf[ii]); } ret = unregister_chrdev(AT2041_MAJOR, "at2042"); if (ret < 0) { printk("at2042: at2042 unregister failed\n"); return; } printk("at2042: at2042 unloaded\n"); iounmap((void *)pt); return;}module_init(at2041_init_module);module_exit(at2041_cleanup_module);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -