Exemple #1
0
static int
ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
	char		 buf[80];
	const uint64_t	 mask_39bit = 0x7FFFFFFFFFULL;
	struct		 ahc_softc *ahc;
	ahc_dev_softc_t	 pci;
	struct		 ahc_pci_identity *entry;
	char		*name;
	int		 error;

	pci = pdev;
	entry = ahc_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, "ahc_pci:%d:%d:%d",
		ahc_get_pci_bus(pci),
		ahc_get_pci_slot(pci),
		ahc_get_pci_function(pci));
	name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
	if (name == NULL)
		return (-ENOMEM);
	strcpy(name, buf);
	ahc = ahc_alloc(NULL, name);
	if (ahc == NULL)
		return (-ENOMEM);
	if (pci_enable_device(pdev)) {
		ahc_free(ahc);
		return (-ENODEV);
	}
	pci_set_master(pdev);

	if (sizeof(dma_addr_t) > 4
	 && ahc_linux_get_memsize() > 0x80000000
	 && pci_set_dma_mask(pdev, mask_39bit) == 0) {
		ahc->flags |= AHC_39BIT_ADDRESSING;
	} else {
		if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
			printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n");
                	return (-ENODEV);
		}
	}
	ahc->dev_softc = pci;
	error = ahc_pci_config(ahc, entry);
	if (error != 0) {
		ahc_free(ahc);
		return (-error);
	}
	pci_set_drvdata(pdev, ahc);
	ahc_linux_register_host(ahc, &aic7xxx_driver_template);
	return (0);
}
Exemple #2
0
static int
aic7770_attach(device_t dev)
{
	struct	 aic7770_identity *entry;
	struct	 ahc_softc *ahc;
	char	*name;
	int	 error;

	entry = aic7770_find_device(eisa_get_id(dev));
	if (entry == NULL)
		return (ENXIO);

	/*
	 * Allocate a softc for this card and
	 * set it up for attachment by our
	 * common detect routine.
	 */
	name = malloc(strlen(device_get_nameunit(dev)) + 1, M_DEVBUF, M_NOWAIT);
	if (name == NULL)
		return (ENOMEM);
	strcpy(name, device_get_nameunit(dev));
	ahc = ahc_alloc(dev, name);
	if (ahc == NULL)
		return (ENOMEM);

	ahc_set_unit(ahc, device_get_unit(dev));

	/* Allocate a dmatag for our SCB DMA maps */
	/* XXX Should be a child of the PCI bus dma tag */
	error = aic_dma_tag_create(ahc, /*parent*/bus_get_dma_tag(dev),
				   /*alignment*/1, /*boundary*/0,
				   /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
				   /*highaddr*/BUS_SPACE_MAXADDR,
				   /*filter*/NULL, /*filterarg*/NULL,
				   /*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
				   /*nsegments*/AHC_NSEG,
				   /*maxsegsz*/AHC_MAXTRANSFER_SIZE,
				   /*flags*/0,
				   &ahc->parent_dmat);

	if (error != 0) {
		printf("ahc_eisa_attach: Could not allocate DMA tag "
		       "- error %d\n", error);
		ahc_free(ahc);
		return (ENOMEM);
	}
	ahc->dev_softc = dev;
	error = aic7770_config(ahc, entry, /*unused ioport arg*/0);
	if (error != 0) {
		ahc_free(ahc);
		return (error);
	}

	ahc_attach(ahc);
	return (0);
}
static int
aic7770_probe(struct device *dev)
{
	struct eisa_device *edev = to_eisa_device(dev);
	u_int eisaBase = edev->base_addr+AHC_EISA_SLOT_OFFSET;
	struct	ahc_softc *ahc;
	char	buf[80];
	char   *name;
	int	error;

	sprintf(buf, "ahc_eisa:%d", eisaBase >> 12);
	name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
	if (name == NULL)
		return (ENOMEM);
	strcpy(name, buf);
	ahc = ahc_alloc(&aic7xxx_driver_template, name);
	if (ahc == NULL)
		return (ENOMEM);
	error = aic7770_config(ahc, aic7770_ident_table + edev->id.driver_data,
			       eisaBase);
	if (error != 0) {
		ahc->bsh.ioport = 0;
		ahc_free(ahc);
		return (error);
	}

 	dev_set_drvdata(dev, ahc);

	error = ahc_linux_register_host(ahc, &aic7xxx_driver_template);
	return (error);
}
static int
aic7770_eisa_dev_remove(struct device *dev)
{
	struct ahc_softc *ahc;
	u_long l;

	/*
	 * We should be able to just perform
	 * the free directly, but check our
	 * list for extra sanity.
	 */
	ahc_list_lock(&l);
	ahc = ahc_find_softc((struct ahc_softc *)dev->driver_data);
	if (ahc != NULL) {
		u_long s;

		ahc_lock(ahc, &s);
		ahc_intr_enable(ahc, FALSE);
		ahc_unlock(ahc, &s);
		ahc_free(ahc);
	}
	ahc_list_unlock(&l);

	return (0);
}
Exemple #5
0
static void
ahc_linux_pci_dev_remove(struct pci_dev *pdev)
{
	struct ahc_softc *ahc = pci_get_drvdata(pdev);
	u_long s;

	ahc_lock(ahc, &s);
	ahc_intr_enable(ahc, FALSE);
	ahc_unlock(ahc, &s);
	ahc_free(ahc);
}
static void
ahc_linux_pci_dev_remove(struct pci_dev *pdev)
{
	struct ahc_softc *ahc = pci_get_drvdata(pdev);
	u_long s;

	if (ahc->platform_data && ahc->platform_data->host)
			scsi_remove_host(ahc->platform_data->host);

	ahc_lock(ahc, &s);
	ahc_intr_enable(ahc, FALSE);
	ahc_unlock(ahc, &s);
	ahc_free(ahc);
}
static int
aic7770_remove(struct device *dev)
{
	struct ahc_softc *ahc = dev_get_drvdata(dev);
	u_long s;

	if (ahc->platform_data && ahc->platform_data->host)
			scsi_remove_host(ahc->platform_data->host);

	ahc_lock(ahc, &s);
	ahc_intr_enable(ahc, FALSE);
	ahc_unlock(ahc, &s);

	ahc_free(ahc);
	return 0;
}
static int
aic7770_linux_config(struct aic7770_identity *entry, aic7770_dev_t dev,
		     u_int eisaBase)
{
	struct	ahc_softc *ahc;
	char	buf[80];
	char   *name;
	int	error;

	/*
	 * Allocate a softc for this card and
	 * set it up for attachment by our
	 * common detect routine.
	 */
	sprintf(buf, "ahc_eisa:%d", eisaBase >> 12);
	name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
	if (name == NULL)
		return (ENOMEM);
	strcpy(name, buf);
	ahc = ahc_alloc(&aic7xxx_driver_template, name);
	if (ahc == NULL) {
		free(name, M_DEVBUF);
		return (ENOMEM);
	}
	error = aic7770_config(ahc, entry, eisaBase);
	if (error != 0) {
		ahc->bsh.ioport = 0;
		ahc_free(ahc);
		return (error);
	}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
	dev->driver_data = (void *)ahc;
	if (aic7xxx_detect_complete)
		error = ahc_linux_register_host(ahc, &aic7xxx_driver_template);
#endif
	return (error);
}
Exemple #9
0
void
ahc_cardbus_attach(device_t parent, device_t self, void *aux)
{
	struct cardbus_attach_args *ca = aux;
	struct ahc_cardbus_softc *csc = device_private(self);
	struct ahc_softc *ahc = &csc->sc_ahc;
	cardbus_devfunc_t ct = ca->ca_ct;
	bus_space_tag_t bst;
	bus_space_handle_t bsh;
	pcireg_t reg;
	u_int sxfrctl1 = 0;
	u_char sblkctl;


	ahc->sc_dev = self;
	csc->sc_ct = ct;
	csc->sc_tag = ca->ca_tag;

	printf(": Adaptec ADP-1480 SCSI\n");

	/*
	 * Map the device.
	 */
	csc->sc_csr = PCI_COMMAND_MASTER_ENABLE;
	if (Cardbus_mapreg_map(csc->sc_ct, AHC_CARDBUS_MMBA,
	    PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
	    &bst, &bsh, NULL, &csc->sc_size) == 0) {
		csc->sc_bar = AHC_CARDBUS_MMBA;
		csc->sc_csr |= PCI_COMMAND_MEM_ENABLE;
	} else if (Cardbus_mapreg_map(csc->sc_ct, AHC_CARDBUS_IOBA,
	    PCI_MAPREG_TYPE_IO, 0, &bst, &bsh, NULL, &csc->sc_size) == 0) {
		csc->sc_bar = AHC_CARDBUS_IOBA;
		csc->sc_csr |= PCI_COMMAND_IO_ENABLE;
	} else {
		csc->sc_bar = 0;
		aprint_error("%s: unable to map device registers\n",
		    ahc_name(ahc));
		return;
	}

	/* Enable the appropriate bits in the PCI CSR. */
	reg = Cardbus_conf_read(ct, ca->ca_tag, PCI_COMMAND_STATUS_REG);
	reg &= ~(PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE);
	reg |= csc->sc_csr;
	Cardbus_conf_write(ct, ca->ca_tag, PCI_COMMAND_STATUS_REG, reg);

	/*
	 * Make sure the latency timer is set to some reasonable
	 * value.
	 */
	reg = Cardbus_conf_read(ct, ca->ca_tag, PCI_BHLC_REG);
	if (PCI_LATTIMER(reg) < 0x20) {
		reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
		reg |= (0x20 << PCI_LATTIMER_SHIFT);
		Cardbus_conf_write(ct, ca->ca_tag, PCI_BHLC_REG, reg);
	}

	ahc_set_name(ahc, device_xname(ahc->sc_dev));

	ahc->parent_dmat = ca->ca_dmat;
	ahc->tag = bst;
	ahc->bsh = bsh;

	/*
	 * ADP-1480 is always an AIC-7860.
	 */
	ahc->chip = AHC_AIC7860 | AHC_PCI;
	ahc->features = AHC_AIC7860_FE|AHC_REMOVABLE;
	ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
	if (PCI_REVISION(ca->ca_class) >= 1)
		ahc->bugs |= AHC_PCI_2_1_RETRY_BUG;

	if (ahc_softc_init(ahc) != 0)
		return;

	/*
	 * On all CardBus adapters, we allow SCB paging.
	 */
	ahc->flags = AHC_PAGESCBS;

	ahc->channel = 'A';

	ahc_intr_enable(ahc, FALSE);

	ahc_reset(ahc);

	/*
	 * Establish the interrupt.
	 */
	ahc->ih = Cardbus_intr_establish(ct, IPL_BIO, ahc_intr, ahc);
	if (ahc->ih == NULL) {
		aprint_error("%s: unable to establish interrupt\n",
		    ahc_name(ahc));
		return;
	}

	ahc->seep_config = malloc(sizeof(*ahc->seep_config),
				  M_DEVBUF, M_NOWAIT);
	if (ahc->seep_config == NULL)
		return;

	ahc_check_extport(ahc, &sxfrctl1);
	/*
	 * Take the LED out of diagnostic mode.
	 */
	sblkctl = ahc_inb(ahc, SBLKCTL);
	ahc_outb(ahc, SBLKCTL, (sblkctl & ~(DIAGLEDEN|DIAGLEDON)));

	/*
	 * I don't know where this is set in the SEEPROM or by the
	 * BIOS, so we default to 100%.
	 */
	ahc_outb(ahc, DSPCISTATUS, DFTHRSH_100);

	if (ahc->flags & AHC_USEDEFAULTS) {
		int our_id;
		/*
		 * Assume only one connector and always turn
		 * on termination.
		 */
		our_id = AHC_CARDBUS_DEFAULT_SCSI_ID;
		sxfrctl1 = STPWEN;
		ahc_outb(ahc, SCSICONF, our_id | ENSPCHK | RESET_SCSI);
		ahc->our_id = our_id;
	}

	printf("%s: aic7860", ahc_name(ahc));

	/*
	 * Record our termination setting for the
	 * generic initialization routine.
	 */
        if ((sxfrctl1 & STPWEN) != 0)
		ahc->flags |= AHC_TERM_ENB_A;

	if (ahc_init(ahc)) {
		ahc_free(ahc);
		return;
	}

	ahc_attach(ahc);
}
Exemple #10
0
static int
ahc_pci_attach(device_t dev)
{
	struct	 ahc_pci_identity *entry;
	struct	 ahc_softc *ahc;
	char	*name;
	int	 error;

	entry = ahc_find_pci_device(dev);
	if (entry == NULL)
		return (ENXIO);

	/*
	 * Allocate a softc for this card and
	 * set it up for attachment by our
	 * common detect routine.
	 */
	name = kmalloc(strlen(device_get_nameunit(dev)) + 1, M_DEVBUF, M_INTWAIT);
	strcpy(name, device_get_nameunit(dev));
	ahc = ahc_alloc(dev, name);
	if (ahc == NULL)
		return (ENOMEM);

	ahc_set_unit(ahc, device_get_unit(dev));

	/*
	 * Should we bother disabling 39Bit addressing
	 * based on installed memory?
	 */
	if (sizeof(bus_addr_t) > 4)
                ahc->flags |= AHC_39BIT_ADDRESSING;

	/* Allocate a dmatag for our SCB DMA maps */
	/* XXX Should be a child of the PCI bus dma tag */
	error = aic_dma_tag_create(ahc, /*parent*/NULL, /*alignment*/1,
				   /*boundary*/0,
				   (ahc->flags & AHC_39BIT_ADDRESSING)
				   ? 0x7FFFFFFFFFULL
				   : BUS_SPACE_MAXADDR_32BIT,
				   /*highaddr*/BUS_SPACE_MAXADDR,
				   /*filter*/NULL, /*filterarg*/NULL,
				   /*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
				   /*nsegments*/AHC_NSEG,
				   /*maxsegsz*/AHC_MAXTRANSFER_SIZE,
				   /*flags*/0,
				   &ahc->parent_dmat);

	if (error != 0) {
		kprintf("ahc_pci_attach: Could not allocate DMA tag "
		       "- error %d\n", error);
		ahc_free(ahc);
		return (ENOMEM);
	}
	ahc->dev_softc = dev;
	error = ahc_pci_config(ahc, entry);
	if (error != 0) {
		ahc_free(ahc);
		return (error);
	}

	ahc_attach(ahc);
	return (0);
}
Exemple #11
0
void
ahc_isa_attach(struct device *parent, struct device *self, void *aux)
{
	struct ahc_softc *ahc = (void *)self;
	struct isa_attach_args *ia = aux;
	bus_space_tag_t iot = ia->ia_iot;
	bus_space_handle_t ioh;
	int irq;
	char idstring[EISA_IDSTRINGLEN];
	const char *model;
	u_int intdef;
	
	ahc_set_name(ahc, ahc->sc_dev.dv_xname);
	ahc_set_unit(ahc, ahc->sc_dev.dv_unit);
	
	/* set dma tags */
	ahc->parent_dmat = ia->ia_dmat;
	
	ahc->chip = AHC_VL; /* We are a VL Bus Controller */  
	
	if (bus_space_map(iot, ia->ia_iobase, ia->ia_iosize, 0, &ioh))
		panic("ahc_isa_attach: can't map slot i/o addresses");
	if (!ahc_isa_idstring(iot, ioh, idstring))
		panic("ahc_isa_attach: could not read ID string");
	if ((irq = ahc_isa_irq(iot, ioh)) < 0)
		panic("ahc_isa_attach: ahc_isa_irq failed!");

	if (strcmp(idstring, "ADP7756") == 0) {
		model = EISA_PRODUCT_ADP7756;
	} else if (strcmp(idstring, "ADP7757") == 0) {
		model = EISA_PRODUCT_ADP7757;
	} else {
		panic("ahc_isa_attach: Unknown device type %s", idstring);
	}
	printf(": %s\n", model);
	
	ahc->channel = 'A';
	ahc->chip = AHC_AIC7770;
	ahc->features = AHC_AIC7770_FE;
	ahc->bugs |= AHC_TMODE_WIDEODD_BUG;
	ahc->flags |= AHC_PAGESCBS;
	
	/* set tag and handle */
	ahc->tag = iot;
	ahc->bsh = ioh;

#ifdef DEBUG
	/*
	 * Tell the user what type of interrupts we're using.
	 * useful for debugging irq problems
	 */
	printf( "%s: Using %s Interrupts\n", ahc_name(ahc),
	    ahc->pause & IRQMS ?  "Level Sensitive" : "Edge Triggered");
#endif

	if (ahc_reset(ahc, /*reinit*/FALSE) != 0)
		return;
	
	/* See if we are edge triggered */
	intdef = ahc_inb(ahc, INTDEF);
	if ((intdef & EDGE_TRIG) != 0)
		ahc->flags |= AHC_EDGE_INTERRUPT;

	/*
	 * Now that we know we own the resources we need, do the 
	 * card initialization.
	 */
	aha2840_load_seeprom(ahc);

	/*      
	 * See if we have a Rev E or higher aic7770. Anything below a
	 * Rev E will have a R/O autoflush disable configuration bit.
	 * It's still not clear exactly what is differenent about the Rev E.
	 * We think it allows 8 bit entries in the QOUTFIFO to support
	 * "paging" SCBs so you can have more than 4 commands active at
	 * once.
	 */     
	{
		char *id_string;
		u_char sblkctl;
		u_char sblkctl_orig;

		sblkctl_orig = ahc_inb(ahc, SBLKCTL);
		sblkctl = sblkctl_orig ^ AUTOFLUSHDIS;
		ahc_outb(ahc, SBLKCTL, sblkctl);
		sblkctl = ahc_inb(ahc, SBLKCTL);
		if(sblkctl != sblkctl_orig)
		{
			id_string = "aic7770 >= Rev E, ";
			/*
			 * Ensure autoflush is enabled
			 */
			sblkctl &= ~AUTOFLUSHDIS;
			ahc_outb(ahc, SBLKCTL, sblkctl);

			/* Allow paging on this adapter */
			ahc->flags |= AHC_PAGESCBS;
		}
		else
			id_string = "aic7770 <= Rev C, ";

		printf("%s: %s", ahc_name(ahc), id_string);
	}

	/* Setup the FIFO threshold and the bus off time */
	{
		u_char hostconf = ahc_inb(ahc, HOSTCONF);
		ahc_outb(ahc, BUSSPD, hostconf & DFTHRSH);
		ahc_outb(ahc, BUSTIME, (hostconf << 2) & BOFF);
	}

	/*
	 * Generic aic7xxx initialization.
	 */
	if(ahc_init(ahc)){
		ahc_free(ahc);
		return;
	}
	
	/*
	 * Link this softc in with all other ahc instances.
	 */
	ahc_softc_insert(ahc);

	/*
	 * Enable the board's BUS drivers
	 */
	ahc_outb(ahc, BCTL, ENABLE);

	/*
	 * The IRQMS bit enables level sensitive interrupts only allow
	 * IRQ sharing if its set.
	 */
	ahc->ih = isa_intr_establish(ia->ia_ic, irq,
	    ahc->pause & IRQMS ? IST_LEVEL : IST_EDGE, IPL_BIO, ahc_platform_intr,
	    ahc, ahc->sc_dev.dv_xname);
	if (ahc->ih == NULL) {
		printf("%s: couldn't establish interrupt\n",
		       ahc->sc_dev.dv_xname);
		ahc_free(ahc);
		return;
	}

	ahc_intr_enable(ahc, TRUE);
	
	/* Attach sub-devices - always succeeds */
	ahc_attach(ahc);
}
Exemple #12
0
static int
ahc_isa_attach(device_t dev)
{
	struct	 aic7770_identity *entry;
	bus_space_tag_t	    tag;
	bus_space_handle_t  bsh;
	struct	  resource *regs;
	struct	  ahc_softc *ahc;
	char	 *name;
	int	  zero;
	int	  error;

	zero = 0;
	regs = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &zero, RF_ACTIVE);
	if (regs == NULL)
		return (ENOMEM);

	tag = rman_get_bustag(regs);
	bsh = rman_get_bushandle(regs);
	entry = ahc_isa_find_device(tag, bsh);
	bus_release_resource(dev, SYS_RES_IOPORT, zero, regs);
	if (entry == NULL)
		return (ENODEV);

	/*
	 * Allocate a softc for this card and
	 * set it up for attachment by our
	 * common detect routine.
	 */
	name = malloc(strlen(device_get_nameunit(dev)) + 1, M_DEVBUF, M_NOWAIT);
	if (name == NULL)
		return (ENOMEM);
	strcpy(name, device_get_nameunit(dev));
	ahc = ahc_alloc(dev, name);
	if (ahc == NULL)
		return (ENOMEM);

	ahc_set_unit(ahc, device_get_unit(dev));

	/* Allocate a dmatag for our SCB DMA maps */
	error = aic_dma_tag_create(ahc, /*parent*/bus_get_dma_tag(dev),
				   /*alignment*/1, /*boundary*/0,
				   /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
				   /*highaddr*/BUS_SPACE_MAXADDR,
				   /*filter*/NULL, /*filterarg*/NULL,
				   /*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
				   /*nsegments*/AHC_NSEG,
				   /*maxsegsz*/AHC_MAXTRANSFER_SIZE,
				   /*flags*/0,
				   &ahc->parent_dmat);

	if (error != 0) {
		printf("ahc_isa_attach: Could not allocate DMA tag "
		       "- error %d\n", error);
		ahc_free(ahc);
		return (ENOMEM);
	}
	ahc->dev_softc = dev;
	error = aic7770_config(ahc, entry, /*unused ioport arg*/0);
	if (error != 0) {
		ahc_free(ahc);
		return (error);
	}

	ahc_attach(ahc);
	return (0);
}
static int
ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
	char		 buf[80];
	const uint64_t	 mask_39bit = 0x7FFFFFFFFFULL;
	struct		 ahc_softc *ahc;
	ahc_dev_softc_t	 pci;
	struct		 ahc_pci_identity *entry;
	char		*name;
	int		 error;
	struct device	*dev = &pdev->dev;

	pci = pdev;
	entry = ahc_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, "ahc_pci:%d:%d:%d",
		ahc_get_pci_bus(pci),
		ahc_get_pci_slot(pci),
		ahc_get_pci_function(pci));
	name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
	if (name == NULL)
		return (-ENOMEM);
	strcpy(name, buf);
	ahc = ahc_alloc(NULL, name);
	if (ahc == NULL)
		return (-ENOMEM);
	if (pci_enable_device(pdev)) {
		ahc_free(ahc);
		return (-ENODEV);
	}
	pci_set_master(pdev);

	if (sizeof(dma_addr_t) > 4
	    && ahc->features & AHC_LARGE_SCBS
	    && dma_set_mask(dev, mask_39bit) == 0
	    && dma_get_required_mask(dev) > DMA_32BIT_MASK) {
		ahc->flags |= AHC_39BIT_ADDRESSING;
	} else {
		if (dma_set_mask(dev, DMA_32BIT_MASK)) {
			ahc_free(ahc);
			printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n");
                	return (-ENODEV);
		}
	}
	ahc->dev_softc = pci;
	error = ahc_pci_config(ahc, entry);
	if (error != 0) {
		ahc_free(ahc);
		return (-error);
	}

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

	pci_set_drvdata(pdev, ahc);
	ahc_linux_register_host(ahc, &aic7xxx_driver_template);
	return (0);
}