Esempio n. 1
0
static int
ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
	char		 buf[80];
	struct		 ahd_softc *ahd;
	ahd_dev_softc_t	 pci;
	struct		 ahd_pci_identity *entry;
	char		*name;
	int		 error;

	pci = pdev;
	entry = ahd_find_pci_device(pci);
	if (entry == NULL)
		return (-ENODEV);

	/*
	 * Allocate a softc for this card and
	 * set it up for attachment by our
	 * common detect routine.
	 */
	sprintf(buf, "ahd_pci:%d:%d:%d",
		ahd_get_pci_bus(pci),
		ahd_get_pci_slot(pci),
		ahd_get_pci_function(pci));
	name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
	if (name == NULL)
		return (-ENOMEM);
	strcpy(name, buf);
	ahd = ahd_alloc(NULL, name);
	if (ahd == NULL)
		return (-ENOMEM);
	if (pci_enable_device(pdev)) {
		ahd_free(ahd);
		return (-ENODEV);
	}
	pci_set_master(pdev);

	if (sizeof(dma_addr_t) > 4) {
		uint64_t   memsize;
		const uint64_t mask_39bit = 0x7FFFFFFFFFULL;

		memsize = ahd_linux_get_memsize();

		if (memsize >= 0x8000000000ULL
	 	 && pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) {
			ahd->flags |= AHD_64BIT_ADDRESSING;
		} else if (memsize > 0x80000000
			&& pci_set_dma_mask(pdev, mask_39bit) == 0) {
			ahd->flags |= AHD_39BIT_ADDRESSING;
		}
	} else {
		pci_set_dma_mask(pdev, DMA_32BIT_MASK);
	}
	ahd->dev_softc = pci;
	error = ahd_pci_config(ahd, entry);
	if (error != 0) {
		ahd_free(ahd);
		return (-error);
	}

	/*
	 * Second Function PCI devices need to inherit some
	 * * settings from function 0.
	 */
	if ((ahd->features & AHD_MULTI_FUNC) && PCI_FUNC(pdev->devfn) != 0)
		ahd_linux_pci_inherit_flags(ahd);

	pci_set_drvdata(pdev, ahd);

	ahd_linux_register_host(ahd, &aic79xx_driver_template);
	return (0);
}
Esempio n. 2
0
int
ahd_pci_map_registers(struct ahd_softc *ahd)
{
	uint32_t command;
	u_long	 base;
	uint8_t	__iomem *maddr;
	int	 error;

	/*
	 * If its allowed, we prefer memory mapped access.
	 */
	command = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, 4);
	command &= ~(PCIM_CMD_PORTEN|PCIM_CMD_MEMEN);
	base = 0;
	maddr = NULL;
	error = ahd_linux_pci_reserve_mem_region(ahd, &base, &maddr);
	if (error == 0) {
		ahd->platform_data->mem_busaddr = base;
		ahd->tags[0] = BUS_SPACE_MEMIO;
		ahd->bshs[0].maddr = maddr;
		ahd->tags[1] = BUS_SPACE_MEMIO;
		ahd->bshs[1].maddr = maddr + 0x100;
		ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
				     command | PCIM_CMD_MEMEN, 4);

		if (ahd_pci_test_register_access(ahd) != 0) {

			printf("aic79xx: PCI Device %d:%d:%d "
			       "failed memory mapped test.  Using PIO.\n",
			       ahd_get_pci_bus(ahd->dev_softc),
			       ahd_get_pci_slot(ahd->dev_softc),
			       ahd_get_pci_function(ahd->dev_softc));
			iounmap(maddr);
			release_mem_region(ahd->platform_data->mem_busaddr,
					   0x1000);
			ahd->bshs[0].maddr = NULL;
			maddr = NULL;
		} else
			command |= PCIM_CMD_MEMEN;
	} else if (bootverbose) {
		printf("aic79xx: PCI%d:%d:%d MEM region 0x%lx "
		       "unavailable. Cannot memory map device.\n",
		       ahd_get_pci_bus(ahd->dev_softc),
		       ahd_get_pci_slot(ahd->dev_softc),
		       ahd_get_pci_function(ahd->dev_softc),
		       base);
	}

	if (maddr == NULL) {
		u_long	 base2;

		error = ahd_linux_pci_reserve_io_regions(ahd, &base, &base2);
		if (error == 0) {
			ahd->tags[0] = BUS_SPACE_PIO;
			ahd->tags[1] = BUS_SPACE_PIO;
			ahd->bshs[0].ioport = base;
			ahd->bshs[1].ioport = base2;
			command |= PCIM_CMD_PORTEN;
		} else {
			printf("aic79xx: PCI%d:%d:%d IO regions 0x%lx and 0x%lx"
			       "unavailable. Cannot map device.\n",
			       ahd_get_pci_bus(ahd->dev_softc),
			       ahd_get_pci_slot(ahd->dev_softc),
			       ahd_get_pci_function(ahd->dev_softc),
			       base, base2);
		}
	}
	ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, 4);
	return (error);
}
Esempio n. 3
0
static int
ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
	char		 buf[80];
	struct		 ahd_softc *ahd;
	ahd_dev_softc_t	 pci;
	const struct ahd_pci_identity *entry;
	char		*name;
	int		 error;
	struct device	*dev = &pdev->dev;

	pci = pdev;
	entry = ahd_find_pci_device(pci);
	if (entry == NULL)
		return (-ENODEV);

	/*
	 * Allocate a softc for this card and
	 * set it up for attachment by our
	 * common detect routine.
	 */
	sprintf(buf, "ahd_pci:%d:%d:%d",
		ahd_get_pci_bus(pci),
		ahd_get_pci_slot(pci),
		ahd_get_pci_function(pci));
	name = kmalloc(strlen(buf) + 1, GFP_ATOMIC);
	if (name == NULL)
		return (-ENOMEM);
	strcpy(name, buf);
	ahd = ahd_alloc(NULL, name);
	if (ahd == NULL)
		return (-ENOMEM);
	if (pci_enable_device(pdev)) {
		ahd_free(ahd);
		return (-ENODEV);
	}
	pci_set_master(pdev);

	if (sizeof(dma_addr_t) > 4) {
		const u64 required_mask = dma_get_required_mask(dev);

		if (required_mask > DMA_BIT_MASK(39) &&
		    dma_set_mask(dev, DMA_BIT_MASK(64)) == 0)
			ahd->flags |= AHD_64BIT_ADDRESSING;
		else if (required_mask > DMA_BIT_MASK(32) &&
			 dma_set_mask(dev, DMA_BIT_MASK(39)) == 0)
			ahd->flags |= AHD_39BIT_ADDRESSING;
		else
			dma_set_mask(dev, DMA_BIT_MASK(32));
	} else {
		dma_set_mask(dev, DMA_BIT_MASK(32));
	}
	ahd->dev_softc = pci;
	error = ahd_pci_config(ahd, entry);
	if (error != 0) {
		ahd_free(ahd);
		return (-error);
	}

	/*
	 * Second Function PCI devices need to inherit some
	 * * settings from function 0.
	 */
	if ((ahd->features & AHD_MULTI_FUNC) && PCI_FUNC(pdev->devfn) != 0)
		ahd_linux_pci_inherit_flags(ahd);

	pci_set_drvdata(pdev, ahd);

	ahd_linux_register_host(ahd, &aic79xx_driver_template);
	return (0);
}