static void cs4280_attach(device_t parent, device_t self, void *aux) { struct cs428x_softc *sc; struct pci_attach_args *pa; pci_chipset_tag_t pc; const struct cs4280_card_t *cs_card; char const *intrstr; const char *vendor, *product; pcireg_t reg; uint32_t mem; int error; char intrbuf[PCI_INTRSTR_LEN]; sc = device_private(self); sc->sc_dev = self; pa = (struct pci_attach_args *)aux; pc = pa->pa_pc; pci_aprint_devinfo(pa, "Audio controller"); cs_card = cs4280_identify_card(pa); if (cs_card != NULL) { vendor = pci_findvendor(cs_card->id); product = pci_findproduct(cs_card->id); if (vendor == NULL) aprint_normal_dev(sc->sc_dev, "vendor 0x%04x product 0x%04x\n", PCI_VENDOR(cs_card->id), PCI_PRODUCT(cs_card->id)); else if (product == NULL) aprint_normal_dev(sc->sc_dev, "%s product 0x%04x\n", vendor, PCI_PRODUCT(cs_card->id)); else aprint_normal_dev(sc->sc_dev, "%s %s\n", vendor, product); sc->sc_flags = cs_card->flags; } else { sc->sc_flags = CS428X_FLAG_NONE; } sc->sc_pc = pa->pa_pc; sc->sc_pt = pa->pa_tag; /* Map I/O register */ if (pci_mapreg_map(pa, PCI_BA0, PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->ba0t, &sc->ba0h, NULL, NULL)) { aprint_error_dev(sc->sc_dev, "can't map BA0 space\n"); return; } if (pci_mapreg_map(pa, PCI_BA1, PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->ba1t, &sc->ba1h, NULL, NULL)) { aprint_error_dev(sc->sc_dev, "can't map BA1 space\n"); return; } sc->sc_dmatag = pa->pa_dmat; /* power up chip */ if ((error = pci_activate(pa->pa_pc, pa->pa_tag, self, pci_activate_null)) && error != EOPNOTSUPP) { aprint_error_dev(sc->sc_dev, "cannot activate %d\n", error); return; } /* Enable the device (set bus master flag) */ 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); /* LATENCY_TIMER setting */ mem = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG); if ( PCI_LATTIMER(mem) < 32 ) { mem &= 0xffff00ff; mem |= 0x00002000; pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, mem); } /* CLKRUN hack initialization */ cs4280_clkrun_hack_init(sc); /* Map and establish the interrupt. */ if (pci_intr_map(pa, &sc->intrh)) { aprint_error_dev(sc->sc_dev, "couldn't map interrupt\n"); return; } intrstr = pci_intr_string(pc, sc->intrh, intrbuf, sizeof(intrbuf)); mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO); sc->sc_ih = pci_intr_establish(sc->sc_pc, sc->intrh, IPL_AUDIO, cs4280_intr, sc); if (sc->sc_ih == NULL) { aprint_error_dev(sc->sc_dev, "couldn't establish interrupt"); if (intrstr != NULL) aprint_error(" at %s", intrstr); aprint_error("\n"); mutex_destroy(&sc->sc_lock); mutex_destroy(&sc->sc_intr_lock); return; } aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr); /* Initialization */ if(cs4280_init(sc, 1) != 0) { mutex_destroy(&sc->sc_lock); mutex_destroy(&sc->sc_intr_lock); return; } sc->type = TYPE_CS4280; sc->halt_input = cs4280_halt_input; sc->halt_output = cs4280_halt_output; /* setup buffer related parameters */ sc->dma_size = CS4280_DCHUNK; sc->dma_align = CS4280_DALIGN; sc->hw_blocksize = CS4280_ICHUNK; /* AC 97 attachment */ sc->host_if.arg = sc; sc->host_if.attach = cs428x_attach_codec; sc->host_if.read = cs4280_read_codec; sc->host_if.write = cs4280_write_codec; #if 0 sc->host_if.reset = cs4280_reset_codec; #else sc->host_if.reset = NULL; #endif sc->host_if.flags = cs4280_flags_codec; if (ac97_attach(&sc->host_if, self, &sc->sc_lock) != 0) { aprint_error_dev(sc->sc_dev, "ac97_attach failed\n"); return; } audio_attach_mi(&cs4280_hw_if, sc, sc->sc_dev); #if NMIDI > 0 midi_attach_mi(&cs4280_midi_hw_if, sc, sc->sc_dev); #endif if (!pmf_device_register(self, cs4280_suspend, cs4280_resume)) aprint_error_dev(self, "couldn't establish power handler\n"); }
void cs4280_attach(struct device *parent, struct device *self, void *aux) { struct cs4280_softc *sc = (struct cs4280_softc *) self; struct pci_attach_args *pa = (struct pci_attach_args *) aux; pci_chipset_tag_t pc = pa->pa_pc; char const *intrstr; pci_intr_handle_t ih; u_int32_t mem; /* Map I/O register */ if (pci_mapreg_map(pa, CSCC_PCI_BA0, PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->ba0t, &sc->ba0h, NULL, NULL, 0)) { printf(": can't map BA0 space\n"); return; } if (pci_mapreg_map(pa, CSCC_PCI_BA1, PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->ba1t, &sc->ba1h, NULL, NULL, 0)) { printf(": can't map BA1 space\n"); return; } sc->sc_dmatag = pa->pa_dmat; /* Get out of power save mode if needed. */ pci_set_powerstate(pc, pa->pa_tag, PCI_PMCSR_STATE_D0); /* LATENCY_TIMER setting */ mem = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG); if ( PCI_LATTIMER(mem) < 32 ) { mem &= 0xffff00ff; mem |= 0x00002000; pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, mem); } /* Map and establish the interrupt. */ if (pci_intr_map(pa, &ih)) { printf(": couldn't map interrupt\n"); return; } intrstr = pci_intr_string(pc, ih); sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO | IPL_MPSAFE, cs4280_intr, sc, sc->sc_dev.dv_xname); if (sc->sc_ih == NULL) { printf(": couldn't establish interrupt"); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); return; } printf(": %s\n", intrstr); /* Initialization */ if (cs4280_init(sc, 1) != 0) return; mountroothook_establish(cs4280_attachhook, sc); /* AC 97 attachement */ sc->host_if.arg = sc; sc->host_if.attach = cs4280_attach_codec; sc->host_if.read = cs4280_read_codec; sc->host_if.write = cs4280_write_codec; sc->host_if.reset = cs4280_reset_codec; if (ac97_attach(&sc->host_if) != 0) { printf("%s: ac97_attach failed\n", sc->sc_dev.dv_xname); return; } }