www.pudn.com > 422.rar > irq.c
/* irq.c * Linux serial-bus device driver. * Written by wang song yue--bupt email:wsy5228@sina.com * This software is released under the GPL-License. * Version 0.1 28 october 2005 */ #include#if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS) #define MODVERSIONS #endif #if defined (MODVERSIONS) #include #endif #include #include #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,2,19)) #include #else #include #endif #include "../include/main.h" #include "../include/irq.h" #include "../include/s16c554.h" void s16c554_irq_read_handler(void); void s16c554_irq_write_handler(void); void (*put_reg)(unsigned char data, unsigned long address); unsigned (*get_reg)(unsigned long address); struct chip_t *chip=NULL; struct candevice_t *device=NULL; unsigned object=0,irq_register=0; unsigned long msgbase=0; struct canfifo_t *fifo=NULL; //unsigned long message_id=0; //struct rtr_id *rtr_search; void s16c554_irq_handler(int irq, void *dev_id, struct pt_regs *regs) { printk("i am in s16c554_irq_handler now!\n"); chip=(struct chip_t *)dev_id; device=(struct candevice_t *)chip->hostdevice; put_reg=device->hwspecops->write_register; get_reg=device->hwspecops->read_register; irq_register=get_reg(ISR); // DEBUGMSG("sja1000_irq_handler: SJAIR:%02x\n",irq_register); // DEBUGMSG("sja1000_irq_handler: SJASR:%02x\n", // get_reg(chip->chip_base_addr+SJASR)); if (irq_register & (0x01)) //there is no any interrupt! return; fifo=chip->msgobj[0]->fifo; msgbase=chip->msgobj[0]->obj_base_addr; if (irq_register & (0x04)) //there is read interrupt! s16c554_irq_read_handler(); if (irq_register & (0x02)) //there is write interrupt s16c554_irq_write_handler(); if ((irq_register & (0x06)) != 0) { //there is error intrupt! // Some error happened // FIXME: chip should be brought to usable state. Transmission cancelled if in progress. // Reset flag set to 0 if chip is already off the bus. Full state report // CANMSG("Error: status register: 0x%x irq_register: 0x%02x\n", // get_reg(SJASR), irq_register); chip->msgobj[0]->ret=-1; if (waitqueue_active(&fifo->writeq)) wake_up_interruptible(&fifo->writeq); if (waitqueue_active(&fifo->readq)) wake_up_interruptible(&fifo->readq); } return; } void s16c554_irq_read_handler(void) { int i=0, tmp=1; printk("i am in s16c554_irq_read_handler!!\n"); while (tmp) { fifo->head=0; fifo->buf_rx_entry[fifo->head].data[i] = get_reg(RHR); fifo->buf_rx_entry[fifo->head].length++; i++; fifo->head++; tmp=(get_reg(LSR) & (0x01))&&(i<64); } if (waitqueue_active(&fifo->readq)) wake_up_interruptible(&fifo->readq); } void s16c554_irq_write_handler(void) { fifo->tx_readp++; if (fifo->tx_readp >= fifo->buf_tx_entry + MAX_BUF_LENGTH) fifo->tx_readp = fifo->buf_tx_entry; if (fifo->tx_readp == fifo->tx_writep) { // Output buffer is empty fifo->tx_in_progress = 0; if (waitqueue_active(&fifo->writeq)) { chip->msgobj[object]->ret = 0; wake_up_interruptible(&fifo->writeq); } return; } if (chip->chipspecops->pre_write_config(chip, chip->msgobj[object], fifo->tx_readp)) { if (waitqueue_active(&fifo->writeq)) { chip->msgobj[object]->ret = -1; wake_up_interruptible(&fifo->writeq); return; } } }