/* Read status register */
status_reg = ioread16(&tpci200->info->interface_regs->status);
/* Did we cause the interrupt? */ if (!(status_reg & TPCI200_SLOT_INT_MASK)) return IRQ_NONE;
/* callback to the IRQ handler for the corresponding slot */
rcu_read_lock(); for (i = 0; i < TPCI200_NB_SLOT; i++) { if (!(status_reg & ((TPCI200_A_INT0 | TPCI200_A_INT1) << (2 * i)))) continue;
slot_irq = rcu_dereference(tpci200->slots[i].irq);
ret = tpci200_slot_irq(slot_irq); if (ret == -ENODEV) {
dev_info(&tpci200->info->pdev->dev, "No registered ISR for slot [%d:%d]!. IRQ will be disabled.\n",
tpci200->number, i);
tpci200_disable_irq(tpci200, i);
}
}
rcu_read_unlock();
staticint tpci200_request_irq(struct ipack_device *dev,
irqreturn_t (*handler)(void *), void *arg)
{ int res = 0; struct slot_irq *slot_irq; struct tpci200_board *tpci200;
tpci200 = check_slot(dev); if (tpci200 == NULL) return -EINVAL;
if (mutex_lock_interruptible(&tpci200->mutex)) return -ERESTARTSYS;
if (tpci200->slots[dev->slot].irq != NULL) {
dev_err(&dev->dev, "Slot [%d:%d] IRQ already registered !\n",
dev->bus->bus_nr,
dev->slot);
res = -EINVAL; goto out_unlock;
}
slot_irq = kzalloc(sizeof(struct slot_irq), GFP_KERNEL); if (slot_irq == NULL) {
dev_err(&dev->dev, "Slot [%d:%d] unable to allocate memory for IRQ !\n",
dev->bus->bus_nr, dev->slot);
res = -ENOMEM; goto out_unlock;
}
/* * WARNING: Setup Interrupt Vector in the IndustryPack device * before an IRQ request. * Read the User Manual of your IndustryPack device to know * where to write the vector in memory.
*/
slot_irq->handler = handler;
slot_irq->arg = arg;
slot_irq->holder = dev;
staticint tpci200_register(struct tpci200_board *tpci200)
{ int i; int res;
phys_addr_t ioidint_base; unsignedshort slot_ctrl;
if (pci_enable_device(tpci200->info->pdev) < 0) return -ENODEV;
/* Request IP interface register (Bar 2) */
res = pci_request_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR, "Carrier IP interface registers"); if (res) {
dev_err(&tpci200->info->pdev->dev, "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 2 !",
tpci200->info->pdev->bus->number,
tpci200->info->pdev->devfn); goto err_disable_device;
}
/* Request IO ID INT space (Bar 3) */
res = pci_request_region(tpci200->info->pdev,
TPCI200_IO_ID_INT_SPACES_BAR, "Carrier IO ID INT space"); if (res) {
dev_err(&tpci200->info->pdev->dev, "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 3 !",
tpci200->info->pdev->bus->number,
tpci200->info->pdev->devfn); goto err_ip_interface_bar;
}
/* Request MEM8 space (Bar 5) */
res = pci_request_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR, "Carrier MEM8 space"); if (res) {
dev_err(&tpci200->info->pdev->dev, "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 5!",
tpci200->info->pdev->bus->number,
tpci200->info->pdev->devfn); goto err_io_id_int_spaces_bar;
}
/* Request MEM16 space (Bar 4) */
res = pci_request_region(tpci200->info->pdev, TPCI200_MEM16_SPACE_BAR, "Carrier MEM16 space"); if (res) {
dev_err(&tpci200->info->pdev->dev, "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 4!",
tpci200->info->pdev->bus->number,
tpci200->info->pdev->devfn); goto err_mem8_space_bar;
}
/* Map internal tpci200 driver user space */
tpci200->info->interface_regs =
ioremap(pci_resource_start(tpci200->info->pdev,
TPCI200_IP_INTERFACE_BAR),
TPCI200_IFACE_SIZE); if (!tpci200->info->interface_regs) {
dev_err(&tpci200->info->pdev->dev, "(bn 0x%X, sn 0x%X) failed to map driver user space!",
tpci200->info->pdev->bus->number,
tpci200->info->pdev->devfn);
res = -ENOMEM; goto err_mem16_space_bar;
}
/* Initialize lock that protects interface_regs */
spin_lock_init(&tpci200->regs_lock);
tpci200 = kzalloc(sizeof(struct tpci200_board), GFP_KERNEL); if (!tpci200) return -ENOMEM;
tpci200->info = kzalloc(sizeof(struct tpci200_infos), GFP_KERNEL); if (!tpci200->info) {
ret = -ENOMEM; goto err_tpci200;
}
pci_dev_get(pdev);
/* Obtain a mapping of the carrier's PCI configuration registers */
ret = pci_request_region(pdev, TPCI200_CFG_MEM_BAR,
KBUILD_MODNAME " Configuration Memory"); if (ret) {
dev_err(&pdev->dev, "Failed to allocate PCI Configuration Memory");
ret = -EBUSY; goto err_tpci200_info;
}
tpci200->info->cfg_regs = ioremap(
pci_resource_start(pdev, TPCI200_CFG_MEM_BAR),
pci_resource_len(pdev, TPCI200_CFG_MEM_BAR)); if (!tpci200->info->cfg_regs) {
dev_err(&pdev->dev, "Failed to map PCI Configuration Memory");
ret = -EFAULT; goto err_request_region;
}
/* Disable byte swapping for 16 bit IP module access. This will ensure * that the Industrypack big endian byte order is preserved by the
* carrier. */
reg32 = ioread32(tpci200->info->cfg_regs + LAS1_DESC);
reg32 |= 1 << LAS_BIT_BIGENDIAN;
iowrite32(reg32, tpci200->info->cfg_regs + LAS1_DESC);
/* register the device and initialize it */
ret = tpci200_install(tpci200); if (ret) {
dev_err(&pdev->dev, "error during tpci200 install\n");
ret = -ENODEV; goto err_cfg_regs;
}
/* Register the carrier in the industry pack bus driver */
tpci200->info->ipack_bus = ipack_bus_register(&pdev->dev,
TPCI200_NB_SLOT,
&tpci200_bus_ops,
THIS_MODULE); if (!tpci200->info->ipack_bus) {
dev_err(&pdev->dev, "error registering the carrier on ipack driver\n");
ret = -EFAULT; goto err_tpci200_install;
}
/* save the bus number given by ipack to logging purpose */
tpci200->number = tpci200->info->ipack_bus->bus_nr;
dev_set_drvdata(&pdev->dev, tpci200);
for (i = 0; i < TPCI200_NB_SLOT; i++)
tpci200_create_device(tpci200, i); return 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.