/** * * \brief int open(const char *pathname, int flags); * opens the CAN device for following operations * \param pathname device pathname, usual /dev/can? * \param flags is one of \c O_RDONLY, \c O_WRONLY or \c O_RDWR which request * opening the file read-only, write-only or read/write, * respectively. * * * The open call is used to "open" the device. * Doing a first initialization according the to values in the /proc/sys/Can * file system. * Additional an ISR function is assigned to the IRQ. * * The CLK OUT pin is configured for creating the same frequency * like the chips input frequency fclk (XTAL). * * If Vendor Option \a VendOpt is set to 's' the driver performs * an hardware reset befor initializing the chip. * * \returns * open return the new file descriptor, * or -1 if an error occurred (in which case, errno is set appropriately). * * \par ERRORS * the following errors can occur * \arg \c ENXIO the file is a device special file * and no corresponding device exists. * \arg \c EINVAL illegal \b minor device number * \arg \c EINVAL wrong IO-model format in /proc/sys/Can/IOmodel * \arg \c EBUSY IRQ for hardware is not available * \arg \c EBUSY I/O region for hardware is not available */ int can_open( __LDDK_OPEN_PARAM ) { int retval = 0; DBGin("can_open"); { int lasterr; unsigned int minor = iminor(inode); if( minor > MAX_CHANNELS ) { printk(KERN_ERR "CAN: Illegal minor number %d\n", minor); DBGout(); return -EINVAL; } /* check if device is already open, should be used only by one process */ if(Can_isopen[minor] == 1) { DBGout(); return -ENXIO; } if( Base[minor] == 0x00) { /* No device available */ printk(KERN_ERR "CAN[%d]: no device available\n", minor); DBGout(); return -ENXIO; } /* the following does all the board specific things also memory remapping if necessary */ if( (lasterr = CAN_VendorInit(minor)) < 0 ){ DBGout(); return lasterr; } /* Access macros based in can_base[] should work now */ /* CAN_ShowStat(minor); */ /* controller_available(curr + 0x400, 4); */ Can_WaitInit(minor); /* initialize wait queue for select() */ Can_FifoInit(minor); #if CAN_USE_FILTER Can_FilterInit(minor); #endif if( CAN_ChipReset(minor) < 0 ) { DBGout(); return -EINVAL; } CAN_StartChip(minor); #if DEBUG CAN_ShowStat(minor); #endif ++Can_isopen[minor]; /* flag device in use */ } DBGout(); return retval; }
int can_select( __LDDK_SELECT_PARAM ) #endif { unsigned int minor = __LDDK_MINOR; msg_fifo_t *RxFifo = &Rx_Buf[minor]; DBGin("can_select"); DBGprint(DBG_DATA,("minor = %d", minor)); #if 0 DBGprint(DBG_DATA,("file = %p", file)); ; DBGprint(DBG_DATA,("s(CanWait[]) = %2d", sizeof(CanWait[0]))); ; /* DBGprint(DBG_DATA,("s(CanWait) = %2d", sizeof(CanWait))); */ ; DBGprint(DBG_DATA,("&CanWait[] = %p", &CanWait[0])); DBGprint(DBG_DATA,("CanWait[minor].task_list.n = %p", CanWait[minor].task_list.next)); DBGprint(DBG_DATA,("CanWait[minor].task_list.p = %p", CanWait[minor].task_list.prev)); DBGprint(DBG_DATA,("&CanWait[minor]->task_list.p = %p", (&CanWait[minor])->task_list.prev)); DBGprint(DBG_DATA,("wait = %p", wait)); if(wait) { DBGprint(DBG_DATA,("wait->error = %d", wait->error)); DBGprint(DBG_DATA,("wait->table = %p", wait->table)); } else { DBGprint(DBG_DATA,("can not dereference wait components")); } #endif #ifdef DEBUG CAN_ShowStat(minor); #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) DBGprint(DBG_BRANCH,("POLL: fifo empty,poll waiting...\n")); /* every event queue that could wake up the process * and change the status of the poll operation * can be added to the poll_table structure by * calling the function poll_wait: */ /* _select para, wait queue, _select para */ /* X */ poll_wait(file, &CanWait[minor] , wait); DBGprint(DBG_BRANCH,("POLL: wait returned \n")); if( RxFifo->head != RxFifo->tail ) { /* fifo has some telegrams */ /* Return a bit mask * describing operations that could be immediately performed * without blocking. */ DBGout(); /* * POLLIN This bit must be set * if the device can be read without blocking. * POLLRDNORM This bit must be set * if "normal'' data is available for reading. * A readable device returns (POLLIN | POLLRDNORM) * * * */ return POLLIN | POLLRDNORM; } DBGout();return 0; #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,3) DBGprint(DBG_BRANCH,("POLL: fifo empty,poll waiting...\n")); poll_wait(file, &CanWait[minor] , wait); DBGprint(DBG_BRANCH,("POLL: wait returned \n")); if( RxFifo->head != RxFifo->tail ) { /* fifo has some telegrams */ DBGout(); return POLLIN | POLLRDNORM; } DBGout();return 0; #else switch (sel_type) { case SEL_IN: DBGprint(DBG_BRANCH,("sel_in \n")); if( RxFifo->head == RxFifo->tail ) { DBGprint(DBG_BRANCH,("fifo empty \n")); select_wait(&CanWait[minor],wait); DBGout();return 0; } break; case SEL_OUT: DBGprint(DBG_BRANCH,("sel_out \n")); /* ready for write ? */ select_wait(&CanWait[minor],wait); DBGout();return 0; } DBGout();return 1; #endif DBGout(); return 0; }