static int dabpci_probe(struct pci_dev *dev, const struct pci_device_id *id) { int result; printk(KERN_INFO "init DAB PCIe."); printk(KERN_INFO "the vendor:0x%x.\nthe device:0x%x.\n",dev->vendor,dev->device); /*adapt the space for private*/ DABDrv = kmalloc(sizeof(struct dab_dev),GFP_KERNEL); if(unlikely(!DABDrv)) return -ENOMEM; DABDrv->pci_dev = dev; /* Enable PCI*/ result = pci_enable_device(dev); if(unlikely(result)) goto disable_pci; /*set the pci dma mode*/ pci_set_master(dev); result = pci_set_dma_mask(dev, DMA_BIT_MASK(32)); if(unlikely(result)) { printk( KERN_ERR "DABPCI: 32-bits PCI DMA address not supported!\n"); goto disable_pci; } else printk( KERN_INFO "DABPCI: set dma mask successfuly!\n"); /*request I/O resource */ DABDrv->mmio_start = pci_resource_start(dev,0); DABDrv->mmio_end = pci_resource_end(dev,0); DABDrv->mmio_flags = pci_resource_flags(dev,0); DABDrv->mmio_len = pci_resource_len(dev,0); if(unlikely(!(DABDrv->mmio_flags & IORESOURCE_MEM))) { printk(KERN_ERR "DABPCI: Failed to alloc IO mem!\n"); } result = pci_request_regions(dev, DAB_NAME); if(unlikely(result)) { printk(KERN_ERR "DABPCI: Failed to request IO space!\n"); goto disable_pci; } DABDrv->mmio_addr = ioremap(DABDrv->mmio_start,DABDrv->mmio_len); if(unlikely(!DABDrv->mmio_addr)) { result = -EIO; printk(KERN_ERR "DABPCI: Failed to do IO remap!\n"); } /*enable MSI*/ result = pci_enable_msi(dev); if(unlikely(result)) { printk(KERN_ERR "DABPCI: Failed to enable msi!\n"); return result; } DABDrv->m_irq = dev->irq; result = request_irq(DABDrv->m_irq,DABDrv_interrupt,IRQF_DISABLED,DAB_NAME,NULL); if(unlikely(result)) { printk(KERN_ERR "DABPCI: Failed to request interrup.\n"); goto disable_pci; } dabpci_major = register_chrdev(0,DAB_CLASS_NAME,&DABDrv_fops); if(dabpci_major<0) { printk(KERN_ERR "DABPCI: Failed to get the major device number:%d;\n",dabpci_major); goto disable_pci; } else { printk(KERN_INFO "DABPCI: Get the major device number succesful,major = %d\n",dabpci_major); } return 0; disable_pci: pci_disable_device(dev); return result; }
static int dwc_otg_probe(struct pci_dev *pdev, const struct pci_device_id *id) { int retval = 0; struct resource res[2]; struct dwc_otg2 *otg = NULL; unsigned long resource, len; if (!dwc3_otg_pdata) return -ENODEV; if (pci_enable_device(pdev) < 0) { dev_err(&pdev->dev, "pci device enable failed\n"); return -ENODEV; } pci_set_power_state(pdev, PCI_D0); pci_set_master(pdev); otg = dwc3_otg_alloc(&pdev->dev); if (!otg) { dev_err(&pdev->dev, "dwc3 otg init failed\n"); goto err; } /* control register: BAR 0 */ resource = pci_resource_start(pdev, 0); len = pci_resource_len(pdev, 0); if (!request_mem_region(resource, len, driver_name)) { otg_err(otg, "Request memory region failed\n"); retval = -EBUSY; goto err; } otg_dbg(otg, "dwc otg pci resouce: 0x%lu, len: 0x%lu\n", resource, len); otg_dbg(otg, "vendor: 0x%x, device: 0x%x\n", pdev->vendor, pdev->device); memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res)); res[0].start = pci_resource_start(pdev, 0); res[0].end = pci_resource_end(pdev, 0); res[0].name = "dwc_usb3_io"; res[0].flags = IORESOURCE_MEM; res[1].start = pdev->irq; res[1].name = "dwc_usb3_irq"; res[1].flags = IORESOURCE_IRQ; retval = dwc3_otg_create_children(otg, res, ARRAY_SIZE(res)); if (retval) { otg_err(otg, "dwc3 otg create alloc children failed\n"); goto err; } otg->irqnum = pdev->irq; wake_lock_init(&wakelock, WAKE_LOCK_SUSPEND, "dwc_otg_wakelock"); if (dwc3_otg_pdata->platform_init) { retval = dwc3_otg_pdata->platform_init(otg); if (retval) goto err; } pm_runtime_set_autosuspend_delay(&pdev->dev, 100); pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_allow(&pdev->dev); pm_runtime_mark_last_busy(otg->dev); pm_runtime_put_autosuspend(&pdev->dev); return 0; err: if (the_transceiver) dwc_otg_remove(pdev); return retval; }
static int dwc3_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) { struct resource res[2]; struct platform_device *dwc3; struct dwc3_pci *glue; int ret = -ENOMEM; struct device *dev = &pci->dev; glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL); if (!glue) { dev_err(dev, "not enough memory\n"); return -ENOMEM; } glue->dev = dev; ret = pci_enable_device(pci); if (ret) { dev_err(dev, "failed to enable pci device\n"); return -ENODEV; } pci_set_power_state(pci, PCI_D0); pci_set_master(pci); ret = dwc3_pci_register_phys(glue); if (ret) { dev_err(dev, "couldn't register PHYs\n"); return ret; } dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO); if (!dwc3) { dev_err(dev, "couldn't allocate dwc3 device\n"); ret = -ENOMEM; goto err1; } memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res)); res[0].start = pci_resource_start(pci, 0); res[0].end = pci_resource_end(pci, 0); res[0].name = "dwc_usb3"; res[0].flags = IORESOURCE_MEM; res[1].start = pci->irq; res[1].name = "dwc_usb3"; res[1].flags = IORESOURCE_IRQ; ret = platform_device_add_resources(dwc3, res, ARRAY_SIZE(res)); if (ret) { dev_err(dev, "couldn't add resources to dwc3 device\n"); goto err1; } pci_set_drvdata(pci, glue); dma_set_coherent_mask(&dwc3->dev, dev->coherent_dma_mask); dwc3->dev.dma_mask = dev->dma_mask; dwc3->dev.dma_parms = dev->dma_parms; dwc3->dev.parent = dev; glue->dwc3 = dwc3; ret = platform_device_add(dwc3); if (ret) { dev_err(dev, "failed to register dwc3 device\n"); goto err3; } return 0; err3: pci_set_drvdata(pci, NULL); platform_device_put(dwc3); err1: pci_disable_device(pci); return ret; }
int qxl_device_init(struct qxl_device *qdev, struct drm_device *ddev, struct pci_dev *pdev, unsigned long flags) { int r; qdev->dev = &pdev->dev; qdev->ddev = ddev; qdev->pdev = pdev; qdev->flags = flags; mutex_init(&qdev->gem.mutex); mutex_init(&qdev->update_area_mutex); mutex_init(&qdev->release_mutex); mutex_init(&qdev->surf_evict_mutex); INIT_LIST_HEAD(&qdev->gem.objects); qdev->rom_base = pci_resource_start(pdev, 2); qdev->rom_size = pci_resource_len(pdev, 2); qdev->vram_base = pci_resource_start(pdev, 0); qdev->surfaceram_base = pci_resource_start(pdev, 1); qdev->surfaceram_size = pci_resource_len(pdev, 1); qdev->io_base = pci_resource_start(pdev, 3); qdev->vram_mapping = io_mapping_create_wc(qdev->vram_base, pci_resource_len(pdev, 0)); qdev->surface_mapping = io_mapping_create_wc(qdev->surfaceram_base, qdev->surfaceram_size); DRM_DEBUG_KMS("qxl: vram %p-%p(%dM %dk), surface %p-%p(%dM %dk)\n", (void *)qdev->vram_base, (void *)pci_resource_end(pdev, 0), (int)pci_resource_len(pdev, 0) / 1024 / 1024, (int)pci_resource_len(pdev, 0) / 1024, (void *)qdev->surfaceram_base, (void *)pci_resource_end(pdev, 1), (int)qdev->surfaceram_size / 1024 / 1024, (int)qdev->surfaceram_size / 1024); qdev->rom = ioremap(qdev->rom_base, qdev->rom_size); if (!qdev->rom) { pr_err("Unable to ioremap ROM\n"); return -ENOMEM; } qxl_check_device(qdev); r = qxl_bo_init(qdev); if (r) { DRM_ERROR("bo init failed %d\n", r); return r; } qdev->ram_header = ioremap(qdev->vram_base + qdev->rom->ram_header_offset, sizeof(*qdev->ram_header)); qdev->command_ring = qxl_ring_create(&(qdev->ram_header->cmd_ring_hdr), sizeof(struct qxl_command), QXL_COMMAND_RING_SIZE, qdev->io_base + QXL_IO_NOTIFY_CMD, false, &qdev->display_event); qdev->cursor_ring = qxl_ring_create( &(qdev->ram_header->cursor_ring_hdr), sizeof(struct qxl_command), QXL_CURSOR_RING_SIZE, qdev->io_base + QXL_IO_NOTIFY_CMD, false, &qdev->cursor_event); qdev->release_ring = qxl_ring_create( &(qdev->ram_header->release_ring_hdr), sizeof(uint64_t), QXL_RELEASE_RING_SIZE, 0, true, NULL); /* TODO - slot initialization should happen on reset. where is our * reset handler? */ qdev->n_mem_slots = qdev->rom->slots_end; qdev->slot_gen_bits = qdev->rom->slot_gen_bits; qdev->slot_id_bits = qdev->rom->slot_id_bits; qdev->va_slot_mask = (~(uint64_t)0) >> (qdev->slot_id_bits + qdev->slot_gen_bits); qdev->mem_slots = kmalloc(qdev->n_mem_slots * sizeof(struct qxl_memslot), GFP_KERNEL); idr_init(&qdev->release_idr); spin_lock_init(&qdev->release_idr_lock); idr_init(&qdev->surf_id_idr); spin_lock_init(&qdev->surf_id_idr_lock); mutex_init(&qdev->async_io_mutex); /* reset the device into a known state - no memslots, no primary * created, no surfaces. */ qxl_io_reset(qdev); /* must initialize irq before first async io - slot creation */ r = qxl_irq_init(qdev); if (r) return r; /* * Note that virtual is surface0. We rely on the single ioremap done * before. */ qdev->main_mem_slot = setup_slot(qdev, 0, (unsigned long)qdev->vram_base, (unsigned long)qdev->vram_base + qdev->rom->ram_header_offset); qdev->surfaces_mem_slot = setup_slot(qdev, 1, (unsigned long)qdev->surfaceram_base, (unsigned long)qdev->surfaceram_base + qdev->surfaceram_size); DRM_INFO("main mem slot %d [%lx,%x)\n", qdev->main_mem_slot, (unsigned long)qdev->vram_base, qdev->rom->ram_header_offset); qdev->gc_queue = create_singlethread_workqueue("qxl_gc"); INIT_WORK(&qdev->gc_work, qxl_gc_work); r = qxl_fb_init(qdev); if (r) return r; return 0; }
static int softpcie_pci_init(struct pci_dev *pdev, const struct pci_device_id *ent) { struct dma *bar2_dma = &sp->dev.bar2_dma; struct mmio *bar0 = &sp->dev.bar0; struct mmio *bar2 = &sp->dev.bar2; int rc; pr_info("%s\n", __func__); rc = pci_enable_device(pdev); if (rc) goto error; rc = pci_request_regions(pdev, DRV_NAME); if (rc) goto error; /* set BUS Master Mode */ pci_set_master(pdev); /* BAR0 (pcie pio) */ bar0->start = pci_resource_start(pdev, 0); bar0->end = pci_resource_end(pdev, 0); bar0->flags = pci_resource_flags(pdev, 0); bar0->len = pci_resource_len(pdev, 0); bar0->virt = ioremap(bar0->start, bar0->len); if(!bar0->virt) { pr_err("cannot ioremap MMIO0 base\n"); goto error; } pr_info("bar0_start: %X\n", (uint32_t)bar0->start); pr_info("bar0_end : %X\n", (uint32_t)bar0->end); pr_info("bar0_flags: %X\n", (uint32_t)bar0->flags); pr_info("bar0_len : %X\n", (uint32_t)bar0->len); /* BAR2 (pcie DMA) */ bar2->start = pci_resource_start(pdev, 2); bar2->end = pci_resource_end(pdev, 2); bar2->flags = pci_resource_flags(pdev, 2); bar2->len = pci_resource_len(pdev, 2); bar2->virt = ioremap(bar2->start, bar2->len); if (!bar2->virt) { pr_err("cannot ioremap MMIO1 base\n"); goto error; } pr_info("bar2_virt : %p\n", bar2->virt); pr_info("bar2_start: %X\n", (uint32_t)bar2->start); pr_info("bar2_end : %X\n", (uint32_t)bar2->end); pr_info("bar2_flags: %X\n", (uint32_t)bar2->flags); pr_info("bar2_len : %X\n", (uint32_t)bar2->len); /* BAR2 (pcie DMA) */ bar2_dma->virt = dma_alloc_coherent(&pdev->dev, DMA_BUF_SIZE, &bar2_dma->phys, GFP_KERNEL); if (!bar2_dma->virt) { pr_err("cannot dma_alloc_coherent\n"); goto error; } pr_info("bar2_dma_virt: %p\n", bar2_dma->virt); pr_info("bar2_dma_phys: %X\n", (uint32_t)bar2_dma->phys); return 0; error: pr_info("softpcie_pci_init error\n"); pci_release_regions(pdev); pci_disable_device(pdev); return -1; }
static int dwc3_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) { struct property_entry *p = (struct property_entry *)id->driver_data; struct dwc3_pci *dwc; struct resource res[2]; int ret; struct device *dev = &pci->dev; ret = pcim_enable_device(pci); if (ret) { dev_err(dev, "failed to enable pci device\n"); return -ENODEV; } pci_set_master(pci); dwc = devm_kzalloc(dev, sizeof(*dwc), GFP_KERNEL); if (!dwc) return -ENOMEM; dwc->dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO); if (!dwc->dwc3) return -ENOMEM; memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res)); res[0].start = pci_resource_start(pci, 0); res[0].end = pci_resource_end(pci, 0); res[0].name = "dwc_usb3"; res[0].flags = IORESOURCE_MEM; res[1].start = pci->irq; res[1].name = "dwc_usb3"; res[1].flags = IORESOURCE_IRQ; ret = platform_device_add_resources(dwc->dwc3, res, ARRAY_SIZE(res)); if (ret) { dev_err(dev, "couldn't add resources to dwc3 device\n"); goto err; } dwc->pci = pci; dwc->dwc3->dev.parent = dev; ACPI_COMPANION_SET(&dwc->dwc3->dev, ACPI_COMPANION(dev)); ret = platform_device_add_properties(dwc->dwc3, p); if (ret < 0) return ret; ret = dwc3_pci_quirks(dwc); if (ret) goto err; ret = platform_device_add(dwc->dwc3); if (ret) { dev_err(dev, "failed to register dwc3 device\n"); goto err; } device_init_wakeup(dev, true); pci_set_drvdata(pci, dwc); pm_runtime_put(dev); #ifdef CONFIG_PM INIT_WORK(&dwc->wakeup_work, dwc3_pci_resume_work); #endif return 0; err: platform_device_put(dwc->dwc3); return ret; }
int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) { int err, idx, nm; unsigned int memlen; struct hpi_message hm; struct hpi_response hr; struct hpi_adapter adapter; struct hpi_pci pci; memset(&adapter, 0, sizeof(adapter)); printk(KERN_DEBUG "probe PCI device (%04x:%04x,%04x:%04x,%04x)\n", pci_dev->vendor, pci_dev->device, pci_dev->subsystem_vendor, pci_dev->subsystem_device, pci_dev->devfn); hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CREATE_ADAPTER); hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CREATE_ADAPTER, HPI_ERROR_PROCESSING_MESSAGE); hm.adapter_index = -1; /* an invalid index */ /* fill in HPI_PCI information from kernel provided information */ adapter.pci = pci_dev; nm = HPI_MAX_ADAPTER_MEM_SPACES; for (idx = 0; idx < nm; idx++) { HPI_DEBUG_LOG(INFO, "resource %d %s %08llx-%08llx %04llx\n", idx, pci_dev->resource[idx].name, (unsigned long long)pci_resource_start(pci_dev, idx), (unsigned long long)pci_resource_end(pci_dev, idx), (unsigned long long)pci_resource_flags(pci_dev, idx)); if (pci_resource_flags(pci_dev, idx) & IORESOURCE_MEM) { memlen = pci_resource_len(pci_dev, idx); adapter.ap_remapped_mem_base[idx] = ioremap(pci_resource_start(pci_dev, idx), memlen); if (!adapter.ap_remapped_mem_base[idx]) { HPI_DEBUG_LOG(ERROR, "ioremap failed, aborting\n"); /* unmap previously mapped pci mem space */ goto err; } } pci.ap_mem_base[idx] = adapter.ap_remapped_mem_base[idx]; } /* could replace Pci with direct pointer to pci_dev for linux Instead wrap accessor functions for IDs etc. Would it work for windows? */ pci.bus_number = pci_dev->bus->number; pci.vendor_id = (u16)pci_dev->vendor; pci.device_id = (u16)pci_dev->device; pci.subsys_vendor_id = (u16)(pci_dev->subsystem_vendor & 0xffff); pci.subsys_device_id = (u16)(pci_dev->subsystem_device & 0xffff); pci.device_number = pci_dev->devfn; pci.interrupt = pci_dev->irq; pci.p_os_data = pci_dev; hm.u.s.resource.bus_type = HPI_BUS_PCI; hm.u.s.resource.r.pci = &pci; /* call CreateAdapterObject on the relevant hpi module */ hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); if (hr.error) goto err; if (prealloc_stream_buf) { adapter.p_buffer = vmalloc(prealloc_stream_buf); if (!adapter.p_buffer) { HPI_DEBUG_LOG(ERROR, "HPI could not allocate " "kernel buffer size %d\n", prealloc_stream_buf); goto err; } } adapter.index = hr.u.s.adapter_index; adapter.type = hr.u.s.aw_adapter_list[adapter.index]; hm.adapter_index = adapter.index; err = hpi_adapter_open(NULL, adapter.index); if (err) goto err; adapter.snd_card_asihpi = NULL; /* WARNING can't init mutex in 'adapter' * and then copy it to adapters[] ?!?! */ adapters[hr.u.s.adapter_index] = adapter; mutex_init(&adapters[adapter.index].mutex); pci_set_drvdata(pci_dev, &adapters[adapter.index]); printk(KERN_INFO "probe found adapter ASI%04X HPI index #%d.\n", adapter.type, adapter.index); return 0; err: for (idx = 0; idx < HPI_MAX_ADAPTER_MEM_SPACES; idx++) { if (adapter.ap_remapped_mem_base[idx]) { iounmap(adapter.ap_remapped_mem_base[idx]); adapter.ap_remapped_mem_base[idx] = NULL; } } if (adapter.p_buffer) { adapter.buffer_size = 0; vfree(adapter.p_buffer); } HPI_DEBUG_LOG(ERROR, "adapter_probe failed\n"); return -ENODEV; }
static int __devinit hypercall_init_board(struct pci_dev *pdev, struct hypercall_dev **dev_out) { unsigned long ioaddr; struct hypercall_dev *dev; int rc; u32 disable_dev_on_err = 0; unsigned long pio_start, pio_end, pio_flags, pio_len; unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; assert(pdev != NULL); *dev_out = NULL; dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (dev == NULL) { printk (KERN_ERR "%s: Unable to alloc hypercall device\n", pci_name(pdev)); return -ENOMEM; } dev->pci_dev = pdev; rc = pci_enable_device(pdev); if (rc) goto err_out; disable_dev_on_err = 1; pio_start = pci_resource_start (pdev, 0); pio_end = pci_resource_end (pdev, 0); pio_flags = pci_resource_flags (pdev, 0); pio_len = pci_resource_len (pdev, 0); mmio_start = pci_resource_start (pdev, 1); mmio_end = pci_resource_end (pdev, 1); mmio_flags = pci_resource_flags (pdev, 1); mmio_len = pci_resource_len (pdev, 1); DPRINTK("PIO region size == 0x%02lX\n", pio_len); DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); rc = pci_request_regions (pdev, "hypercall"); if (rc) goto err_out; #define USE_IO_OPS 1 #ifdef USE_IO_OPS ioaddr = (unsigned long)pci_iomap(pdev, 0, 0); //ioaddr = ioport_map(pio_start, pio_len); if (!ioaddr) { printk(KERN_ERR "%s: cannot map PIO, aborting\n", pci_name(pdev)); rc = -EIO; goto err_out; } dev->base_addr = (unsigned long)pio_start; dev->io_addr = (void*)ioaddr; dev->regs_len = pio_len; #else ioaddr = pci_iomap(pdev, 1, 0); if (ioaddr == NULL) { printk(KERN_ERR "%s: cannot remap MMIO, aborting\n", pci_name(pdev)); rc = -EIO; goto err_out; } dev->base_addr = ioaddr; dev->io_addr = (void*)ioaddr; dev->regs_len = mmio_len; #endif /* USE_IO_OPS */ *dev_out = dev; return 0; err_out: hypercall_cleanup_dev(dev); if (disable_dev_on_err) pci_disable_device(pdev); return rc; }
/*! * otg_pci_probe() - otg pci probe function * * Get the standard PCI resources allocated. * */ int __devinit otg_pci_probe (struct pci_dev *pci_dev, const struct pci_device_id *id, struct otg_pci_driver *otg_pci_driver) { struct otg_driver *otg_driver; struct otg_dev *otg_dev = NULL; int enabled = 0; int irq = 0; int region; u8 latency, limit; /* allocate otg_dev structure and fill in standard fields */ THROW_UNLESS((otg_dev = kmalloc(sizeof(struct otg_dev), SLAB_KERNEL)), error); memset(otg_dev, 0, sizeof(struct otg_dev)); otg_dev->PCI = otg_trace_obtain_tag(); //printk(KERN_INFO"%s: PCI %d\n", __FUNCTION__, otg_dev->PCI); //TRACE_MSG0(otg_dev->PCI, "TEST"); THROW_UNLESS((enabled = !pci_enable_device(pci_dev)), error); otg_dev->otg_pci_driver = otg_pci_driver; otg_dev->pci_regions = otg_pci_driver->pci_regions; pci_set_drvdata(pci_dev, otg_dev); printk(KERN_INFO"%s: pci_dev: %x otg_dev: %x drv_data: %x\n", __FUNCTION__, pci_dev, otg_dev, pci_get_drvdata(pci_dev)); for (region = 0; region < DEVICE_COUNT_RESOURCE; region++) { unsigned long resource_start; unsigned long resource_len; TRACE_MSG5(otg_dev->PCI, "[%2d] flags: %08x start: %08x end: %08x len: %08x", region, pci_resource_flags(pci_dev, region), pci_resource_start(pci_dev, region), pci_resource_end(pci_dev, region), pci_resource_len(pci_dev, region) ); CONTINUE_UNLESS(otg_dev->pci_regions & (1 << region)); resource_start = pci_resource_start(pci_dev, region); resource_len = pci_resource_len(pci_dev, region); TRACE_MSG5(otg_dev->PCI, "pci_dev: %x otg_dev: %x start: %lx len: %lx name: %s", pci_dev, otg_dev, resource_start, resource_len, otg_pci_driver->name); THROW_UNLESS(request_mem_region(resource_start, resource_len, otg_pci_driver->name), error); THROW_UNLESS((otg_dev->regs[region] = ioremap_nocache(resource_start, resource_len)), error); TRACE_MSG2(otg_dev->PCI, "regs[%d] %x", region, otg_dev->regs[region]); } THROW_UNLESS((irq = !request_irq(pci_dev->irq, otg_pci_isr, SA_SHIRQ, otg_pci_driver->name, pci_dev)), error); TRACE_MSG1(otg_dev->PCI, "irq: %d", pci_dev->irq); /* bad pci latencies can contribute to overruns - but where ?? */ pci_read_config_byte (pci_dev, PCI_LATENCY_TIMER, &latency); pci_read_config_byte (pci_dev, PCI_MAX_LAT, &limit); TRACE_MSG2(otg_dev->PCI, "latency: %02x limit: %02x", latency, limit); if (latency && /* limit &&*/ (limit < latency)) { pci_write_config_byte (pci_dev, PCI_LATENCY_TIMER, limit); pci_read_config_byte (pci_dev, PCI_LATENCY_TIMER, &latency); TRACE_MSG2(otg_dev->PCI, "latency: %02x limit: %02x", latency, limit); } /* XXX lock? */ otg_dev->id = otg_get_id(pci_dev); TRACE_MSG1(otg_dev->PCI, "id: %d", otg_dev->id); if (otg_devs) { TRACE_MSG2(otg_dev->PCI, "otg_devs: %x new: %x", otg_devs, otg_dev); otg_dev->next = otg_devs; } otg_devs = otg_dev; return 0; CATCH(error) { printk(KERN_INFO"%s: FAILED\n", __FUNCTION__); pci_set_drvdata(pci_dev, NULL); if (irq) free_irq(pci_dev->irq, otg_dev); otg_pci_free_dev(pci_dev, otg_dev); if (otg_dev) kfree(otg_dev); if (enabled) pci_disable_device(pci_dev); return -EINVAL; } }
/* * sycamore_init: called when the module is loaded and before probe */ static int __init sycamore_init(void){ struct sycamore_dev *dev; dev_t devno; int result; unsigned short num_of_bases; u32 base_address; printk("sycamore_init called\n"); /* * Allocate the per-device structure(s) */ sycamore_devices = kmalloc(sizeof(struct sycamore_dev), GFP_KERNEL); if (sycamore_devices == NULL){ printk("sycamore_init: no memory\n"); result = -ENOMEM; goto fail; } /* * Get a range of minor numbers to work with, asking for a dynamic * major unless directed otherwise at load time. */ if (sycamore_init_major != 0){ sycamore_major = sycamore_init_major; devno = MKDEV(sycamore_major, 0); result = register_chrdev_region(devno, 1, PCI_DRIVER_NAME); } else { //let the system assign the major number dynamically result = alloc_chrdev_region(&devno, 0, 1, PCI_DRIVER_NAME); sycamore_major = MAJOR(devno); } if (result < 0){ printk(KERN_NOTICE "sycamore_init: can't get major %d\n", sycamore_major); goto fail; } //only one device for now dev = sycamore_devices; /* * Initialize and add this device's character device table entry */ dev->pcidev = NULL; //initialize a character device cdev_init(&dev->cdev, &sycamore_fops); dev->cdev.owner = THIS_MODULE; dev->cdev.ops = &sycamore_fops; dev->offset = 0; //add the cdev device to the device result = cdev_add(&dev->cdev, devno, 1); //configure the pci device if (result){ printk(KERN_NOTICE "Error %d adding %s device", result, PCI_DRIVER_NAME); goto fail; } if ((result = pci_register_driver(&sycamore_driver)) != 0){ printk(KERN_NOTICE "Error %d registering %s PCI device", result, PCI_DRIVER_NAME); goto fail; } if (dev->pcidev == NULL){ printk(KERN_NOTICE "PCI DEV is NULL, probe failed\n"); goto fail; } //get the physical base addresses of the PCI base_address = pci_resource_start(dev->pcidev, 0); printk("<1> First base address register found at %08X \n", pci_resource_start(dev->pcidev, 0)); num_of_bases = 0; //why are bases less than 6? while ((base_address = pci_resource_start(dev->pcidev, num_of_bases)) != 0x00000000 && (num_of_bases < NUM_OF_BASES)){ unsigned long flags; flags = pci_resource_flags(dev->pcidev, num_of_bases); dev->bases[num_of_bases] = base_address; dev->base_size[num_of_bases] = pci_resource_end(dev->pcidev, num_of_bases) - base_address + 1; if (flags & IORESOURCE_IO){ //resource is IO mapped dev->base_map[num_of_bases] = BRIDGE_IO_MAPPED; } else { //resource is MEM mapped dev->base_map[num_of_bases] = BRIDGE_MEM_MAPPED; } num_of_bases++; } if (num_of_bases < 1){ printk("<1>No implemented base address register found!\n"); } dev->current_resource = -1; //store number of bases in structure dev->num_of_bases = num_of_bases; printk("num_of_bases found %d\n", num_of_bases); //display information about all base addresses found in this procedure for (num_of_bases = 0; num_of_bases < dev->num_of_bases; num_of_bases++){ printk("<1>BAR%d range from %08X to %08X \n", num_of_bases, dev->bases[num_of_bases], dev->bases[num_of_bases] + dev->base_size[num_of_bases]); } return 0; fail: sycamore_exit(); return result; }
static int pcidev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int ret = 0; struct pcidev_struct *pcidev = (struct pcidev_struct *)file->private_data; if (!pcidev) return -EIO; switch(cmd) { case PCIDEV_IOCTL_FIND: { struct pcidev_find_struct *find; struct pci_dev *dev; unsigned long vendorID, deviceID; int idx; if (pcidev->dev) return -EIO; // only alloc once for now if (!access_ok(VERIFY_WRITE, (void *)arg, sizeof(struct pcidev_find_struct))) return -EFAULT; find = (struct pcidev_find_struct *)arg; __get_user(vendorID, &find->vendorID); __get_user(deviceID, &find->deviceID); __put_user(-1, &find->bus); __put_user(-1, &find->device); __put_user(-1, &find->func); dev = pci_find_device(vendorID, deviceID, NULL); if (!dev) return -ENOENT; if (pci_enable_device(dev)) { printk(KERN_WARNING "pcidev: Could not enable the PCI device.\n"); return -EIO; } if (pci_set_dma_mask(dev, 0xffffffff)) printk(KERN_WARNING "pcidev: only limited PCI busmaster DMA support.\n"); pci_set_master(dev); printk(KERN_INFO "pcidev: device found at %x:%x.%d\n", dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); ret = pci_request_regions(dev, pcidev_name); if (ret < 0) break; for (idx = 0; idx < PCIDEV_COUNT_RESOURCES; idx++) { if (pci_resource_flags(dev, idx) & IORESOURCE_MEM) { long len = pci_resource_len(dev, idx); unsigned long mapped_start = (unsigned long)ioremap(pci_resource_start(dev, idx), len); __put_user(mapped_start, &find->resources[idx].start); __put_user(mapped_start + len - 1, &find->resources[idx].end); pcidev->mapped_mem[idx] = (void *)mapped_start; } else { pcidev->mapped_mem[idx] = NULL; __put_user(pci_resource_start(dev, idx), &find->resources[idx].start); __put_user(pci_resource_end(dev, idx), &find->resources[idx].end); } __put_user(pci_resource_flags(dev, idx), &find->resources[idx].flags); } pcidev->dev = dev; __put_user(dev->bus->number, &find->bus); __put_user(PCI_SLOT(dev->devfn), &find->device); __put_user(PCI_FUNC(dev->devfn), &find->func); ret = 0; break; } case PCIDEV_IOCTL_READ_CONFIG_BYTE: case PCIDEV_IOCTL_READ_CONFIG_WORD: case PCIDEV_IOCTL_READ_CONFIG_DWORD: { struct pcidev_io_struct *io; unsigned long address, value; if (!pcidev->dev) return -EIO; if (!access_ok(VERIFY_WRITE, (void *)arg, sizeof(struct pcidev_io_struct))) return -EFAULT; io = (struct pcidev_io_struct *)arg; __get_user(address, &io->address); __put_user(-1, &io->value); printk(KERN_DEBUG "pcidev: reading config address %#x\n", (int)address); switch(cmd) { case PCIDEV_IOCTL_READ_CONFIG_BYTE: ret = pci_read_config_byte(pcidev->dev, address, (u8 *)&value); break; case PCIDEV_IOCTL_READ_CONFIG_WORD: ret = pci_read_config_word(pcidev->dev, address, (u16 *)&value); break; case PCIDEV_IOCTL_READ_CONFIG_DWORD: ret = pci_read_config_dword(pcidev->dev, address, (u32 *)&value); break; } if (ret < 0) return ret; __put_user(value, &io->value); break; } case PCIDEV_IOCTL_WRITE_CONFIG_BYTE: case PCIDEV_IOCTL_WRITE_CONFIG_WORD: case PCIDEV_IOCTL_WRITE_CONFIG_DWORD: { struct pcidev_io_struct *io; unsigned long address, value; if (!pcidev->dev) return -EIO; if (!access_ok(VERIFY_READ, (void *)arg, sizeof(struct pcidev_io_struct))) return -EFAULT; io = (struct pcidev_io_struct *)arg; __get_user(address, &io->address); __get_user(value, &io->value); /* * Next tests prevent the pcidev user from remapping * the PCI host device since this could cause great * trouble because we don't own those I/O resources. * If the pcidev wants to remap a device he needs to * emulate the mapping himself and not bother the host * kernel about it. */ if (address == PCI_INTERRUPT_PIN) { printk(KERN_WARNING "pcidev: not allowed to set irq pin!\n"); return -EIO; } if (address == PCI_INTERRUPT_LINE) { printk(KERN_WARNING "pcidev: not allowed to set irq line!\n"); return -EIO; } if (PCI_BASE_ADDRESS_0 <= address && (address & ~3UL) <= PCI_BASE_ADDRESS_5) { printk(KERN_WARNING "pcidev: now allowed to change base address %d\n", (int)((address & ~3UL) - PCI_BASE_ADDRESS_0) / 4); return -EIO; } printk(KERN_DEBUG "pcidev: writing config address %#x\n", (int)address); switch(cmd) { case PCIDEV_IOCTL_WRITE_CONFIG_BYTE: ret = pci_write_config_byte(pcidev->dev, address, (u8)value); break; case PCIDEV_IOCTL_WRITE_CONFIG_WORD: ret = pci_write_config_word(pcidev->dev, address, (u16)value); break; case PCIDEV_IOCTL_WRITE_CONFIG_DWORD: ret = pci_write_config_dword(pcidev->dev, address, (u32)value); break; } break; } case PCIDEV_IOCTL_INTERRUPT: { u8 irq; if (!pcidev->dev) return -EIO; ret = pci_read_config_byte(pcidev->dev, PCI_INTERRUPT_PIN, &irq); if (ret < 0) break; if (!irq) return -EIO; ret = pci_read_config_byte(pcidev->dev, PCI_INTERRUPT_LINE, &irq); if (ret < 0) break; if (arg & 1) { pcidev->pid = current->pid; // our dev_id printk(KERN_INFO "pcidev: enabling IRQ %d\n", irq); ret = request_irq(irq, pcidev_irqhandler, SA_SHIRQ, pcidev_name, (void *)current->pid); } else { if (!pcidev->pid) return -EIO; printk(KERN_INFO "pcidev: disabling IRQ %d\n", irq); free_irq(irq, (void *)pcidev->pid); pcidev->pid = 0; ret = 0; } break; } /* * Next ioctl is only for testing purposes. */ case PCIDEV_IOCTL_INTERRUPT_TEST: { ret = -EIO; if (!pcidev->dev) break; if (!pcidev->pid) break; if (pcidev->irq_timer.function) del_timer_sync(&pcidev->irq_timer); pcidev->irq_timer.function = NULL; if (arg & 1) { init_timer(&pcidev->irq_timer); pcidev->irq_timer.function = irq_test_timer; pcidev->irq_timer.data = (unsigned long)pcidev; pcidev->irq_timer.expires = jiffies + HZ; add_timer(&pcidev->irq_timer); } ret = 0; break; } case PCIDEV_IOCTL_READ_IO_BYTE: case PCIDEV_IOCTL_READ_IO_WORD: case PCIDEV_IOCTL_READ_IO_DWORD: { /* * We should probably check access rights against * the PCI resource list... but who cares for a * security hole more or less :) */ struct pcidev_io_struct *io; unsigned long address, value = -1; if (!access_ok(VERIFY_WRITE, (void *)arg, sizeof(struct pcidev_io_struct))) return -EFAULT; io = (struct pcidev_io_struct *)arg; __get_user(address, &io->address); printk(KERN_DEBUG "pcidev: reading I/O port %#x\n", (int)address); switch(cmd) { case PCIDEV_IOCTL_READ_IO_BYTE: value = inb(address); break; case PCIDEV_IOCTL_READ_IO_WORD: value = inw(address); break; case PCIDEV_IOCTL_READ_IO_DWORD: value = inl(address); break; } __put_user(value, &io->value); ret = 0; break; } case PCIDEV_IOCTL_WRITE_IO_BYTE: case PCIDEV_IOCTL_WRITE_IO_WORD: case PCIDEV_IOCTL_WRITE_IO_DWORD: { struct pcidev_io_struct *io; unsigned long address, value; if (!access_ok(VERIFY_READ, (void *)arg, sizeof(struct pcidev_io_struct))) return -EFAULT; io = (struct pcidev_io_struct *)arg; __get_user(address, &io->address); __get_user(value, &io->value); printk(KERN_DEBUG "pcidev: writing I/O port %#x\n", (int)address); switch(cmd) { case PCIDEV_IOCTL_WRITE_IO_BYTE: outb(value, address); break; case PCIDEV_IOCTL_WRITE_IO_WORD: outw(value, address); break; case PCIDEV_IOCTL_WRITE_IO_DWORD: outl(value, address); break; } ret = 0; break; } case PCIDEV_IOCTL_READ_MEM_BYTE: case PCIDEV_IOCTL_READ_MEM_WORD: case PCIDEV_IOCTL_READ_MEM_DWORD: { struct pcidev_io_struct *io; unsigned long address, value = -1; if (!access_ok(VERIFY_WRITE, (void *)arg, sizeof(struct pcidev_io_struct))) return -EFAULT; io = (struct pcidev_io_struct *)arg; __get_user(address, &io->address); printk(KERN_DEBUG "pcidev: reading memory %#x\n", (int)address); switch(cmd) { case PCIDEV_IOCTL_READ_MEM_BYTE: value = readb((unsigned char *)address); break; case PCIDEV_IOCTL_READ_MEM_WORD: value = readw((unsigned short *)address); break; case PCIDEV_IOCTL_READ_MEM_DWORD: value = readl((unsigned int *)address); break; } __put_user(value, &io->value); ret = 0; break; } case PCIDEV_IOCTL_WRITE_MEM_BYTE: case PCIDEV_IOCTL_WRITE_MEM_WORD: case PCIDEV_IOCTL_WRITE_MEM_DWORD: { struct pcidev_io_struct *io; unsigned long address, value; if (!access_ok(VERIFY_READ, (void *)arg, sizeof(struct pcidev_io_struct))) return -EFAULT; io = (struct pcidev_io_struct *)arg; __get_user(address, &io->address); __get_user(value, &io->value); printk(KERN_DEBUG "pcidev: writing memory %#x\n", (int)address); switch(cmd) { case PCIDEV_IOCTL_WRITE_MEM_BYTE: writeb(value, (unsigned char *)address); break; case PCIDEV_IOCTL_WRITE_MEM_WORD: writew(value, (unsigned short *)address); break; case PCIDEV_IOCTL_WRITE_MEM_DWORD: writel(value, (unsigned int *)address); break; } ret = 0; break; } case PCIDEV_IOCTL_PROBE_CONFIG_DWORD: { /* * This ioctl allows for probing a config space value. * This can be used for base address size probing */ struct pcidev_io_struct *io; unsigned long address, value, orig_value; if (!pcidev->dev) return -EIO; if (!access_ok(VERIFY_WRITE, (void *)arg, sizeof(struct pcidev_io_struct))) return -EFAULT; io = (struct pcidev_io_struct *)arg; __get_user(address, &io->address); __get_user(value, &io->value); __put_user(-1, &io->value); printk(KERN_INFO "pcidev: probing config space address: %#x\n", (int)address); ret = pci_read_config_dword(pcidev->dev, address, (u32 *)&orig_value); if (ret < 0) break; pci_write_config_dword(pcidev->dev, address, (u32)value); pci_read_config_dword(pcidev->dev, address, (u32 *)&value); ret = pci_write_config_dword(pcidev->dev, address, (u32)orig_value); if (ret < 0) break; __put_user(value, &io->value); break; } default: ret = -ENOTTY; } return ret; }
static int __devinit EvtDevicePrepareHardware(struct pci_dev *pdev, const struct pci_device_id *ent) { int ret = -EIO; u16 subVender; u16 uModel; //will contain galil model number (e.g. 0x1802) long resourceStart, resourceEnd, resourceLen; char name[10]; //will contain name in /dev/ (e.g. galilpci0) device++; //incremented each time be find a galil board if (device >= MAX_DEVICES) { printk("EvtDevicePrepareHardware This driver only supports %i devices\n", MAX_DEVICES); device--; //update the device count return -ENODEV; } if (pci_enable_device(pdev)) { //wake up the device printk("EvtDevicePrepareHardware Not possible to enable PCI Device\n"); device--; //update the device count return -ENODEV; } //Mark all PCI regions associated with PCI device pdev as being reserved by owner res_name. //Do not access any address inside the PCI regions unless this call returns successfully. //This will reverve both i/o ports and memory regions, and shows up in /proc/ioports and /proc/iomem if (pci_request_regions(pdev, GALILNAME)) { printk("EvtDevicePrepareHardware I/O address (0x%04x) already in use\n", (unsigned int) d[device].baseAddress); device--; //update the device count return -ENODEV; } //I/O ADDRESSES d[device].baseAddress = pci_resource_start(pdev, /*BAR*/ 2); //get base address N from BAR2 d[device].irqAddress = pci_resource_start(pdev, /*BAR*/ 1); //get base address N from BAR2. 0 on 18x0/2. Non zero on 18x2. resourceStart = pci_resource_start(pdev, /*BAR*/ 0); if ( resourceStart == 0x0000 ) { printk("No data record channel\n"); resourceEnd = 0; resourceLen = 0; } else { resourceEnd = pci_resource_end(pdev, /*BAR*/ 0); resourceLen = resourceEnd-resourceStart+1; } printk("Bar 0 address: 0x%X to 0x%X, len=%i\n", resourceStart, resourceEnd, resourceLen); if ( resourceLen == 128 ) { // d[device].recordAddress = pci_iomap(pdev, /*BAR*/ 0, 128 /*bytes*/); d[device].pciInfo.m_fRevsion = REV1; // PLX based device d[device].recordAddress = resourceStart; printk("PLX based controller - not supported\n"); device--; //update the device count return -ENODEV; } else if ( resourceLen == 512 ) { d[device].pciInfo.m_fRevsion = REV2; // XININX based device d[device].recordAddress = pci_iomap(pdev, 0, 512); printk("XINUNX based controller\n"); } if (d[device].baseAddress == 0x0000) { //check base address. printk("EvtDevicePrepareHardware No Main I/O-Address for device detected\n"); ret = -ENODEV; goto release_regions; } printk("Base Address: 0x%X\n", d[device].baseAddress); printk("Record Address: 0x%X\n", d[device].recordAddress); // Identify PCI device pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subVender); //read galil model (e.g. 0x1806) pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &uModel); //read galil model (e.g. 0x1806) d[device].pciInfo.m_fSubVendor = subVender; d[device].pciInfo.m_fSubSystem = uModel; //register the device under major number 10. Minor number will show up in /proc/misc d[device].galilpci_miscdev.minor = MISC_DYNAMIC_MINOR, //assign the minor number dynamically (ask for a free one). This field will eventually contain the actual minor number. sprintf(name, GALILNAME "%i", device); d[device].galilpci_miscdev.name = name, //the name for this device, meant for human consumption: users will find the name in the /proc/misc file. d[device].galilpci_miscdev.fops = &galilpci_fops, //the file operations d[device].bOpen = 0; //file not open ret = misc_register(&(d[device].galilpci_miscdev)); if (ret) { printk ("EvtDevicePrepareHardware cannot register miscdev (err=%d)\n", ret); goto release_regions; } init_waitqueue_head(&d[device].sleepQ); //INTERRUPTS d[device].interrupt = pdev->irq; //store the IRQ number so we can call free-irq in the cleanup function when the module us removed with rmmod if (request_irq(d[device].interrupt, EvtInterruptIsr, IRQF_SHARED, GALILNAME, &d[device])) //register the interrupt handler. This should happen before we enable interrupts on the controller. Kernel 2.6.18 2006Sep changed SA_SHIRQ to IRQF_SHARED http://lwn.net/Articles/2.6-kernel-api/ { printk("EvtDevicePrepareHardware IRQ %x is not free\n", d[device].interrupt); goto misc_deregister; } init_waitqueue_head(&d[device].interruptWaitQ); //initialize the list of processes waiting for EI/UI interrupts d[device].interruptQ.in = d[device].interruptQ.out = 0; //initialize circular buffer pointers init_waitqueue_head(&d[device].recordWaitQ); //initialize the list of processes waiting for record interrupts d[device].recordQ.in = d[device].recordQ.out = 0; //initialize circular buffer pointers //ENABLE INTERRUPTS ON CONTROLLER #if 1 switch (d[device].pciInfo.m_fSubSystem) { case DMC18x2: inb( d[device].baseAddress + 1); //reset 4701 ("clear FIFOs"). Interrupts won't enable on 18x2 rev F without this (rev D1 doesn't require it) outb(0x01, d[device].baseAddress + 1); outb(0x80, d[device].baseAddress + 1); outb(0x01, d[device].baseAddress + 1); outb(0x80, d[device].baseAddress + 1); inb( d[device].baseAddress + 1); outb(0x02, d[device].baseAddress + 1); //set 4701 pointer register to point to the interrupt mask register (register 2) outb(0x04, d[device].baseAddress + 1); //interrupt when the controller writes to its mailbox (don't interrupt on 6 full, 5 empty, 4 almost full, 3 almost empty, 1 byte detect, nor 0 parity/frame error //below is necessary so 18x2 doesn't keep interrupting outb(0x06, d[device].baseAddress + 1); //set 4701 pointer register to point to the other port's mailbox inb ( d[device].baseAddress + 1); //read other port's mailbox (clears any pending mailbox interrupt) d[device].irqAddress += 0x4c; //76 byte offset from the address in BAR1 outl( 0x40 | inl(d[device].irqAddress), d[device].irqAddress); //enable interrupts on the controller. They will stay enabled until the module is unloaded (or power is shut off) break; case DMC18x6: case DMC18x0: outb(0x40 | inb(d[device].baseAddress + 4), d[device].baseAddress + 4); //enable interrupts on the controller. They will stay enabled until the module is unloaded (or power is shut off) break; case DMC1417: d[device].irqAddress += 0x4c; outb(0x40 | inb(d[device].irqAddress), d[device].irqAddress); //enable interrupts on the controller. They will stay enabled until the module is unloaded (or power is shut off) break; case DMC1640: default: ; }; #else if(d[device].irqAddress) //18x2 { inb( d[device].baseAddress + 1); //reset 4701 ("clear FIFOs"). Interrupts won't enable on 18x2 rev F without this (rev D1 doesn't require it) outb(0x01, d[device].baseAddress + 1); outb(0x80, d[device].baseAddress + 1); outb(0x01, d[device].baseAddress + 1); outb(0x80, d[device].baseAddress + 1); inb( d[device].baseAddress + 1); outb(0x02, d[device].baseAddress + 1); //set 4701 pointer register to point to the interrupt mask register (register 2) outb(0x04, d[device].baseAddress + 1); //interrupt when the controller writes to its mailbox (don't interrupt on 6 full, 5 empty, 4 almost full, 3 almost empty, 1 byte detect, nor 0 parity/frame error //below is necessary so 18x2 doesn't keep interrupting outb(0x06, d[device].baseAddress + 1); //set 4701 pointer register to point to the other port's mailbox inb ( d[device].baseAddress + 1); //read other port's mailbox (clears any pending mailbox interrupt) d[device].irqAddress += 0x4c; //76 byte offset from the address in BAR1 outl( 0x40 | inl(d[device].irqAddress), d[device].irqAddress); //enable interrupts on the controller. They will stay enabled until the module is unloaded (or power is shut off) } else //18x6 outb(0x40 | inb(d[device].baseAddress + 4), d[device].baseAddress + 4); //enable interrupts on the controller. They will stay enabled until the module is unloaded (or power is shut off) #endif printk("EvtDevicePrepareHardware I/O address (0x%lx), Model %x, minor number %d Rev(%i)\n", d[device].baseAddress, uModel, d[device].galilpci_miscdev.minor, d[device].pciInfo.m_fRevsion); return 0; misc_deregister: misc_deregister(&(d[device].galilpci_miscdev)); //unregister the device with major number 10 release_regions: pci_release_regions(pdev); disable_device: pci_disable_device(pdev); device--; //update the device count return ret; }
static void quirk_system_pci_resources(struct pnp_dev *dev) { struct pci_dev *pdev = NULL; struct resource *res; resource_size_t pnp_start, pnp_end, pci_start, pci_end; int i, j; /* * Some BIOSes have PNP motherboard devices with resources that * partially overlap PCI BARs. The PNP system driver claims these * motherboard resources, which prevents the normal PCI driver from * requesting them later. * * This patch disables the PNP resources that conflict with PCI BARs * so they won't be claimed by the PNP system driver. */ for_each_pci_dev(pdev) { for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { if (!(pci_resource_flags(pdev, i) & IORESOURCE_MEM) || pci_resource_len(pdev, i) == 0) continue; pci_start = pci_resource_start(pdev, i); pci_end = pci_resource_end(pdev, i); for (j = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, j)); j++) { if (res->flags & IORESOURCE_UNSET || (res->start == 0 && res->end == 0)) continue; pnp_start = res->start; pnp_end = res->end; /* * If the PNP region doesn't overlap the PCI * region at all, there's no problem. */ if (pnp_end < pci_start || pnp_start > pci_end) continue; /* * If the PNP region completely encloses (or is * at least as large as) the PCI region, that's * also OK. For example, this happens when the * PNP device describes a bridge with PCI * behind it. */ if (pnp_start <= pci_start && pnp_end >= pci_end) continue; /* * Otherwise, the PNP region overlaps *part* of * the PCI region, and that might prevent a PCI * driver from requesting its resources. */ dev_warn(&dev->dev, "mem resource " "(0x%llx-0x%llx) overlaps %s BAR %d " "(0x%llx-0x%llx), disabling\n", (unsigned long long) pnp_start, (unsigned long long) pnp_end, pci_name(pdev), i, (unsigned long long) pci_start, (unsigned long long) pci_end); res->flags |= IORESOURCE_DISABLED; } } } }
/* Get framebuffer memory from Hyper-V video pci space */ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info) { struct hvfb_par *par = info->par; struct pci_dev *pdev = NULL; void __iomem *fb_virt; int gen2vm = efi_enabled(EFI_BOOT); resource_size_t pot_start, pot_end; int ret; if (gen2vm) { pot_start = 0; pot_end = -1; } else { pdev = pci_get_device(PCI_VENDOR_ID_MICROSOFT, PCI_DEVICE_ID_HYPERV_VIDEO, NULL); if (!pdev) { pr_err("Unable to find PCI Hyper-V video\n"); return -ENODEV; } if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) || pci_resource_len(pdev, 0) < screen_fb_size) goto err1; pot_end = pci_resource_end(pdev, 0); pot_start = pot_end - screen_fb_size + 1; } ret = vmbus_allocate_mmio(&par->mem, hdev, pot_start, pot_end, screen_fb_size, 0x100000, true); if (ret != 0) { pr_err("Unable to allocate framebuffer memory\n"); goto err1; } fb_virt = ioremap(par->mem->start, screen_fb_size); if (!fb_virt) goto err2; info->apertures = alloc_apertures(1); if (!info->apertures) goto err3; if (gen2vm) { info->apertures->ranges[0].base = screen_info.lfb_base; info->apertures->ranges[0].size = screen_info.lfb_size; remove_conflicting_framebuffers(info->apertures, KBUILD_MODNAME, false); } else { info->apertures->ranges[0].base = pci_resource_start(pdev, 0); info->apertures->ranges[0].size = pci_resource_len(pdev, 0); } info->fix.smem_start = par->mem->start; info->fix.smem_len = screen_fb_size; info->screen_base = fb_virt; info->screen_size = screen_fb_size; if (!gen2vm) pci_dev_put(pdev); return 0; err3: iounmap(fb_virt); err2: vmbus_free_mmio(par->mem->start, screen_fb_size); par->mem = NULL; err1: if (!gen2vm) pci_dev_put(pdev); return -ENOMEM; }
static void print_bar_info(struct pci_dev* device) { unsigned int flags = 0; unsigned int i = 0; for(i = 0; i < 6; i++) { flags = pci_resource_flags(device, i); if(!flags) printk(KERN_INFO ANB_DEVICE_PREFIX "Device BAR %d: not in use\n", i); else { printk(KERN_INFO ANB_DEVICE_PREFIX "Device BAR %d: %10d bytes (0x%08x ~ 0x%08x) Type: %3s P %c RO %c C %c RL%c SH%c\n", i, (unsigned int)pci_resource_len(device, i), (unsigned int)pci_resource_start(device, i), (unsigned int)pci_resource_end(device, i), ((flags & IORESOURCE_IO) == IORESOURCE_IO) ? "IO" : ((flags & IORESOURCE_MEM) == IORESOURCE_MEM) ? "MEM" : "---", ((flags & IORESOURCE_PREFETCH) == IORESOURCE_PREFETCH) ? '+' : '-', ((flags & IORESOURCE_READONLY) == IORESOURCE_READONLY) ? '+' : '-', ((flags & IORESOURCE_CACHEABLE) == IORESOURCE_CACHEABLE) ? '+' : '-', ((flags & IORESOURCE_RANGELENGTH) == IORESOURCE_RANGELENGTH) ? '+' : '-', ((flags & IORESOURCE_SHADOWABLE) == IORESOURCE_SHADOWABLE) ? '+' : '-'); printk(KERN_INFO ANB_DEVICE_PREFIX " ASz%c ASt%c M64%c W %c M %c\n", ((flags & IORESOURCE_SIZEALIGN) == IORESOURCE_SIZEALIGN) ? '+' : '-', ((flags & IORESOURCE_STARTALIGN) == IORESOURCE_STARTALIGN) ? '+' : '-', ((flags & IORESOURCE_MEM_64) == IORESOURCE_MEM_64) ? '+' : '-', ((flags & IORESOURCE_WINDOW) == IORESOURCE_WINDOW) ? '+' : '-', ((flags & IORESOURCE_MUXED) == IORESOURCE_MUXED) ? '+' : '-'); printk(KERN_INFO ANB_DEVICE_PREFIX " Ex %c Dis%c U %c A %c B %c\n", ((flags & IORESOURCE_EXCLUSIVE) == IORESOURCE_EXCLUSIVE) ? '+' : '-', ((flags & IORESOURCE_DISABLED) == IORESOURCE_DISABLED) ? '+' : '-', ((flags & IORESOURCE_UNSET) == IORESOURCE_UNSET) ? '+' : '-', ((flags & IORESOURCE_AUTO) == IORESOURCE_AUTO) ? '+' : '-', ((flags & IORESOURCE_BUSY) == IORESOURCE_BUSY) ? '+' : '-'); } } }
/* Get framebuffer memory from Hyper-V video pci space */ static int hvfb_getmem(struct fb_info *info) { struct hvfb_par *par = info->par; struct pci_dev *pdev = NULL; void __iomem *fb_virt; int gen2vm = efi_enabled(EFI_BOOT); int ret; par->mem.name = KBUILD_MODNAME; par->mem.flags = IORESOURCE_MEM | IORESOURCE_BUSY; if (gen2vm) { ret = allocate_resource(&hyperv_mmio, &par->mem, screen_fb_size, 0, -1, screen_fb_size, NULL, NULL); if (ret != 0) { pr_err("Unable to allocate framebuffer memory\n"); return -ENODEV; } } else { pdev = pci_get_device(PCI_VENDOR_ID_MICROSOFT, PCI_DEVICE_ID_HYPERV_VIDEO, NULL); if (!pdev) { pr_err("Unable to find PCI Hyper-V video\n"); return -ENODEV; } if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) || pci_resource_len(pdev, 0) < screen_fb_size) goto err1; par->mem.end = pci_resource_end(pdev, 0); par->mem.start = par->mem.end - screen_fb_size + 1; ret = request_resource(&pdev->resource[0], &par->mem); if (ret != 0) { pr_err("Unable to request framebuffer memory\n"); goto err1; } } fb_virt = ioremap(par->mem.start, screen_fb_size); if (!fb_virt) goto err2; info->apertures = alloc_apertures(1); if (!info->apertures) goto err3; if (gen2vm) { info->apertures->ranges[0].base = screen_info.lfb_base; info->apertures->ranges[0].size = screen_info.lfb_size; remove_conflicting_framebuffers(info->apertures, KBUILD_MODNAME, false); } else { info->apertures->ranges[0].base = pci_resource_start(pdev, 0); info->apertures->ranges[0].size = pci_resource_len(pdev, 0); } info->fix.smem_start = par->mem.start; info->fix.smem_len = screen_fb_size; info->screen_base = fb_virt; info->screen_size = screen_fb_size; if (!gen2vm) pci_dev_put(pdev); return 0; err3: iounmap(fb_virt); err2: release_resource(&par->mem); err1: if (!gen2vm) pci_dev_put(pdev); return -ENOMEM; }
/** * This function is called by the PCI core when it has a struct pci_dev that it * thinks the driver wants to control. It will allocate the memory for the struct * alt_up_pci_dev, initialize it correctly and dynamically allocate a character * device node. * * @param[in] dev The pointer to the pci device that evokes the probe function. * @param[in] id The pci_id_table of the driver. * * @return Return 0 on success. */ static int __devinit alt_up_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) { int i, retval = 0; // allocate the memory for the struct alt_up_pci_dev struct alt_up_pci_dev *mydev = kmalloc( sizeof(struct alt_up_pci_dev), GFP_KERNEL ); if (mydev == NULL){ printk(KERN_DEBUG "kmalloc() memory for struct alt_up_pci_dev failed. \n"); goto err_alloc_dev; } // save the pointers for the future usage pci_set_drvdata(dev, (void *)mydev); mydev->pci_dev = dev; // wake up the device retval = pci_enable_device(dev); if (retval) { printk(KERN_DEBUG "pci_enable_device() failed. \n"); goto err_enable_device; } // enables bus-mastering for device dev pci_set_master(dev); // reserved PCI I/O and memory resources retval = pci_request_regions(dev, DRV_NAME); if (retval) { printk(KERN_DEBUG "pci_request_regions() failed. \n"); goto err_request_regions; } // set the DMA addressing limitation retval = pci_set_dma_mask(dev, DMA_BIT_MASK( pci_dma_bit_range )); if (retval) { printk(KERN_DEBUG "pci_set_dma_mask() failed. \n"); goto err_set_dma_mask; } retval = pci_set_consistent_dma_mask(dev,DMA_BIT_MASK( pci_dma_bit_range )); if(retval) { printk(KERN_DEBUG "pci_set_consistent_dma_mask() failed. \n"); goto err_set_dma_mask; } // set __iomem address, accessed by ioread, iowrite for (i = 0; i < MAX_NUM_OF_BARS; i ++) { if ( pci_resource_end(dev, i) != pci_resource_start(dev, i) ){ /* create a virtual mapping cookie for a PCI BAR, * second arg is BAR, third is maxlen (0 means complete BAR) */ mydev->bar[i] = pci_iomap(dev, i, 0); if( !mydev->bar[i] ){ printk(KERN_DEBUG "pci_iomap() failed. \n"); goto err_iomap; } printk(KERN_DEBUG DRV_NAME " BAR%d initialized.\n", i); mydev->bar_size[i] = pci_resource_end(dev, i) - pci_resource_start(dev, i) + 1; } else mydev->bar[i] = NULL; } // initialize the alt_up_pci_dev struct retval = alt_up_pci_dev_init(mydev); if(retval) { printk(KERN_DEBUG "alt_up_pci_dev_init() failed. \n"); goto err_dev_init; } // have MSI enabled on its device function retval = pci_enable_msi(dev); if (retval) { printk(KERN_DEBUG "pci_enable_msi() failed. \n"); goto err_enable_msi; } // request irq line for interrupt mydev->irq_line = dev->irq; retval = request_irq((int)mydev->irq_line, (void*)alt_up_pci_irqhandler, IRQF_SHARED, DRV_NAME, (void *)mydev); if (retval) { printk(KERN_DEBUG "pci_request_irq() failed. \n"); goto err_request_irq; } // write irq_line to the PCI configuration space retval = pci_write_config_byte(dev, PCI_INTERRUPT_LINE, mydev->irq_line); if (retval) { printk(KERN_DEBUG "pci_read_config() failed. \n"); goto err_write_config; } /* dynamically allocate a character device node * 0 : requested minor * 1 : count */ retval = alloc_chrdev_region(&mydev->cdev_no, 0, 1, DRV_NAME); if(retval) { printk(KERN_DEBUG "alloc_chrdev_region() failed. \n"); goto err_alloc_chrdev; } // init the cdev cdev_init(&mydev->cdev, &alt_up_pci_fops); mydev->cdev.owner = THIS_MODULE; mydev->cdev.ops = &alt_up_pci_fops; // add the cdev to kernel, from now on, the driver is alive retval = cdev_add(&mydev->cdev, mydev->cdev_no, 1); /* 1: count */ if(retval) { printk(KERN_DEBUG "cdev_add() failed. \n"); goto err_cdev_add; } return 0; //cdev_del(&mydev->cdev); err_cdev_add: unregister_chrdev_region(mydev->cdev_no, 1); err_alloc_chrdev: err_write_config: free_irq(mydev->irq_line, (void *)mydev); err_request_irq: pci_disable_msi(dev); err_enable_msi: alt_up_pci_dev_exit(mydev); err_dev_init: for (i = 0; i < MAX_NUM_OF_BARS; i ++) { if( mydev->bar[i] != NULL ) pci_iounmap(dev, mydev->bar[i]); } goto err_set_dma_mask; err_iomap: for ( i = i - 1; i >= 0; i --){ if( mydev->bar[i] != NULL) pci_iounmap(dev, mydev->bar[i]); } err_set_dma_mask: pci_release_regions(dev); err_request_regions: pci_disable_device(dev); err_enable_device: kfree(mydev); err_alloc_dev: printk("alt_up_pci_probe() failed with error: %d \n ", retval); return retval; }
/* A board has been found, initialize it. */ static struct dgnc_board *dgnc_found_board(struct pci_dev *pdev, int id) { struct dgnc_board *brd; unsigned int pci_irq; int i = 0; int rc = 0; brd = kzalloc(sizeof(*brd), GFP_KERNEL); if (!brd) return ERR_PTR(-ENOMEM); /* store the info for the board we've found */ brd->boardnum = dgnc_num_boards; brd->vendor = dgnc_pci_tbl[id].vendor; brd->device = dgnc_pci_tbl[id].device; brd->pdev = pdev; brd->pci_bus = pdev->bus->number; brd->pci_slot = PCI_SLOT(pdev->devfn); brd->name = dgnc_ids[id].name; brd->maxports = dgnc_ids[id].maxports; if (dgnc_ids[i].is_pci_express) brd->bd_flags |= BD_IS_PCI_EXPRESS; brd->dpastatus = BD_NOFEP; init_waitqueue_head(&brd->state_wait); spin_lock_init(&brd->bd_lock); spin_lock_init(&brd->bd_intr_lock); brd->state = BOARD_FOUND; /* store which card & revision we have */ pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &brd->subvendor); pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &brd->subdevice); pci_read_config_byte(pdev, PCI_REVISION_ID, &brd->rev); pci_irq = pdev->irq; brd->irq = pci_irq; switch (brd->device) { case PCI_DEVICE_CLASSIC_4_DID: case PCI_DEVICE_CLASSIC_8_DID: case PCI_DEVICE_CLASSIC_4_422_DID: case PCI_DEVICE_CLASSIC_8_422_DID: brd->dpatype = T_CLASSIC | T_PCIBUS; /* * For PCI ClassicBoards * PCI Local Address (i.e. "resource" number) space * 0 PLX Memory Mapped Config * 1 PLX I/O Mapped Config * 2 I/O Mapped UARTs and Status * 3 Memory Mapped VPD * 4 Memory Mapped UARTs and Status */ brd->membase = pci_resource_start(pdev, 4); if (!brd->membase) { dev_err(&brd->pdev->dev, "Card has no PCI IO resources, failing.\n"); rc = -ENODEV; goto failed; } brd->membase_end = pci_resource_end(pdev, 4); if (brd->membase & 1) brd->membase &= ~3; else brd->membase &= ~15; brd->iobase = pci_resource_start(pdev, 1); brd->iobase_end = pci_resource_end(pdev, 1); brd->iobase = ((unsigned int)(brd->iobase)) & 0xFFFE; brd->bd_ops = &dgnc_cls_ops; brd->bd_uart_offset = 0x8; brd->bd_dividend = 921600; rc = dgnc_do_remap(brd); if (rc < 0) goto failed; /* Get and store the board VPD, if it exists */ brd->bd_ops->vpd(brd); /* * Enable Local Interrupt 1 (0x1), * Local Interrupt 1 Polarity Active high (0x2), * Enable PCI interrupt (0x40) */ outb(0x43, brd->iobase + 0x4c); break; case PCI_DEVICE_NEO_4_DID: case PCI_DEVICE_NEO_8_DID: case PCI_DEVICE_NEO_2DB9_DID: case PCI_DEVICE_NEO_2DB9PRI_DID: case PCI_DEVICE_NEO_2RJ45_DID: case PCI_DEVICE_NEO_2RJ45PRI_DID: case PCI_DEVICE_NEO_1_422_DID: case PCI_DEVICE_NEO_1_422_485_DID: case PCI_DEVICE_NEO_2_422_485_DID: case PCI_DEVICE_NEO_EXPRESS_8_DID: case PCI_DEVICE_NEO_EXPRESS_4_DID: case PCI_DEVICE_NEO_EXPRESS_4RJ45_DID: case PCI_DEVICE_NEO_EXPRESS_8RJ45_DID: /* * This chip is set up 100% when we get to it. * No need to enable global interrupts or anything. */ if (brd->bd_flags & BD_IS_PCI_EXPRESS) brd->dpatype = T_NEO_EXPRESS | T_PCIBUS; else brd->dpatype = T_NEO | T_PCIBUS; brd->membase = pci_resource_start(pdev, 0); brd->membase_end = pci_resource_end(pdev, 0); if (brd->membase & 1) brd->membase &= ~3; else brd->membase &= ~15; brd->bd_ops = &dgnc_neo_ops; brd->bd_uart_offset = 0x200; brd->bd_dividend = 921600; rc = dgnc_do_remap(brd); if (rc < 0) goto failed; /* Read and store the dvid after remapping */ brd->dvid = readb(brd->re_map_membase + 0x8D); /* Get and store the board VPD, if it exists */ brd->bd_ops->vpd(brd); break; default: dev_err(&brd->pdev->dev, "Didn't find any compatible Neo/Classic PCI boards.\n"); rc = -ENXIO; goto failed; } tasklet_init(&brd->helper_tasklet, brd->bd_ops->tasklet, (unsigned long)brd); wake_up_interruptible(&brd->state_wait); return brd; failed: kfree(brd); return ERR_PTR(rc); }
static int dwc2_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) { struct resource res[2]; struct platform_device *dwc2; struct platform_device *phy; int ret; struct device *dev = &pci->dev; struct dwc2_pci_glue *glue; ret = pcim_enable_device(pci); if (ret) { dev_err(dev, "failed to enable pci device\n"); return -ENODEV; } pci_set_master(pci); dwc2 = platform_device_alloc("dwc2", PLATFORM_DEVID_AUTO); if (!dwc2) { dev_err(dev, "couldn't allocate dwc2 device\n"); return -ENOMEM; } memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res)); res[0].start = pci_resource_start(pci, 0); res[0].end = pci_resource_end(pci, 0); res[0].name = "dwc2"; res[0].flags = IORESOURCE_MEM; res[1].start = pci->irq; res[1].name = "dwc2"; res[1].flags = IORESOURCE_IRQ; ret = platform_device_add_resources(dwc2, res, ARRAY_SIZE(res)); if (ret) { dev_err(dev, "couldn't add resources to dwc2 device\n"); return ret; } dwc2->dev.parent = dev; phy = usb_phy_generic_register(); if (IS_ERR(phy)) { dev_err(dev, "error registering generic PHY (%ld)\n", PTR_ERR(phy)); return PTR_ERR(phy); } ret = dwc2_pci_quirks(pci, dwc2); if (ret) goto err; ret = platform_device_add(dwc2); if (ret) { dev_err(dev, "failed to register dwc2 device\n"); goto err; } glue = kzalloc(sizeof(*glue), GFP_KERNEL); if (!glue) return -ENOMEM; glue->phy = phy; glue->dwc2 = dwc2; pci_set_drvdata(pci, glue); return 0; err: usb_phy_generic_unregister(phy); platform_device_put(dwc2); return ret; }
static int __devinit atomisp_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct atomisp_device *isp = NULL; unsigned int start, len; void __iomem *base = NULL; int err = 0; if (!dev) { v4l2_err(&atomisp_dev, "atomisp: erorr device ptr\n"); return -EINVAL; } atomisp_pci_vendor = id->vendor; atomisp_pci_device = id->device; err = pci_enable_device(dev); if (err) { v4l2_err(&atomisp_dev, "Failed to enable CI ISP device\n"); return err; } start = pci_resource_start(dev, 0); len = pci_resource_len(dev, 0); err = pci_request_region(dev, 0, atomisp_pci_driver.name); if (err) { v4l2_err(&atomisp_dev, "Failed to request region 0x%1x-0x%Lx\n", start, (unsigned long long)pci_resource_end(dev, 0)); goto request_region_fail; } base = ioremap_nocache(start, len); if (!base) { v4l2_err(&atomisp_dev, "Failed to I/O memory remapping\n"); err = -ENOMEM; goto ioremap_fail; } isp = kzalloc(sizeof(struct atomisp_device), GFP_KERNEL); if (!isp) { v4l2_err(&atomisp_dev, "Failed to alloc CI ISP structure\n"); goto kzalloc_fail; } isp->sw_contex.probed = false; isp->sw_contex.init = false; isp->pdev = dev; isp->dev = &dev->dev; isp->sw_contex.power_state = ATOM_ISP_POWER_UP; isp->hw_contex.pci_root = pci_get_bus_and_slot(0, 0); /* Load isp firmware from user space */ /* * fixing me: * MRFLD VP does not use firmware loading * from file system */ if (!IS_MRFLD) { isp->firmware = load_firmware(&dev->dev); if (!isp->firmware) { v4l2_err(&atomisp_dev, "Load firmwares failed\n"); goto load_fw_fail; } } err = atomisp_initialize_modules(isp); if (err < 0) { v4l2_err(&atomisp_dev, "atomisp_initialize_modules\n"); goto init_mod_fail; } err = atomisp_register_entities(isp); if (err < 0) { v4l2_err(&atomisp_dev, "atomisp_register_entities failed\n"); goto init_mod_fail; } init_completion(&isp->wq_frame_complete); init_completion(&isp->dis_state_complete); spin_lock_init(&isp->irq_lock); isp->work_queue = create_singlethread_workqueue(isp->v4l2_dev.name); if (isp->work_queue == NULL) { v4l2_err(&atomisp_dev, "Failed to initialize work queue\n"); goto work_queue_fail; } INIT_WORK(&isp->work, atomisp_work); isp->hw_contex.ispmmadr = start; pci_set_master(dev); atomisp_io_base = base; isp->tvnorm = tvnorms; mutex_init(&isp->input_lock); /* isp_lock is to protect race access of css functions */ mutex_init(&isp->isp_lock); isp->sw_contex.updating_uptr = false; isp->isp3a_stat_ready = false; pci_set_drvdata(dev, isp); err = pci_enable_msi(dev); if (err) { v4l2_err(&atomisp_dev, "Failed to enable msi\n"); goto enable_msi_fail; } err = request_irq(dev->irq, atomisp_isr, IRQF_SHARED, "isp_irq", isp); if (err) { v4l2_err(&atomisp_dev, "Failed to request irq\n"); goto request_irq_fail; } setup_timer(&isp->wdt, atomisp_wdt_wakeup_dog, (unsigned long)isp); atomisp_msi_irq_init(isp, dev); pm_qos_add_request(&isp->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE); /* * fixing me! * MRFLD VP does not implement * PM Core */ #ifdef CONFIG_PM if (!IS_MRFLD) { pm_runtime_put_noidle(&dev->dev); pm_runtime_allow(&dev->dev); } #endif isp->sw_contex.probed = true; err = hmm_pool_register(repool_pgnr, HMM_POOL_TYPE_RESERVED); if (err) v4l2_err(&atomisp_dev, "Failed to register reserved memory pool.\n"); return 0; request_irq_fail: pci_disable_msi(dev); enable_msi_fail: pci_set_drvdata(dev, NULL); destroy_workqueue(isp->work_queue); work_queue_fail: atomisp_unregister_entities(isp); init_mod_fail: release_firmware(isp->firmware); load_fw_fail: kfree(isp); kzalloc_fail: iounmap(base); ioremap_fail: pci_release_region(dev, 0); request_region_fail: pci_disable_device(dev); return err; }
static int __devinit dwc3_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) { struct resource res[2]; struct platform_device *dwc3; struct dwc3_pci *glue; int ret = -ENOMEM; int devid; glue = kzalloc(sizeof(*glue), GFP_KERNEL); if (!glue) { dev_err(&pci->dev, "not enough memory\n"); goto err0; } glue->dev = &pci->dev; ret = pci_enable_device(pci); if (ret) { dev_err(&pci->dev, "failed to enable pci device\n"); goto err1; } pci_set_power_state(pci, PCI_D0); pci_set_master(pci); devid = dwc3_get_device_id(); if (devid < 0) goto err2; dwc3 = platform_device_alloc("dwc3", devid); if (!dwc3) { dev_err(&pci->dev, "couldn't allocate dwc3 device\n"); goto err3; } memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res)); res[0].start = pci_resource_start(pci, 0); res[0].end = pci_resource_end(pci, 0); res[0].name = "dwc_usb3"; res[0].flags = IORESOURCE_MEM; res[1].start = pci->irq; res[1].name = "dwc_usb3"; res[1].flags = IORESOURCE_IRQ; ret = platform_device_add_resources(dwc3, res, ARRAY_SIZE(res)); if (ret) { dev_err(&pci->dev, "couldn't add resources to dwc3 device\n"); goto err4; } pci_set_drvdata(pci, glue); dma_set_coherent_mask(&dwc3->dev, pci->dev.coherent_dma_mask); dwc3->dev.dma_mask = pci->dev.dma_mask; dwc3->dev.dma_parms = pci->dev.dma_parms; dwc3->dev.parent = &pci->dev; glue->dwc3 = dwc3; ret = platform_device_add(dwc3); if (ret) { dev_err(&pci->dev, "failed to register dwc3 device\n"); goto err4; } return 0; err4: pci_set_drvdata(pci, NULL); platform_device_put(dwc3); err3: dwc3_put_device_id(devid); err2: pci_disable_device(pci); err1: kfree(pci); err0: return ret; }
static int dwc3_haps_probe(struct pci_dev *pci, const struct pci_device_id *id) { struct dwc3_haps *dwc; struct device *dev = &pci->dev; struct resource res[2]; int ret; ret = pcim_enable_device(pci); if (ret) { dev_err(dev, "failed to enable pci device\n"); return -ENODEV; } pci_set_master(pci); dwc = devm_kzalloc(dev, sizeof(*dwc), GFP_KERNEL); if (!dwc) return -ENOMEM; dwc->dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO); if (!dwc->dwc3) return -ENOMEM; memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res)); res[0].start = pci_resource_start(pci, 0); res[0].end = pci_resource_end(pci, 0); res[0].name = "dwc_usb3"; res[0].flags = IORESOURCE_MEM; res[1].start = pci->irq; res[1].name = "dwc_usb3"; res[1].flags = IORESOURCE_IRQ; ret = platform_device_add_resources(dwc->dwc3, res, ARRAY_SIZE(res)); if (ret) { dev_err(dev, "couldn't add resources to dwc3 device\n"); goto err; } dwc->pci = pci; dwc->dwc3->dev.parent = dev; ret = platform_device_add_properties(dwc->dwc3, initial_properties); if (ret) goto err; ret = platform_device_add(dwc->dwc3); if (ret) { dev_err(dev, "failed to register dwc3 device\n"); goto err; } pci_set_drvdata(pci, dwc); return 0; err: platform_device_put(dwc->dwc3); return ret; }
/*************************************************************************/ /*! @Function OSPCIClearResourceMTRRs @Description Clear any BIOS-configured MTRRs for a PCI memory region @Input hPVRPCI PCI device handle @Input ui32Index Address range index @Return PVRSRV_ERROR Services error code */ /**************************************************************************/ PVRSRV_ERROR OSPCIClearResourceMTRRs(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index) { PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI; resource_size_t start, end; int err; start = pci_resource_start(psPVRPCI->psPCIDev, ui32Index); end = pci_resource_end(psPVRPCI->psPCIDev, ui32Index) + 1; err = mtrr_add(start, end - start, MTRR_TYPE_UNCACHABLE, 0); if (err < 0) { printk(KERN_ERR "OSPCIClearResourceMTRRs: mtrr_add failed (%d)", err); return PVRSRV_ERROR_PCI_CALL_FAILED; } err = mtrr_del(err, start, end - start); if (err < 0) { printk(KERN_ERR "OSPCIClearResourceMTRRs: mtrr_del failed (%d)", err); return PVRSRV_ERROR_PCI_CALL_FAILED; } #if 1 /* Workaround for overlapping MTRRs. */ { IMG_BOOL bGotMTRR0 = IMG_FALSE; /* Current mobo BIOSes will normally set up a WRBACK MTRR spanning * 0->4GB, and then another 4GB->6GB. If the PCI card's automatic & * overlapping UNCACHABLE MTRR is deleted, we see WRBACK behaviour. * * WRBACK is incompatible with some PCI devices, so try to split * the UNCACHABLE regions up and insert a WRCOMB region instead. */ err = mtrr_add(start, end - start, MTRR_TYPE_WRBACK, 0); if (err < 0) { /* If this fails, services has probably run before and created * a write-combined MTRR for the test chip. Assume it has, and * don't return an error here. */ return PVRSRV_OK; } if(err == 0) bGotMTRR0 = IMG_TRUE; err = mtrr_del(err, start, end - start); if(err < 0) { printk(KERN_ERR "OSPCIClearResourceMTRRs: mtrr_del failed (%d)", err); return PVRSRV_ERROR_PCI_CALL_FAILED; } if(bGotMTRR0) { /* Replace 0 with a non-overlapping WRBACK MTRR */ err = mtrr_add(0, start, MTRR_TYPE_WRBACK, 0); if(err < 0) { printk(KERN_ERR "OSPCIClearResourceMTRRs: mtrr_add failed (%d)", err); return PVRSRV_ERROR_PCI_CALL_FAILED; } /* Add a WRCOMB MTRR for the PCI device memory bar */ err = mtrr_add(start, end - start, MTRR_TYPE_WRCOMB, 0); if(err < 0) { printk(KERN_ERR "OSPCIClearResourceMTRRs: mtrr_add failed (%d)", err); return PVRSRV_ERROR_PCI_CALL_FAILED; } } } #endif return PVRSRV_OK; }
int do_setup_ddr(struct device *dev) { struct psh_ia_priv *ia_data = (struct psh_ia_priv *)dev_get_drvdata(dev); struct psh_plt_priv *plt_priv = (struct psh_plt_priv *)ia_data->platform_priv; uintptr_t ddr_phy = plt_priv->ddr_phy; uintptr_t imr2_phy = plt_priv->imr2_phy; const struct firmware *fw_entry; struct ia_cmd cmd_user = { .cmd_id = CMD_SETUP_DDR, .sensor_id = 0, }; static int fw_load_done; int load_default = 0; char fname[40]; if (fw_load_done) return 0; #ifdef VPROG2_SENSOR intel_scu_ipc_msic_vprog2(1); msleep(500); #endif again: if (!request_firmware(&fw_entry, fname, dev)) { if (!fw_entry) return -ENOMEM; psh_debug("psh fw size %d virt:0x%p\n", (int)fw_entry->size, fw_entry->data); if (fw_entry->size > APP_IMR_SIZE) { psh_err("psh fw size too big\n"); } else { struct ia_cmd cmd = { .cmd_id = CMD_RESET, .sensor_id = 0, }; memcpy(plt_priv->imr2, fw_entry->data, fw_entry->size); *(uintptr_t *)(&cmd.param) = imr2_phy; cmd.tran_id = 0x1; if (process_send_cmd(ia_data, PSH2IA_CHANNEL3, &cmd, 7)) return -1; ia_data->load_in_progress = 1; wait_for_completion_timeout(&ia_data->cmd_load_comp, 3 * HZ); fw_load_done = 1; } release_firmware(fw_entry); } else { psh_err("cannot find psh firmware(%s)\n", fname); if (!load_default) { psh_err("try to load default psh.bin\n"); snprintf(fname, 20, "psh.bin"); load_default = 1; goto again; } } ia_lbuf_read_reset(ia_data->lbuf); *(unsigned long *)(&cmd_user.param) = ddr_phy; return ia_send_cmd(ia_data, &cmd_user, 7); } static void psh2ia_channel_handle(u32 msg, u32 param, void *data) { struct pci_dev *pdev = (struct pci_dev *)data; struct psh_ia_priv *ia_data = (struct psh_ia_priv *)dev_get_drvdata(&pdev->dev); struct psh_plt_priv *plt_priv = (struct psh_plt_priv *)ia_data->platform_priv; u8 *dbuf = NULL; u16 size = 0; if (unlikely(ia_data->load_in_progress)) { ia_data->load_in_progress = 0; complete(&ia_data->cmd_load_comp); return; } while (!ia_lbuf_read_next(ia_data, &plt_priv->lbuf, &dbuf, &size)) { ia_handle_frame(ia_data, dbuf, size); } sysfs_notify(&pdev->dev.kobj, NULL, "data_size"); } static int psh_imr_init(struct pci_dev *pdev, int imr_src, uintptr_t *phy_addr, void **virt_addr, unsigned size, int bar) { struct page *pg; void __iomem *mem; int ret = 0; unsigned long start = 0, len; if (imr_src == imr_allocate) { /* dynamic alloct memory region */ pg = alloc_pages(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO, get_order(size)); if (!pg) { dev_err(&pdev->dev, "can not allocate app page imr buffer\n"); ret = -ENOMEM; goto err; } *phy_addr = page_to_phys(pg); *virt_addr = page_address(pg); } else if (imr_src == imr_pci_shim) { /* dedicate isolated memory region */ start = pci_resource_start(pdev, bar); len = pci_resource_len(pdev, bar); if (!start || !len) { dev_err(&pdev->dev, "bar %d address not set\n", bar); ret = -EINVAL; goto err; } ret = pci_request_region(pdev, bar, "psh"); if (ret) { dev_err(&pdev->dev, "failed to request psh region " "0x%lx-0x%lx\n", start, (unsigned long)pci_resource_end(pdev, bar)); goto err; } mem = ioremap_nocache(start, len); if (!mem) { dev_err(&pdev->dev, "can not ioremap app imr address\n"); ret = -EINVAL; goto err_ioremap; } *phy_addr = start; *virt_addr = (void *)mem; } else { dev_err(&pdev->dev, "Invalid chip imr source\n"); ret = -EINVAL; goto err; } return 0; err_ioremap: pci_release_region(pdev, bar); err: return ret; } static void psh_imr_free(int imr_src, void *virt_addr, unsigned size) { if (imr_src == imr_allocate) __free_pages(virt_to_page(virt_addr), get_order(size)); else if (imr_src == imr_pci_shim) iounmap((void __iomem *)virt_addr); } static int psh_probe(struct pci_dev *pdev, const struct pci_device_id *id) { int ret = -1; struct psh_ia_priv *ia_data; struct psh_plt_priv *plt_priv; ret = pci_enable_device(pdev); if (ret) { dev_err(&pdev->dev, "fail to enable psh pci device\n"); goto pci_err; } plt_priv = kzalloc(sizeof(*plt_priv), GFP_KERNEL); if (!plt_priv) { dev_err(&pdev->dev, "can not allocate plt_priv\n"); goto plt_err; } switch (intel_mid_identify_cpu()) { case INTEL_MID_CPU_CHIP_TANGIER: if (intel_mid_soc_stepping() == 0) plt_priv->imr_src = imr_allocate; else plt_priv->imr_src = imr_pci_shim; break; case INTEL_MID_CPU_CHIP_ANNIEDALE: plt_priv->imr_src = imr_pci_shim; break; default: dev_err(&pdev->dev, "error memory region\n"); goto psh_imr2_err; break; } /* init IMR2 */ ret = psh_imr_init(pdev, plt_priv->imr_src, &plt_priv->imr2_phy, &plt_priv->imr2, APP_IMR_SIZE, 0); if (ret) goto psh_imr2_err; /* init IMR3 */ ret = psh_imr_init(pdev, plt_priv->imr_src, &plt_priv->ddr_phy, &plt_priv->ddr, BUF_IA_DDR_SIZE, 1); if (ret) goto psh_ddr_err; ret = psh_ia_common_init(&pdev->dev, &ia_data); if (ret) { dev_err(&pdev->dev, "fail to init psh_ia_common\n"); goto psh_ia_err; } ia_lbuf_read_init(&plt_priv->lbuf, plt_priv->ddr, BUF_IA_DDR_SIZE, NULL); ia_data->lbuf = &plt_priv->lbuf; plt_priv->hwmon_dev = hwmon_device_register(&pdev->dev); if (!plt_priv->hwmon_dev) { dev_err(&pdev->dev, "fail to register hwmon device\n"); goto hwmon_err; } ia_data->platform_priv = plt_priv; ret = intel_psh_ipc_bind(PSH_RECV_CH0, psh2ia_channel_handle, pdev); if (ret) { dev_err(&pdev->dev, "fail to bind channel\n"); goto irq_err; } /* just put this dev into suspend status always, since this is fake */ pm_runtime_put_noidle(&pdev->dev); pm_runtime_allow(&pdev->dev); return 0; irq_err: hwmon_device_unregister(plt_priv->hwmon_dev); hwmon_err: psh_ia_common_deinit(&pdev->dev); psh_ia_err: psh_imr_free(plt_priv->imr_src, plt_priv->ddr, BUF_IA_DDR_SIZE); psh_ddr_err: psh_imr_free(plt_priv->imr_src, plt_priv->imr2, APP_IMR_SIZE); psh_imr2_err: kfree(plt_priv); plt_err: pci_dev_put(pdev); pci_err: return ret; }
static int __init c4_hdw_init (struct pci_dev *pdev, int found) { hdw_info_t *hi; int i; int fun, slot; unsigned char busno = 0xff; /* our MUSYCC chip supports two functions, 0 & 1 */ if ((fun = PCI_FUNC (pdev->devfn)) > 1) { pr_warning("unexpected devfun: 0x%x\n", pdev->devfn); return 0; } if (pdev->bus) /* obtain bus number */ busno = pdev->bus->number; else busno = 0; /* default for system PCI inconsistency */ slot = pdev->devfn & ~0x07; /* * Functions 0 & 1 for a given board (identified by same bus(busno) and * slot(slot)) are placed into the same 'hardware' structure. The first * part of the board's functionality will be placed into an unpopulated * element, identified by "slot==(0xff)". The second part of a board's * functionality will match the previously loaded slot/busno. */ for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) { /* * match with board's first found interface, otherwise this is first * found */ if ((hi->pci_slot == 0xff) || /* new board */ ((hi->pci_slot == slot) && (hi->bus == pdev->bus))) break; /* found for-loop exit */ } if (i == MAX_BOARDS) /* no match in above loop means MAX * exceeded */ { pr_warning("exceeded number of allowed devices (>%d)?\n", MAX_BOARDS); return 0; } if (pdev->bus) hi->pci_busno = pdev->bus->number; else hi->pci_busno = 0; /* default for system PCI inconsistency */ hi->pci_slot = slot; pci_read_config_byte (pdev, PCI_INTERRUPT_PIN, &hi->pci_pin[fun]); pci_read_config_byte (pdev, PCI_REVISION_ID, &hi->revid[fun]); hi->bus = pdev->bus; hi->addr[fun] = pci_resource_start (pdev, 0); hi->len[fun] = pci_resource_end (pdev, 0) - hi->addr[fun] + 1; hi->pdev[fun] = pdev; { /* * create device name from module name, plus add the appropriate * board number */ char *cp = hi->devname; strcpy (cp, KBUILD_MODNAME); cp += strlen (cp); /* reposition */ *cp++ = '-'; *cp++ = '0' + (found / 2); /* there are two found interfaces per * board */ *cp = 0; /* termination */ } return 1; }
static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) { int rc = 0; struct jsm_board *brd; static int adapter_count = 0; rc = pci_enable_device(pdev); if (rc) { dev_err(&pdev->dev, "Device enable FAILED\n"); goto out; } rc = pci_request_regions(pdev, "jsm"); if (rc) { dev_err(&pdev->dev, "pci_request_region FAILED\n"); goto out_disable_device; } brd = kzalloc(sizeof(struct jsm_board), GFP_KERNEL); if (!brd) { dev_err(&pdev->dev, "memory allocation for board structure failed\n"); rc = -ENOMEM; goto out_release_regions; } /* store the info for the board we've found */ brd->boardnum = adapter_count++; brd->pci_dev = pdev; if (pdev->device == PCIE_DEVICE_ID_NEO_4_IBM) brd->maxports = 4; else if (pdev->device == PCI_DEVICE_ID_DIGI_NEO_8) brd->maxports = 8; else brd->maxports = 2; spin_lock_init(&brd->bd_intr_lock); /* store which revision we have */ brd->rev = pdev->revision; brd->irq = pdev->irq; jsm_printk(INIT, INFO, &brd->pci_dev, "jsm_found_board - NEO adapter\n"); /* get the PCI Base Address Registers */ brd->membase = pci_resource_start(pdev, 0); brd->membase_end = pci_resource_end(pdev, 0); if (brd->membase & 1) brd->membase &= ~3; else brd->membase &= ~15; /* Assign the board_ops struct */ brd->bd_ops = &jsm_neo_ops; brd->bd_uart_offset = 0x200; brd->bd_dividend = 921600; brd->re_map_membase = ioremap(brd->membase, 0x1000); if (!brd->re_map_membase) { dev_err(&pdev->dev, "card has no PCI Memory resources, " "failing board.\n"); rc = -ENOMEM; goto out_kfree_brd; } rc = request_irq(brd->irq, brd->bd_ops->intr, IRQF_DISABLED|IRQF_SHARED, "JSM", brd); if (rc) { printk(KERN_WARNING "Failed to hook IRQ %d\n",brd->irq); goto out_iounmap; } rc = jsm_tty_init(brd); if (rc < 0) { dev_err(&pdev->dev, "Can't init tty devices (%d)\n", rc); rc = -ENXIO; goto out_free_irq; } rc = jsm_uart_port_init(brd); if (rc < 0) { /* XXX: leaking all resources from jsm_tty_init here! */ dev_err(&pdev->dev, "Can't init uart port (%d)\n", rc); rc = -ENXIO; goto out_free_irq; } /* Log the information about the board */ dev_info(&pdev->dev, "board %d: Digi Neo (rev %d), irq %d\n", adapter_count, brd->rev, brd->irq); /* * allocate flip buffer for board. * * Okay to malloc with GFP_KERNEL, we are not at interrupt * context, and there are no locks held. */ brd->flipbuf = kzalloc(MYFLIPLEN, GFP_KERNEL); if (!brd->flipbuf) { /* XXX: leaking all resources from jsm_tty_init and jsm_uart_port_init here! */ dev_err(&pdev->dev, "memory allocation for flipbuf failed\n"); rc = -ENOMEM; goto out_free_irq; } pci_set_drvdata(pdev, brd); pci_save_state(pdev); return 0; out_free_irq: free_irq(brd->irq, brd); out_iounmap: iounmap(brd->re_map_membase); out_kfree_brd: kfree(brd); out_release_regions: pci_release_regions(pdev); out_disable_device: pci_disable_device(pdev); out: return rc; }
static int __devinit rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, void **ioaddr_out) { void *ioaddr = NULL; struct net_device *dev; struct rtl8169_private *tp; unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; int rc, i, acpi_idle_state = 0, pm_cap; assert(pdev != NULL); assert(ioaddr_out != NULL); *ioaddr_out = NULL; *dev_out = NULL; // dev zeroed in alloc_etherdev dev = alloc_etherdev(sizeof (*tp)); if (dev == NULL) { printk(KERN_ERR PFX "unable to alloc new ethernet\n"); return -ENOMEM; } SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); tp = dev->priv; // enable device (incl. PCI PM wakeup and hotplug setup) rc = pci_enable_device(pdev); if (rc) { printk(KERN_ERR PFX "%s: unable to enable device\n", pdev->slot_name); goto err_out; } /* save power state before pci_enable_device overwrites it */ pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); if (pm_cap) { u16 pwr_command; pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command); acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK; } else { printk(KERN_ERR PFX "Cannot find PowerManagement capability, aborting.\n"); goto err_out_free_res; } mmio_start = pci_resource_start(pdev, 1); mmio_end = pci_resource_end(pdev, 1); mmio_flags = pci_resource_flags(pdev, 1); mmio_len = pci_resource_len(pdev, 1); // make sure PCI base addr 1 is MMIO if (!(mmio_flags & IORESOURCE_MEM)) { printk(KERN_ERR PFX "region #1 not an MMIO resource, aborting\n"); rc = -ENODEV; goto err_out_disable; } // check for weird/broken PCI region reporting if (mmio_len < RTL_MIN_IO_SIZE) { printk(KERN_ERR PFX "Invalid PCI region size(s), aborting\n"); rc = -ENODEV; goto err_out_disable; } rc = pci_request_regions(pdev, dev->name); if (rc) { printk(KERN_ERR PFX "%s: Could not request regions.\n", pdev->slot_name); goto err_out_disable; } tp->cp_cmd = PCIMulRW | RxChkSum; if ((sizeof(dma_addr_t) > 32) && !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) tp->cp_cmd |= PCIDAC; else { rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (rc < 0) { printk(KERN_ERR PFX "DMA configuration failed.\n"); goto err_out_free_res; } } // enable PCI bus-mastering pci_set_master(pdev); // ioremap MMIO region ioaddr = ioremap(mmio_start, mmio_len); if (ioaddr == NULL) { printk(KERN_ERR PFX "cannot remap MMIO, aborting\n"); rc = -EIO; goto err_out_free_res; } // Soft reset the chip. RTL_W8(ChipCmd, CmdReset); // Check that the chip has finished the reset. for (i = 1000; i > 0; i--) { if ((RTL_R8(ChipCmd) & CmdReset) == 0) break; udelay(10); } // Identify chip attached to board rtl8169_get_mac_version(tp, ioaddr); rtl8169_get_phy_version(tp, ioaddr); rtl8169_print_mac_version(tp); rtl8169_print_phy_version(tp); for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) { if (tp->mac_version == rtl_chip_info[i].mac_version) break; } if (i < 0) { /* Unknown chip: assume array element #0, original RTL-8169 */ printk(KERN_DEBUG PFX "PCI device %s: unknown chip version, assuming %s\n", pci_name(pdev), rtl_chip_info[0].name); i++; } tp->chipset = i; *ioaddr_out = ioaddr; *dev_out = dev; return 0; err_out_free_res: pci_release_regions(pdev); err_out_disable: pci_disable_device(pdev); err_out: free_netdev(dev); return rc; }