static void ahd_pci_attach(device_t parent, device_t self, void *aux) { struct pci_attach_args *pa = aux; struct ahd_softc *ahd = device_private(self); const struct ahd_pci_identity *entry; uint32_t devconfig; pcireg_t command; int error; pcireg_t subid; uint16_t subvendor; pcireg_t reg; int ioh_valid, ioh2_valid, memh_valid; pcireg_t memtype; pci_intr_handle_t ih; const char *intrstr; struct ahd_pci_busdata *bd; ahd->sc_dev = self; ahd_set_name(ahd, device_xname(self)); ahd->parent_dmat = pa->pa_dmat; command = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); entry = ahd_find_pci_device(pa->pa_id, subid); if (entry == NULL) return; /* Keep information about the PCI bus */ bd = malloc(sizeof (struct ahd_pci_busdata), M_DEVBUF, M_NOWAIT); if (bd == NULL) { aprint_error("%s: unable to allocate bus-specific data\n", ahd_name(ahd)); return; } memset(bd, 0, sizeof(struct ahd_pci_busdata)); bd->pc = pa->pa_pc; bd->tag = pa->pa_tag; bd->func = pa->pa_function; bd->dev = pa->pa_device; ahd->bus_data = bd; ahd->description = entry->name; ahd->seep_config = malloc(sizeof(*ahd->seep_config), M_DEVBUF, M_NOWAIT); if (ahd->seep_config == NULL) { aprint_error("%s: cannot malloc seep_config!\n", ahd_name(ahd)); return; } memset(ahd->seep_config, 0, sizeof(*ahd->seep_config)); LIST_INIT(&ahd->pending_scbs); ahd_timer_init(&ahd->reset_timer); ahd_timer_init(&ahd->stat_timer); ahd->flags = AHD_SPCHK_ENB_A|AHD_RESET_BUS_A|AHD_TERM_ENB_A | AHD_EXTENDED_TRANS_A|AHD_STPWLEVEL_A; ahd->int_coalescing_timer = AHD_INT_COALESCING_TIMER_DEFAULT; ahd->int_coalescing_maxcmds = AHD_INT_COALESCING_MAXCMDS_DEFAULT; ahd->int_coalescing_mincmds = AHD_INT_COALESCING_MINCMDS_DEFAULT; ahd->int_coalescing_threshold = AHD_INT_COALESCING_THRESHOLD_DEFAULT; ahd->int_coalescing_stop_threshold = AHD_INT_COALESCING_STOP_THRESHOLD_DEFAULT; if (ahd_platform_alloc(ahd, NULL) != 0) { ahd_free(ahd); return; } /* * Record if this is an HP board. */ subvendor = PCI_VENDOR(subid); if (subvendor == SUBID_HP) ahd->flags |= AHD_HP_BOARD; error = entry->setup(ahd, pa); if (error != 0) return; devconfig = pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG); if ((devconfig & PCIXINITPAT) == PCIXINIT_PCI33_66) { ahd->chip |= AHD_PCI; /* Disable PCIX workarounds when running in PCI mode. */ ahd->bugs &= ~AHD_PCIX_BUG_MASK; } else { ahd->chip |= AHD_PCIX; } ahd->bus_description = pci_bus_modes[PCI_BUS_MODES_INDEX(devconfig)]; memh_valid = ioh_valid = ioh2_valid = 0; if (!pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PCIX, &bd->pcix_off, NULL)) { if (ahd->chip & AHD_PCIX) aprint_error_dev(self, "warning: can't find PCI-X capability\n"); ahd->chip &= ~AHD_PCIX; ahd->chip |= AHD_PCI; ahd->bugs &= ~AHD_PCIX_BUG_MASK; } /* * Map PCI Registers */ if ((ahd->bugs & AHD_PCIX_MMAPIO_BUG) == 0) { memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, AHD_PCI_MEMADDR); switch (memtype) { case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT: case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT: memh_valid = (pci_mapreg_map(pa, AHD_PCI_MEMADDR, memtype, 0, &ahd->tags[0], &ahd->bshs[0], NULL, NULL) == 0); if (memh_valid) { ahd->tags[1] = ahd->tags[0]; bus_space_subregion(ahd->tags[0], ahd->bshs[0], /*offset*/0x100, /*size*/0x100, &ahd->bshs[1]); if (ahd_pci_test_register_access(ahd) != 0) memh_valid = 0; } break; default: memh_valid = 0; aprint_error("%s: unknown memory type: 0x%x\n", ahd_name(ahd), memtype); break; } if (memh_valid) { command &= ~PCI_COMMAND_IO_ENABLE; pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command); } #ifdef AHD_DEBUG printf("%s: doing memory mapping shs0 0x%lx, shs1 0x%lx\n", ahd_name(ahd), ahd->bshs[0], ahd->bshs[1]); #endif } if (command & PCI_COMMAND_IO_ENABLE) { /* First BAR */ ioh_valid = (pci_mapreg_map(pa, AHD_PCI_IOADDR, PCI_MAPREG_TYPE_IO, 0, &ahd->tags[0], &ahd->bshs[0], NULL, NULL) == 0); /* 2nd BAR */ ioh2_valid = (pci_mapreg_map(pa, AHD_PCI_IOADDR1, PCI_MAPREG_TYPE_IO, 0, &ahd->tags[1], &ahd->bshs[1], NULL, NULL) == 0); if (ioh_valid && ioh2_valid) { KASSERT(memh_valid == 0); command &= ~PCI_COMMAND_MEM_ENABLE; pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command); } #ifdef AHD_DEBUG printf("%s: doing io mapping shs0 0x%lx, shs1 0x%lx\n", ahd_name(ahd), ahd->bshs[0], ahd->bshs[1]); #endif } if (memh_valid == 0 && (ioh_valid == 0 || ioh2_valid == 0)) { aprint_error("%s: unable to map registers\n", ahd_name(ahd)); return; } aprint_normal("\n"); aprint_naive("\n"); /* power up chip */ if ((error = pci_activate(pa->pa_pc, pa->pa_tag, self, pci_activate_null)) && error != EOPNOTSUPP) { aprint_error_dev(self, "cannot activate %d\n", error); return; } /* * Should we bother disabling 39Bit addressing * based on installed memory? */ if (sizeof(bus_addr_t) > 4) ahd->flags |= AHD_39BIT_ADDRESSING; /* * If we need to support high memory, enable dual * address cycles. This bit must be set to enable * high address bit generation even if we are on a * 64bit bus (PCI64BIT set in devconfig). */ if ((ahd->flags & (AHD_39BIT_ADDRESSING|AHD_64BIT_ADDRESSING)) != 0) { uint32_t dvconfig; aprint_normal("%s: Enabling 39Bit Addressing\n", ahd_name(ahd)); dvconfig = pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG); dvconfig |= DACEN; pci_conf_write(pa->pa_pc, pa->pa_tag, DEVCONFIG, dvconfig); } /* Ensure busmastering is enabled */ reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, reg | PCI_COMMAND_MASTER_ENABLE); ahd_softc_init(ahd); /* * Map the interrupt routines */ ahd->bus_intr = ahd_pci_intr; error = ahd_reset(ahd, /*reinit*/FALSE); if (error != 0) { ahd_free(ahd); return; } if (pci_intr_map(pa, &ih)) { aprint_error("%s: couldn't map interrupt\n", ahd_name(ahd)); ahd_free(ahd); return; } intrstr = pci_intr_string(pa->pa_pc, ih); ahd->ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, ahd_intr, ahd); if (ahd->ih == NULL) { aprint_error("%s: couldn't establish interrupt", ahd_name(ahd)); if (intrstr != NULL) aprint_error(" at %s", intrstr); aprint_error("\n"); ahd_free(ahd); return; } if (intrstr != NULL) aprint_normal("%s: interrupting at %s\n", ahd_name(ahd), intrstr); /* Get the size of the cache */ ahd->pci_cachesize = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG); ahd->pci_cachesize *= 4; ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); /* See if we have a SEEPROM and perform auto-term */ error = ahd_check_extport(ahd); if (error != 0) return; /* Core initialization */ error = ahd_init(ahd); if (error != 0) return; /* * Link this softc in with all other ahd instances. */ ahd_attach(ahd); }
int ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry) { struct scb_data *shared_scb_data; u_int command; uint32_t devconfig; uint16_t subvendor; int error; shared_scb_data = NULL; ahd->description = entry->name; /* * Record if this is an HP board. */ subvendor = ahd_pci_read_config(ahd->dev_softc, PCIR_SUBVEND_0, /*bytes*/2); if (subvendor == SUBID_HP) ahd->flags |= AHD_HP_BOARD; error = entry->setup(ahd); if (error != 0) return (error); devconfig = ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4); if ((devconfig & PCIXINITPAT) == PCIXINIT_PCI33_66) { ahd->chip |= AHD_PCI; /* Disable PCIX workarounds when running in PCI mode. */ ahd->bugs &= ~AHD_PCIX_BUG_MASK; } else { ahd->chip |= AHD_PCIX; } ahd->bus_description = pci_bus_modes[PCI_BUS_MODES_INDEX(devconfig)]; ahd_power_state_change(ahd, AHD_POWER_STATE_D0); error = ahd_pci_map_registers(ahd); if (error != 0) return (error); /* * If we need to support high memory, enable dual * address cycles. This bit must be set to enable * high address bit generation even if we are on a * 64bit bus (PCI64BIT set in devconfig). */ if ((ahd->flags & (AHD_39BIT_ADDRESSING|AHD_64BIT_ADDRESSING)) != 0) { uint32_t devconfig; if (bootverbose) printf("%s: Enabling 39Bit Addressing\n", ahd_name(ahd)); devconfig = ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4); devconfig |= DACEN; ahd_pci_write_config(ahd->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); } /* Ensure busmastering is enabled */ command = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2); command |= PCIM_CMD_BUSMASTEREN; ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, /*bytes*/2); error = ahd_softc_init(ahd); if (error != 0) return (error); ahd->bus_intr = ahd_pci_intr; error = ahd_reset(ahd, /*reinit*/FALSE); if (error != 0) return (ENXIO); ahd->pci_cachesize = ahd_pci_read_config(ahd->dev_softc, CSIZE_LATTIME, /*bytes*/1) & CACHESIZE; ahd->pci_cachesize *= 4; ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); /* See if we have a SEEPROM and perform auto-term */ error = ahd_check_extport(ahd); if (error != 0) return (error); /* Core initialization */ error = ahd_init(ahd); if (error != 0) return (error); /* * Allow interrupts now that we are completely setup. */ error = ahd_pci_map_int(ahd); if (!error) ahd->init_level++; return error; }
int ahd_pci_config(struct ahd_softc *ahd, const struct ahd_pci_identity *entry) { struct scb_data *shared_scb_data; u_int command; uint32_t devconfig; uint16_t subvendor; int error; shared_scb_data = NULL; ahd->description = entry->name; subvendor = ahd_pci_read_config(ahd->dev_softc, PCIR_SUBVEND_0, 2); if (subvendor == SUBID_HP) ahd->flags |= AHD_HP_BOARD; error = entry->setup(ahd); if (error != 0) return (error); devconfig = ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, 4); if ((devconfig & PCIXINITPAT) == PCIXINIT_PCI33_66) { ahd->chip |= AHD_PCI; ahd->bugs &= ~AHD_PCIX_BUG_MASK; } else { ahd->chip |= AHD_PCIX; } ahd->bus_description = pci_bus_modes[PCI_BUS_MODES_INDEX(devconfig)]; ahd_power_state_change(ahd, AHD_POWER_STATE_D0); error = ahd_pci_map_registers(ahd); if (error != 0) return (error); if ((ahd->flags & (AHD_39BIT_ADDRESSING|AHD_64BIT_ADDRESSING)) != 0) { if (bootverbose) printf("%s: Enabling 39Bit Addressing\n", ahd_name(ahd)); devconfig = ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, 4); devconfig |= DACEN; ahd_pci_write_config(ahd->dev_softc, DEVCONFIG, devconfig, 4); } command = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, 2); command |= PCIM_CMD_BUSMASTEREN; ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, 2); error = ahd_softc_init(ahd); if (error != 0) return (error); ahd->bus_intr = ahd_pci_intr; error = ahd_reset(ahd, FALSE); if (error != 0) return (ENXIO); ahd->pci_cachesize = ahd_pci_read_config(ahd->dev_softc, CSIZE_LATTIME, 1) & CACHESIZE; ahd->pci_cachesize *= 4; ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); error = ahd_check_extport(ahd); if (error != 0) return (error); error = ahd_init(ahd); if (error != 0) return (error); ahd->init_level++; return ahd_pci_map_int(ahd); }