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

📄 pcan_fops_rt.c

📁 linux下的CAN BUS驱动代码。适合在arm平台使用。
💻 C
📖 第 1 页 / 共 2 页
字号:
//****************************************************************************// Copyright (C) 2001-2007  PEAK System-Technik GmbH//// linux@peak-system.com// www.peak-system.com//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//// Maintainer(s): Klaus Hitschler (klaus.hitschler@gmx.de)//// Major contributions by://                Edouard Tisserant (edouard.tisserant@lolitech.fr) XENOMAI//                Laurent Bessard   (laurent.bessard@lolitech.fr)   XENOMAI//                Oliver Hartkopp   (oliver.hartkopp@volkswagen.de) socketCAN//// Contributions: Marcel Offermans (marcel.offermans@luminis.nl)//                Arno (a.vdlaan@hccnet.nl)//                John Privitera (JohnPrivitera@dciautomation.com)//****************************************************************************//****************************************************************************//// pcan_fops_rt.c - all file operation functions, exports only struct fops//// $Id: pcan_fops_rt.c $////****************************************************************************//****************************************************************************// DEFINES#define PCAN_OPEN_PATH_ARGS struct pcandev *dev, struct rtdm_dev_context *context#define PCAN_RELEASE_PATH_ARGS struct pcandev *dev, struct pcanctx_rt *ctx#define REQ_IRQ_ARG context#if RTDM_API_VER < 6  #define IOCTL_REQUEST_TYPE int#else  #define IOCTL_REQUEST_TYPE unsigned int#endif// TODO  wait_until_fifo_empty(dev, MAX_WAIT_UNTIL_CLOSE, ctx);#define WAIT_UNTIL_FIFO_EMPTY()//****************************************************************************// CODEstatic int copy_from_user_rt(rtdm_user_info_t *user_info, void *to, void *from, size_t size){  if (user_info)  {    if (!rtdm_read_user_ok(user_info, from, size) ||         rtdm_copy_from_user(user_info, to, from, size))      return -EFAULT;  }  else    memcpy(to, from, size);  return 0;}static int copy_to_user_rt(rtdm_user_info_t *user_info, void *to, void *from, size_t size){  if (user_info)  {    if (!rtdm_rw_user_ok(user_info, to, size) ||         rtdm_copy_to_user(user_info, to, from, size))      return -EFAULT;  }  else    memcpy(to, from, size);  return 0;}static void wait_until_fifo_empty(struct pcandev *dev, u32 mTime, struct pcanctx_rt *ctx){  int fifo_not_empty;  rtdm_lockctx_t lockctx;  rtdm_lock_get_irqsave(&ctx->out_lock, lockctx);  fifo_not_empty = pcan_fifo_empty(&dev->writeFifo);  if (fifo_not_empty)    rtdm_event_clear(&ctx->empty_event);  rtdm_lock_put_irqrestore(&ctx->out_lock, lockctx);  if(fifo_not_empty)    rtdm_event_timedwait(&ctx->empty_event, mTime * 1000, NULL);  atomic_set(&dev->DataSendReady, 1);}//----------------------------------------------------------------------------// is called when the path is openedint pcan_open_rt(struct rtdm_dev_context *context, rtdm_user_info_t *user_info, int oflags){  struct pcandev *dev;  int err = 0;  struct pcanctx_rt *ctx;  int _minor = context->device->device_id;  DPRINTK(KERN_DEBUG "%s: pcan_open_rt(), minor = %d.\n", DEVICE_NAME, _minor);  ctx = (struct pcanctx_rt *)context->dev_private;  /* IPC initialisation - cannot fail with used parameters */  rtdm_event_init(&ctx->in_event, 0);  rtdm_event_init(&ctx->out_event, 1);  rtdm_event_init(&ctx->empty_event, 1);  rtdm_lock_init(&ctx->in_lock);  rtdm_lock_init(&ctx->out_lock);  rtdm_lock_init(&ctx->sja_lock);  dev = pcan_search_dev(_minor);  if (!dev)    return -ENODEV;  ctx->dev = dev;  ctx->nReadRest = 0;  ctx->nTotalReadCount = 0;  ctx->pcReadPointer = ctx->pcReadBuffer;  ctx->nWriteCount = 0;  ctx->pcWritePointer = ctx->pcWriteBuffer;  if (dev->wType == HW_PCI)    ctx->irq = dev->port.pci.wIrq;  if (dev->wType == HW_ISA_SJA)    ctx->irq = dev->port.isa.wIrq;  if (dev->wType == HW_DONGLE_SJA || dev->wType == HW_DONGLE_SJA_EPP)    ctx->irq = dev->port.dng.wIrq;  err = pcan_open_path(dev, context);  if (err)    return err;  /* enable IRQ interrupts */  err = rtdm_irq_enable(&ctx->irq_handle);  if (err)  {    DPRINTK(KERN_DEBUG "%s: can't enable interrupt\n", DEVICE_NAME);    return err;  }  DPRINTK(KERN_DEBUG "%s: pcan_open_rt() is OK\n", DEVICE_NAME);  return err;}//----------------------------------------------------------------------------// is called when the path is closedint pcan_close_rt(struct rtdm_dev_context *context, rtdm_user_info_t *user_info){  struct pcandev *dev;  struct pcanctx_rt *ctx;  DPRINTK(KERN_DEBUG "%s: pcan_close_rt()\n", DEVICE_NAME);  ctx = (struct pcanctx_rt *)context->dev_private;  dev = ctx->dev;  // first, prevent pending fops to act if unblocked  dev->ucPhysicallyInstalled = 0;  // then remove IRQ  //rtdm_irq_disable(&ctx->irq_handle);  pcan_release_path(dev, ctx);  rtdm_irq_free(&ctx->irq_handle);  // will unblock pending fops  rtdm_event_destroy(&ctx->out_event);  rtdm_event_destroy(&ctx->in_event);  rtdm_event_destroy(&ctx->empty_event);  // restore device presence  dev->ucPhysicallyInstalled = 1;    // as wait_until_fifo_empty is not called in RT,   // have to fix DataSendReady here,   // so that device can transmit again  atomic_set(&dev->DataSendReady, 1);  return 0;}//----------------------------------------------------------------------------// is called at user ioctl() with cmd = PCAN_READ_MSGint pcan_ioctl_read_rt(rtdm_user_info_t *user_info, struct pcanctx_rt *ctx, TPCANRdMsg *usr){  int err = 0;  TPCANRdMsg msg;  struct pcandev *dev;  rtdm_lockctx_t lockctx;  DPRINTK(KERN_DEBUG "%s: pcan_ioctl_rt(PCAN_READ_MSG)\n", DEVICE_NAME);  dev = ctx->dev;  // sleep until fifo is not empty  err = rtdm_event_wait(&ctx->in_event);  if (err)    goto fail;  // if the device is plugged out  if (!dev->ucPhysicallyInstalled)    return -ENODEV;  rtdm_lock_get_irqsave(&ctx->in_lock, lockctx);   // get data out of fifo  err = pcan_fifo_get(&dev->readFifo, (void *)&msg);  // If fifo is NOT empty  if (pcan_fifo_empty(&dev->readFifo))    rtdm_event_signal(&ctx->in_event);  rtdm_lock_put_irqrestore(&ctx->in_lock, lockctx);  if (err){    goto fail;  }  if (copy_to_user_rt(user_info, usr, &msg, sizeof(*usr)))    err = -EFAULT;  fail:  return err;}//----------------------------------------------------------------------------// is called at user ioctl() with cmd = PCAN_WRITE_MSG int pcan_ioctl_write_rt(rtdm_user_info_t *user_info, struct pcanctx_rt *ctx, TPCANMsg *usr){  int err = 0;  TPCANMsg msg;  struct pcandev *dev;  rtdm_lockctx_t lockctx;  DPRINTK(KERN_DEBUG "%s: pcan_ioctl_rt(PCAN_WRITE_MSG)\n", DEVICE_NAME);  dev = ctx->dev;  // sleep until space is available  err = rtdm_event_wait(&ctx->out_event);  if (err)    goto fail;  // if the device is plugged out  if (!dev->ucPhysicallyInstalled)    return -ENODEV;  // get from user space  if (copy_from_user_rt(user_info, &msg, usr, sizeof(msg)))  {    err = -EFAULT;    goto fail;  }  // filter extended data if initialized to standard only  if (!(dev->bExtended) && ((msg.MSGTYPE & MSGTYPE_EXTENDED) || (msg.ID > 2047)))  {    err = -EINVAL;    goto fail;  }  rtdm_lock_get_irqsave(&ctx->out_lock, lockctx);  // put data into fifo  err = pcan_fifo_put(&dev->writeFifo, &msg);  // if fifo not full or can device ready to send  if (pcan_fifo_near_full(&dev->writeFifo) || atomic_read(&dev->DataSendReady))    rtdm_event_signal(&ctx->out_event);  rtdm_lock_put_irqrestore(&ctx->out_lock, lockctx);  if (!err)  {

⌨️ 快捷键说明

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