Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #5
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;
}
Пример #6
0
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;
}
Пример #7
0
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;
}
Пример #8
0
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;
}
Пример #9
0
/*!
 * 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;
        }
} 
Пример #10
0
/*
 * 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;
}
Пример #11
0
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;
}
Пример #12
0
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;
}
Пример #13
0
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;
            }
        }
    }
}
Пример #14
0
/* 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;
}
Пример #15
0
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)          ? '+' : '-');            
        }
     }
}
Пример #16
0
/* 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;
}
Пример #17
0
/**
 * 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;        
}
Пример #18
0
/* 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);
}
Пример #19
0
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;
}
Пример #20
0
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;
}
Пример #21
0
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;
}
Пример #22
0
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;
}
Пример #23
0
/*************************************************************************/ /*!
@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;
}
Пример #24
0
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;
}
Пример #25
0
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;
}
Пример #26
0
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;
}
Пример #27
0
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;
}