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); }
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); }
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); }
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); }
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); }
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); }
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); }