要将一个具体的can 控制器注册到xenomai 中的RTDM实时驱动模型中,一般分为两个部分:第一,将具体的CAN控制器注册到RTCAN模块中。第二,将注册的具体的RTCAN设备注册到 RTDM之中。
1、 SJA1000设备注册到RTCAN 中
adv_pci_init_one->rtcan_adv_pci_add_chan->rtcan_sja1000_register()->rtcan_dev_register()
在上一篇文章" Advantech PCI card 驱动注册 --W T "中介绍到注册完PCI设备后 ,若需要使用xenomai下实时系统,则应向xenomai的子系统RTDM 实时驱动模型注册一个RTDM设备,在这里选用SJA1000:
rtcan_pci_adv.c中
adv_pci_init_one()启用 PCI 设备,请求适当的配置空间的"BAR"区域
static int adv_pci_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
int ret, channel;
unsigned int nb_ports = 0;
unsigned int bar = 0;
unsigned int bar_flag = 0;
unsigned int offset = 0;
unsigned int ix;
struct rtcan_device *master_dev = NULL;
dev_info(&pdev->dev, "RTCAN Registering card");
ret = pci_enable_device(pdev);
if (ret)
goto failure;
dev_info(&pdev->dev, "RTCAN detected Advantech PCI card at slot RTCAN在插槽中检测到Advantech PCI卡 #%i\n",
PCI_SLOT(pdev->devfn));
ret = pci_request_regions(pdev, RTCAN_DRV_NAME);
if (ret)
goto failure_device;
switch (pdev->device) {
case 0xc001:
case 0xc002:
case 0xc004:
case 0xc101:
case 0xc102:
case 0xc104:
nb_ports = pdev->device & 0x7;
offset = 0x100;
bar = 0;
break;
case 0x1680:
case 0x2052:
nb_ports = 2;
bar = 2;
bar_flag = 1;
break;
case 0x1681:
nb_ports = 1;
bar = 2;
bar_flag = 1;
break;
default:
goto failure_regions;
}
if (nb_ports > 1)
channel = CHANNEL_MASTER;
else
channel = CHANNEL_SINGLE;
RTCAN_DBG("%s: Initializing device %04x:%04x:%04x\n",
RTCAN_DRV_NAME,
pdev->vendor,
pdev->device,
pdev->subsystem_device);
ret = rtcan_adv_pci_add_chan(pdev, channel, bar, offset, &master_dev);
if (ret)
goto failure_iounmap;
/* register slave channel, if any */
for (ix = 1; ix < nb_ports; ix++) {
ret = rtcan_adv_pci_add_chan(pdev,
CHANNEL_SLAVE,
bar + (bar_flag ? ix : 0),
offset * ix,
&master_dev);
if (ret)
goto failure_iounmap;
}
pci_set_drvdata(pdev, master_dev);
return 0;
failure_iounmap:
if (master_dev)
rtcan_adv_pci_del_chan(pdev, master_dev);
failure_regions:
pci_release_regions(pdev);
failure_device:
pci_disable_device(pdev);
failure:
return ret;
}
其中
语句ret = rtcan_adv_pci_add_chan(pdev, channel, bar, offset, &master_dev);
添加设备:rtcan_adv_pci_add_chan()在这个函数中完成了rtcan设备初始化。
static int rtcan_adv_pci_add_chan(struct pci_dev *pdev,
int channel,
unsigned int bar,
unsigned int offset,
struct rtcan_device **master_dev)
{
struct rtcan_device *dev;
struct rtcan_sja1000 *chip;
struct rtcan_adv_pci *board;
void __iomem *base_addr;
int ret;
dev = rtcan_dev_alloc(sizeof(struct rtcan_sja1000),
sizeof(struct rtcan_adv_pci));
if (dev == NULL)
return -ENOMEM;
chip = (struct rtcan_sja1000 *)dev->priv;
board = (struct rtcan_adv_pci *)dev->board_priv;
if (channel == CHANNEL_SLAVE) {
struct rtcan_adv_pci *master_board =
(struct rtcan_adv_pci *)(*master_dev)->board_priv;
master_board->slave_dev =