static void zapm_attach(device_t parent, device_t self, void *aux) { struct zapm_softc *sc = device_private(self); struct apmdev_attach_args aaa; sc->sc_dev = self; aprint_normal(": pseudo power management module\n"); aprint_naive("\n"); /* machine-depent part */ callout_init(&sc->sc_cyclic_poll, 0); callout_setfunc(&sc->sc_cyclic_poll, zapm_cyclic, sc); callout_init(&sc->sc_discharge_poll, 0); callout_setfunc(&sc->sc_discharge_poll, zapm_poll, sc); mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_NONE); if (ZAURUS_ISC1000 || ZAURUS_ISC3000) { sc->sc_ac_detect_pin = GPIO_AC_IN_C3000; sc->sc_batt_cover_pin = GPIO_BATT_COVER_C3000; sc->sc_charge_comp_pin = GPIO_CHRG_CO_C3000; } else { /* XXX */ return; } pxa2x0_gpio_set_function(sc->sc_ac_detect_pin, GPIO_IN); pxa2x0_gpio_set_function(sc->sc_charge_comp_pin, GPIO_IN); pxa2x0_gpio_set_function(sc->sc_batt_cover_pin, GPIO_IN); (void)pxa2x0_gpio_intr_establish(sc->sc_ac_detect_pin, IST_EDGE_BOTH, IPL_BIO, zapm_acintr, sc); (void)pxa2x0_gpio_intr_establish(sc->sc_charge_comp_pin, IST_EDGE_BOTH, IPL_BIO, zapm_bcintr, sc); /* machine-independent part */ sc->events = 0; sc->power_state = APM_SYS_READY; sc->battery_state = APM_BATT_FLAG_UNKNOWN; sc->ac_state = APM_AC_UNKNOWN; sc->battery_life = APM_BATT_LIFE_UNKNOWN; sc->minutes_left = 0; sc->sc_standby_hook = config_hook(CONFIG_HOOK_PMEVENT, CONFIG_HOOK_PMEVENT_STANDBYREQ, CONFIG_HOOK_EXCLUSIVE, zapm_hook, sc); sc->sc_suspend_hook = config_hook(CONFIG_HOOK_PMEVENT, CONFIG_HOOK_PMEVENT_SUSPENDREQ, CONFIG_HOOK_EXCLUSIVE, zapm_hook, sc); sc->sc_battery_hook = config_hook(CONFIG_HOOK_PMEVENT, CONFIG_HOOK_PMEVENT_BATTERY, CONFIG_HOOK_SHARE, zapm_hook, sc); sc->sc_ac_hook = config_hook(CONFIG_HOOK_PMEVENT, CONFIG_HOOK_PMEVENT_AC, CONFIG_HOOK_SHARE, zapm_hook, sc); aaa.accessops = &zapm_accessops; aaa.accesscookie = sc; aaa.apm_detail = 0x0102; sc->sc_apmdev = config_found_ia(self, "apmdevif", &aaa, apmprint); if (sc->sc_apmdev != NULL) { zapm_poll1(sc, 0); callout_schedule(&sc->sc_cyclic_poll, CYCLIC_TIME); } }
static void siisata_pci_attach(device_t parent, device_t self, void *aux) { struct pci_attach_args *pa = aux; struct siisata_pci_softc *psc = device_private(self); struct siisata_softc *sc = &psc->si_sc; char devinfo[256]; const char *intrstr; pci_intr_handle_t intrhandle; pcireg_t csr, memtype; const struct siisata_pci_product *spp; void *ih; bus_space_tag_t memt; bus_space_handle_t memh; uint32_t gcreg; int memh_valid; bus_size_t grsize, prsize; sc->sc_atac.atac_dev = self; psc->sc_pc = pa->pa_pc; psc->sc_pcitag = pa->pa_tag; pci_devinfo(pa->pa_id, pa->pa_class, 1, devinfo, sizeof(devinfo)); aprint_naive(": SATA-II HBA\n"); aprint_normal(": %s\n", devinfo); /* map bar0 */ #if 1 memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, SIISATA_PCI_BAR0); #else memtype = PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT; #endif 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, SIISATA_PCI_BAR0, memtype, 0, &memt, &memh, NULL, &grsize) == 0); break; default: memh_valid = 0; } if (memh_valid) { sc->sc_grt = memt; sc->sc_grh = memh; } else { aprint_error("%s: unable to map device global registers\n", SIISATANAME(sc)); return; } /* map bar1 */ #if 1 memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, SIISATA_PCI_BAR1); #else memtype = PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT; #endif 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, SIISATA_PCI_BAR1, memtype, 0, &memt, &memh, NULL, &prsize) == 0); break; default: memh_valid = 0; } if (memh_valid) { sc->sc_prt = memt; sc->sc_prh = memh; } else { bus_space_unmap(sc->sc_grt, sc->sc_grh, grsize); aprint_error("%s: unable to map device port registers\n", SIISATANAME(sc)); return; } if (pci_dma64_available(pa)) { sc->sc_dmat = pa->pa_dmat64; sc->sc_have_dma64 = 1; aprint_debug("64-bit PCI DMA available\n"); } else { sc->sc_dmat = pa->pa_dmat; sc->sc_have_dma64 = 0; } /* map interrupt */ if (pci_intr_map(pa, &intrhandle) != 0) { bus_space_unmap(sc->sc_grt, sc->sc_grh, grsize); bus_space_unmap(sc->sc_prt, sc->sc_prh, prsize); aprint_error("%s: couldn't map interrupt\n", SIISATANAME(sc)); return; } intrstr = pci_intr_string(pa->pa_pc, intrhandle); ih = pci_intr_establish(pa->pa_pc, intrhandle, IPL_BIO, siisata_intr, sc); if (ih == NULL) { bus_space_unmap(sc->sc_grt, sc->sc_grh, grsize); bus_space_unmap(sc->sc_prt, sc->sc_prh, prsize); aprint_error("%s: couldn't establish interrupt" "at %s\n", SIISATANAME(sc), intrstr); return; } aprint_normal("%s: interrupting at %s\n", SIISATANAME(sc), intrstr ? intrstr : "unknown interrupt"); /* fill in number of ports on this device */ spp = siisata_pci_lookup(pa); if (spp != NULL) { sc->sc_atac.atac_nchannels = spp->spp_ports; sc->sc_chip = spp->spp_chip; } else /* _match() should prevent us from getting here */ panic("siisata: the universe might be falling apart!\n"); gcreg = GRREAD(sc, GR_GC); aprint_normal("%s: SiI%d on ", SIISATANAME(sc), sc->sc_chip); if (sc->sc_chip == 3124) { aprint_normal("%d-bit, ", (gcreg & GR_GC_REQ64) ? 64 : 32); switch (gcreg & (GR_GC_DEVSEL | GR_GC_STOP | GR_GC_TRDY)) { case 0: aprint_normal("%d", (gcreg & GR_GC_M66EN) ? 66 : 33); break; case GR_GC_TRDY: aprint_normal("%d", 66); break; case GR_GC_STOP: aprint_normal("%d", 100); break; case GR_GC_STOP | GR_GC_TRDY: aprint_normal("%d", 133); break; default: break; } aprint_normal("MHz PCI%s bus.", (gcreg & (GR_GC_DEVSEL | GR_GC_STOP | GR_GC_TRDY)) ? "-X" : ""); } else { /* XXX - but only x1 devices so far */ aprint_normal("PCI-Express x1 port."); } if (gcreg & GR_GC_3GBPS) aprint_normal(" 3.0Gb/s capable.\n"); else aprint_normal("\n"); /* enable bus mastering in case the firmware didn't */ csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); csr |= PCI_COMMAND_MASTER_ENABLE; csr |= PCI_COMMAND_MEM_ENABLE; pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, csr); siisata_attach(sc); if (!pmf_device_register(self, NULL, siisata_pci_resume)) aprint_error_dev(self, "couldn't establish power handler\n"); }
static void seeprom_attach(device_t parent, device_t self, void *aux) { struct seeprom_softc *sc = device_private(self); struct i2c_attach_args *ia = aux; sc->sc_tag = ia->ia_tag; sc->sc_address = ia->ia_addr; sc->sc_dev = self; if (ia->ia_name != NULL) { aprint_naive(": %s", ia->ia_name); aprint_normal(": %s", ia->ia_name); } else { aprint_naive(": EEPROM"); aprint_normal(": AT24Cxx or compatible EEPROM"); } /* * The AT24C01A/02/04/08/16 EEPROMs use a 1 byte command * word to select the offset into the EEPROM page. The * AT24C04/08/16 decode fewer of the i2c address bits, * using the bottom 1, 2, or 3 to select the 256-byte * super-page. * * The AT24C32/64/128/256/512 EEPROMs use a 2 byte command * word and decode all of the i2c address bits. * * The AT24C1024 EEPROMs use a 2 byte command and also do bank * switching to select the proper super-page. This isn't * supported by this driver. */ if (device_cfdata(self)->cf_flags) sc->sc_size = (device_cfdata(self)->cf_flags << 7); else sc->sc_size = ia->ia_size; switch (sc->sc_size) { case 128: /* 1Kbit */ case 256: /* 2Kbit */ case 512: /* 4Kbit */ case 1024: /* 8Kbit */ case 2048: /* 16Kbit */ sc->sc_cmdlen = 1; aprint_normal(": size %d\n", sc->sc_size); break; case 4096: /* 32Kbit */ case 8192: /* 64Kbit */ case 16384: /* 128Kbit */ case 32768: /* 256Kbit */ case 65536: /* 512Kbit */ sc->sc_cmdlen = 2; aprint_normal(": size %d\n", sc->sc_size); break; default: /* * Default to 2KB. If we happen to have a 2KB * EEPROM this will allow us to access it. If we * have a smaller one, the worst that can happen * is that we end up trying to read a different * EEPROM on the bus when accessing it. * * Obviously this will not work for 4KB or 8KB * EEPROMs, but them's the breaks. */ aprint_normal("\n"); aprint_error_dev(self, "invalid size specified; " "assuming 2KB (16Kb)\n"); sc->sc_size = 2048; sc->sc_cmdlen = 1; } sc->sc_open = 0; }
void pcic_pci_attach(device_t parent, device_t self, void *aux) { struct pcic_pci_softc *psc = device_private(self); struct pcic_softc *sc = &psc->sc_pcic; struct pci_attach_args *pa = aux; pci_chipset_tag_t pc = pa->pa_pc; bus_space_tag_t memt = pa->pa_memt; bus_space_handle_t memh; const char *model; sc->dev = self; aprint_naive(": PCMCIA controller\n"); if (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0, &sc->iot, &sc->ioh, NULL, NULL)) { aprint_error(": can't map i/o space\n"); return; } /* * XXX need some memory for mapping pcmcia cards into. Ideally, this * would be completely dynamic. Practically this doesn't work, * because the extent mapper doesn't know about all the devices all * the time. With ISA we could finesse the issue by specifying the * memory region in the config line. We can't do that here, so we * cheat for now. Jason Thorpe, you are my Savior, come up with a fix * :-) */ /* Map mem space. */ if (bus_space_map(memt, 0xd0000, 0x4000, 0, &memh)) panic("pcic_pci_attach: can't map mem space"); sc->membase = 0xd0000; sc->subregionmask = (1 << (0x4000 / PCIC_MEM_PAGESIZE)) - 1; /* same deal for io allocation */ sc->iobase = 0x400; sc->iosize = 0xbff; /* end XXX */ sc->pct = &pcic_pci_functions; sc->memt = memt; sc->memh = memh; switch (PCI_PRODUCT(pa->pa_id)) { case PCI_PRODUCT_CIRRUS_CL_PD6729: model = "Cirrus Logic PD6729 PCMCIA controller"; break; default: model = "Model unknown"; break; } aprint_normal(": %s\n", model); /* Enable the card. */ pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) | PCI_COMMAND_MASTER_ENABLE); pcic_attach(sc); /* * Check to see if we're using PCI or ISA interrupts. I don't * know of any i386 systems that use the 6729 in PCI interrupt * mode, but maybe when the PCMCIA code runs on other platforms * we'll need to fix this. */ pcic_write(&sc->handle[0], PCIC_CIRRUS_EXTENDED_INDEX, PCIC_CIRRUS_EXT_CONTROL_1); if ((pcic_read(&sc->handle[0], PCIC_CIRRUS_EXTENDED_DATA) & PCIC_CIRRUS_EXT_CONTROL_1_PCI_INTR_MASK)) { aprint_error_dev(self, "PCI interrupts not supported\n"); return; } psc->intr_est = pcic_pci_machdep_intr_est(pc); sc->irq = -1; #if 0 /* Map and establish the interrupt. */ sc->ih = pcic_pci_machdep_pcic_intr_establish(sc, pcic_intr); if (sc->ih == NULL) { aprint_error_dev(self, "couldn't map interrupt\n"); return; } #endif /* * Defer configuration of children until ISA has had its chance * to use up whatever IO space and IRQs it wants. XXX This will * only work if ISA is attached to a pcib, AND the PCI probe finds * and defers the ISA attachment before this one. */ config_defer(self, pcic_pci_callback); config_interrupts(self, pcic_isa_config_interrupts); }
void uipaq_attach(device_t parent, device_t self, void *aux) { struct uipaq_softc *sc = device_private(self); struct usb_attach_arg *uaa = aux; usbd_device_handle dev = uaa->device; usbd_interface_handle iface; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; char *devinfop; const char *devname = device_xname(self); int i; usbd_status err; struct ucom_attach_args uca; DPRINTFN(10,("\nuipaq_attach: sc=%p\n", sc)); sc->sc_dev = self; aprint_naive("\n"); aprint_normal("\n"); devinfop = usbd_devinfo_alloc(dev, 0); aprint_normal_dev(self, "%s\n", devinfop); usbd_devinfo_free(devinfop); /* Move the device into the configured state. */ err = usbd_set_config_no(dev, UIPAQ_CONFIG_NO, 1); if (err) { aprint_error_dev(self, "failed to set configuration" ", err=%s\n", usbd_errstr(err)); goto bad; } err = usbd_device2interface_handle(dev, UIPAQ_IFACE_INDEX, &iface); if (err) { aprint_error("\n%s: failed to get interface, err=%s\n", devname, usbd_errstr(err)); goto bad; } sc->sc_flags = uipaq_lookup(uaa->vendor, uaa->product)->uv_flags; id = usbd_get_interface_descriptor(iface); sc->sc_udev = dev; sc->sc_iface = iface; uca.ibufsize = UIPAQIBUFSIZE; uca.obufsize = UIPAQOBUFSIZE; uca.ibufsizepad = UIPAQIBUFSIZE; uca.opkthdrlen = 0; uca.device = dev; uca.iface = iface; uca.methods = &uipaq_methods; uca.arg = sc; uca.portno = UCOM_UNK_PORTNO; uca.info = "Generic"; /* err = uipaq_init(sc); if (err) { printf("%s: init failed, %s\n", device_xname(sc->sc_dev), usbd_errstr(err)); goto bad; }*/ usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); uca.bulkin = uca.bulkout = -1; for (i=0; i<id->bNumEndpoints; i++) { ed = usbd_interface2endpoint_descriptor(iface, i); if (ed == NULL) { aprint_error_dev(self, "no endpoint descriptor for %d\n", i); goto bad; } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { uca.bulkin = ed->bEndpointAddress; } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { uca.bulkout = ed->bEndpointAddress; } } if (uca.bulkin == -1 || uca.bulkout == -1) { aprint_error_dev(self, "no proper endpoints found (%d,%d) \n", uca.bulkin, uca.bulkout); return; } sc->sc_subdev = config_found_sm_loc(self, "ucombus", NULL, &uca, ucomprint, ucomsubmatch); return; bad: DPRINTF(("uipaq_attach: ATTACH ERROR\n")); sc->sc_dying = 1; return; }
static void aps_attach(device_t parent, device_t self, void *aux) { struct aps_softc *sc = device_private(self); struct isa_attach_args *ia = aux; int iobase, i; sc->sc_iot = ia->ia_iot; iobase = ia->ia_io[0].ir_addr; if (bus_space_map(sc->sc_iot, iobase, APS_ADDR_SIZE, 0, &sc->sc_ioh)) { aprint_error(": can't map i/o space\n"); return; } aprint_naive("\n"); aprint_normal("\n"); if (!aps_init(sc)) { aprint_error_dev(self, "failed to initialise\n"); goto out; } /* Initialize sensors */ #define INITDATA(idx, unit, string) \ sc->sc_sensor[idx].units = unit; \ strlcpy(sc->sc_sensor[idx].desc, string, \ sizeof(sc->sc_sensor[idx].desc)); INITDATA(APS_SENSOR_XACCEL, ENVSYS_INTEGER, "X_ACCEL"); INITDATA(APS_SENSOR_YACCEL, ENVSYS_INTEGER, "Y_ACCEL"); INITDATA(APS_SENSOR_TEMP1, ENVSYS_STEMP, "TEMP_1"); INITDATA(APS_SENSOR_TEMP2, ENVSYS_STEMP, "TEMP_2"); INITDATA(APS_SENSOR_XVAR, ENVSYS_INTEGER, "X_VAR"); INITDATA(APS_SENSOR_YVAR, ENVSYS_INTEGER, "Y_VAR"); INITDATA(APS_SENSOR_KBACT, ENVSYS_INDICATOR, "Keyboard Active"); INITDATA(APS_SENSOR_MSACT, ENVSYS_INDICATOR, "Mouse Active"); INITDATA(APS_SENSOR_LIDOPEN, ENVSYS_INDICATOR, "Lid Open"); sc->sc_sme = sysmon_envsys_create(); for (i = 0; i < APS_NUM_SENSORS; i++) { sc->sc_sensor[i].state = ENVSYS_SVALID; if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[i])) { sysmon_envsys_destroy(sc->sc_sme); goto out; } } /* * Register with the sysmon_envsys(9) framework. */ sc->sc_sme->sme_name = device_xname(self); sc->sc_sme->sme_flags = SME_DISABLE_REFRESH; if ((i = sysmon_envsys_register(sc->sc_sme))) { aprint_error_dev(self, "unable to register with sysmon (%d)\n", i); sysmon_envsys_destroy(sc->sc_sme); goto out; } if (!pmf_device_register(self, aps_suspend, aps_resume)) aprint_error_dev(self, "couldn't establish power handler\n"); /* Refresh sensor data every 0.5 seconds */ callout_init(&sc->sc_callout, 0); callout_setfunc(&sc->sc_callout, aps_refresh, sc); callout_schedule(&sc->sc_callout, (hz) / 2); aprint_normal_dev(self, "Thinkpad Active Protection System\n"); return; out: bus_space_unmap(sc->sc_iot, sc->sc_ioh, APS_ADDR_SIZE); }
/* * Attach a found zs. * * Match slave number to zs unit number, so that misconfiguration will * not set up the keyboard as ttya, etc. */ void zs_ap_attach(device_t parent, device_t self, void *aux) { struct zsc_softc *zsc = device_private(self); struct apbus_attach_args *apa = aux; struct zsc_attach_args zsc_args; volatile struct zschan *zc; struct zs_chanstate *cs; int s, zs_unit, channel; volatile u_int *txBfifo = (void *)(apa->apa_hwbase + PORTB_XPORT); volatile u_int *rxBfifo = (void *)(apa->apa_hwbase + PORTB_RPORT); volatile u_int *txAfifo = (void *)(apa->apa_hwbase + PORTA_XPORT); volatile u_int *rxAfifo = (void *)(apa->apa_hwbase + PORTA_RPORT); volatile u_int *portBctl = (void *)(apa->apa_hwbase + PORTB_OFFSET); volatile u_int *portActl = (void *)(apa->apa_hwbase + PORTA_OFFSET); volatile u_int *esccregs = (void *)(apa->apa_hwbase + ESCC_REG); zsc->zsc_dev = self; zs_unit = device_unit(self); zsaddr[zs_unit] = (void *)apa->apa_hwbase; aprint_normal(" slot%d addr 0x%lx\n", apa->apa_slotno, apa->apa_hwbase); txAfifo[DMA_MODE_REG] = rxAfifo[DMA_MODE_REG] = DMA_EXTRDY; txBfifo[DMA_MODE_REG] = rxBfifo[DMA_MODE_REG] = DMA_EXTRDY; /* assert DTR */ /* XXX */ portBctl[PORT_CTL] = portActl[PORT_CTL] = PORTCTL_DTR; /* select RS-232C (ch1 only) */ portActl[PORT_SEL] = PORTSEL_RS232C; /* enable SCC interrupts */ esccregs[ESCCREG_INTMASK] = INTMASK_SCC; zs_delay = zs_ap_delay; /* * Initialize software state for each channel. */ for (channel = 0; channel < 2; channel++) { zsc_args.channel = channel; zsc_args.hwflags = zs_hwflags[zs_unit][channel]; cs = &zsc->zsc_cs_store[channel]; zsc->zsc_cs[channel] = cs; zs_lock_init(cs); cs->cs_channel = channel; cs->cs_private = NULL; cs->cs_ops = &zsops_null; cs->cs_brg_clk = PCLK / 16; zc = zs_get_chan_addr(zs_unit, channel); cs->cs_reg_csr = &zc->zc_csr; cs->cs_reg_data = &zc->zc_data; memcpy(cs->cs_creg, zs_init_reg, 16); memcpy(cs->cs_preg, zs_init_reg, 16); /* XXX: Get these from the EEPROM instead? */ /* XXX: See the mvme167 code. Better. */ if (zsc_args.hwflags & ZS_HWFLAG_CONSOLE) cs->cs_defspeed = zs_get_speed(cs); else cs->cs_defspeed = zs_defspeed; cs->cs_defcflag = zs_def_cflag; /* Make these correspond to cs_defcflag (-crtscts) */ cs->cs_rr0_dcd = ZSRR0_DCD; cs->cs_rr0_cts = 0; cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS; cs->cs_wr5_rts = 0; /* * Clear the master interrupt enable. * The INTENA is common to both channels, * so just do it on the A channel. */ if (channel == 0) { zs_write_reg(cs, 9, 0); } /* * Look for a child driver for this channel. * The child attach will setup the hardware. */ if (!config_found(self, (void *)&zsc_args, zs_print)) { /* No sub-driver. Just reset it. */ uint8_t reset = (channel == 0) ? ZSWR9_A_RESET : ZSWR9_B_RESET; s = splhigh(); zs_write_reg(cs, 9, reset); splx(s); } } /* * Now safe to install interrupt handlers. */ zsc->zsc_si = softint_establish(SOFTINT_SERIAL, (void (*)(void *))zsc_intr_soft, zsc); apbus_intr_establish(1, /* interrupt level ( 0 or 1 ) */ NEWS5000_INT1_SCC, 0, /* priority */ zshard_ap, zsc, apa->apa_name, apa->apa_ctlnum); /* XXX; evcnt_attach() ? */ #if 0 { u_int x; /* determine SCC/ESCC type */ x = zs_read_reg(cs, 15); zs_write_reg(cs, 15, x | ZSWR15_ENABLE_ENHANCED); if (zs_read_reg(cs, 15) & ZSWR15_ENABLE_ENHANCED) { /* ESCC Z85230 */ zs_write_reg(cs, 7, ZSWR7P_EXTEND_READ | ZSWR7P_TX_FIFO); } } #endif /* * Set the master interrupt enable and interrupt vector. * (common to both channels, do it on A) */ cs = zsc->zsc_cs[0]; s = splhigh(); /* interrupt vector */ zs_write_reg(cs, 2, zs_init_reg[2]); /* master interrupt control (enable) */ zs_write_reg(cs, 9, zs_init_reg[9]); splx(s); }
static void auvia_attach(device_t parent, device_t self, void *aux) { struct pci_attach_args *pa; struct auvia_softc *sc; const char *intrstr; pci_chipset_tag_t pc; pcitag_t pt; pci_intr_handle_t ih; pcireg_t pr; int r; const char *revnum; /* VT823xx revision number */ char intrbuf[PCI_INTRSTR_LEN]; pa = aux; sc = device_private(self); sc->sc_dev = self; intrstr = NULL; pc = pa->pa_pc; pt = pa->pa_tag; revnum = NULL; aprint_naive(": Audio controller\n"); sc->sc_play.sc_base = AUVIA_PLAY_BASE; sc->sc_record.sc_base = AUVIA_RECORD_BASE; if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_VIATECH_VT8233_AC97) { sc->sc_flags |= AUVIA_FLAGS_VT8233; sc->sc_play.sc_base = VIA8233_MP_BASE; sc->sc_record.sc_base = VIA8233_WR_BASE; } if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, &sc->sc_iot, &sc->sc_ioh, NULL, &sc->sc_iosize)) { aprint_error(": can't map i/o space\n"); return; } sc->sc_dmat = pa->pa_dmat; sc->sc_pc = pc; sc->sc_pt = pt; r = PCI_REVISION(pa->pa_class); if (sc->sc_flags & AUVIA_FLAGS_VT8233) { snprintf(sc->sc_revision, sizeof(sc->sc_revision), "0x%02X", r); switch(r) { case VIA_REV_8233PRE: /* same as 8233, but should not be in the market */ revnum = "3-Pre"; break; case VIA_REV_8233C: /* 2 rec, 4 pb, 1 multi-pb */ revnum = "3C"; break; case VIA_REV_8233: /* 2 rec, 4 pb, 1 multi-pb, spdif */ revnum = "3"; break; case VIA_REV_8233A: /* 1 rec, 1 multi-pb, spdif */ revnum = "3A"; break; default: break; } if (r >= VIA_REV_8237) revnum = "7"; else if (r >= VIA_REV_8235) /* 2 rec, 4 pb, 1 multi-pb, spdif */ revnum = "5"; aprint_normal(": VIA Technologies VT823%s AC'97 Audio " "(rev %s)\n", revnum, sc->sc_revision); } else { sc->sc_revision[1] = '\0'; if (r == 0x20) { sc->sc_revision[0] = 'H'; } else if ((r >= 0x10) && (r <= 0x14)) { sc->sc_revision[0] = 'A' + (r - 0x10); } else { snprintf(sc->sc_revision, sizeof(sc->sc_revision), "0x%02X", r); } aprint_normal(": VIA Technologies VT82C686A AC'97 Audio " "(rev %s)\n", sc->sc_revision); } if (pci_intr_map(pa, &ih)) { aprint_error(": couldn't map interrupt\n"); bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_iosize); return; } intrstr = pci_intr_string(pc, ih, 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(pc, ih, IPL_AUDIO, auvia_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"); bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_iosize); mutex_destroy(&sc->sc_lock); mutex_destroy(&sc->sc_intr_lock); return; } aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr); /* disable SBPro compat & others */ pr = pci_conf_read(pc, pt, AUVIA_PCICONF_JUNK); pr &= ~AUVIA_PCICONF_ENABLES; /* clear compat function enables */ /* XXX what to do about MIDI, FM, joystick? */ pr |= (AUVIA_PCICONF_ACLINKENAB | AUVIA_PCICONF_ACNOTRST | AUVIA_PCICONF_ACVSR | AUVIA_PCICONF_ACSGD); pr &= ~(AUVIA_PCICONF_ACFM | AUVIA_PCICONF_ACSB); pci_conf_write(pc, pt, AUVIA_PCICONF_JUNK, pr); sc->host_if.arg = sc; sc->host_if.attach = auvia_attach_codec; sc->host_if.read = auvia_read_codec; sc->host_if.write = auvia_write_codec; sc->host_if.reset = auvia_reset_codec; sc->host_if.spdif_event = auvia_spdif_event; if ((r = ac97_attach(&sc->host_if, self, &sc->sc_lock)) != 0) { aprint_error_dev(sc->sc_dev, "can't attach codec (error 0x%X)\n", r); pci_intr_disestablish(pc, sc->sc_ih); bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_iosize); mutex_destroy(&sc->sc_lock); mutex_destroy(&sc->sc_intr_lock); return; } /* setup audio_format */ memcpy(sc->sc_formats, auvia_formats, sizeof(auvia_formats)); mutex_enter(&sc->sc_lock); if (sc->sc_play.sc_base != VIA8233_MP_BASE || !AC97_IS_4CH(sc->codec_if)) { AUFMT_INVALIDATE(&sc->sc_formats[AUVIA_FORMATS_4CH_8]); AUFMT_INVALIDATE(&sc->sc_formats[AUVIA_FORMATS_4CH_16]); } if (sc->sc_play.sc_base != VIA8233_MP_BASE || !AC97_IS_6CH(sc->codec_if)) { AUFMT_INVALIDATE(&sc->sc_formats[AUVIA_FORMATS_6CH_8]); AUFMT_INVALIDATE(&sc->sc_formats[AUVIA_FORMATS_6CH_16]); } if (AC97_IS_FIXED_RATE(sc->codec_if)) { for (r = 0; r < AUVIA_NFORMATS; r++) { sc->sc_formats[r].frequency_type = 1; sc->sc_formats[r].frequency[0] = 48000; } } mutex_exit(&sc->sc_lock); if (0 != auconv_create_encodings(sc->sc_formats, AUVIA_NFORMATS, &sc->sc_encodings)) { mutex_enter(&sc->sc_lock); sc->codec_if->vtbl->detach(sc->codec_if); mutex_exit(&sc->sc_lock); pci_intr_disestablish(pc, sc->sc_ih); bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_iosize); mutex_destroy(&sc->sc_lock); mutex_destroy(&sc->sc_intr_lock); aprint_error_dev(sc->sc_dev, "can't create encodings\n"); return; } if (0 != auconv_create_encodings(auvia_spdif_formats, AUVIA_SPDIF_NFORMATS, &sc->sc_spdif_encodings)) { mutex_enter(&sc->sc_lock); sc->codec_if->vtbl->detach(sc->codec_if); mutex_exit(&sc->sc_lock); pci_intr_disestablish(pc, sc->sc_ih); bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_iosize); mutex_destroy(&sc->sc_lock); mutex_destroy(&sc->sc_intr_lock); aprint_error_dev(sc->sc_dev, "can't create spdif encodings\n"); return; } if (!pmf_device_register(self, NULL, auvia_resume)) aprint_error_dev(self, "couldn't establish power handler\n"); audio_attach_mi(&auvia_hw_if, sc, sc->sc_dev); mutex_enter(&sc->sc_lock); sc->codec_if->vtbl->unlock(sc->codec_if); mutex_exit(&sc->sc_lock); return; }
/* * Attach the hypervisor. */ void hypervisor_attach(device_t parent, device_t self, void *aux) { #if NPCI >0 #ifdef PCI_BUS_FIXUP int pci_maxbus = 0; #endif #endif /* NPCI */ union hypervisor_attach_cookie hac; char xen_extra_version[XEN_EXTRAVERSION_LEN]; static char xen_version_string[20]; int rc; const struct sysctlnode *node = NULL; xenkernfs_init(); xen_version = HYPERVISOR_xen_version(XENVER_version, NULL); memset(xen_extra_version, 0, sizeof(xen_extra_version)); HYPERVISOR_xen_version(XENVER_extraversion, xen_extra_version); rc = snprintf(xen_version_string, 20, "%d.%d%s", XEN_MAJOR(xen_version), XEN_MINOR(xen_version), xen_extra_version); aprint_normal(": Xen version %s\n", xen_version_string); if (rc >= 20) aprint_debug(": xen_version_string truncated\n"); sysctl_createv(NULL, 0, NULL, &node, 0, CTLTYPE_NODE, "xen", SYSCTL_DESCR("Xen top level node"), NULL, 0, NULL, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL); if (node != NULL) { sysctl_createv(NULL, 0, &node, NULL, CTLFLAG_READONLY, CTLTYPE_STRING, "version", SYSCTL_DESCR("Xen hypervisor version"), NULL, 0, xen_version_string, 0, CTL_CREATE, CTL_EOL); } aprint_verbose_dev(self, "features: "); #define XEN_TST_F(n) \ if (xen_feature(XENFEAT_##n)) \ aprint_verbose(" %s", #n); XEN_TST_F(writable_page_tables); XEN_TST_F(writable_descriptor_tables); XEN_TST_F(auto_translated_physmap); XEN_TST_F(supervisor_mode_kernel); XEN_TST_F(pae_pgdir_above_4gb); XEN_TST_F(mmu_pt_update_preserve_ad); XEN_TST_F(highmem_assist); XEN_TST_F(gnttab_map_avail_bits); XEN_TST_F(hvm_callback_vector); XEN_TST_F(hvm_safe_pvclock); XEN_TST_F(hvm_pirqs); #undef XEN_TST_F aprint_verbose("\n"); xengnt_init(); events_init(); memset(&hac, 0, sizeof(hac)); hac.hac_vcaa.vcaa_name = "vcpu"; hac.hac_vcaa.vcaa_caa.cpu_number = 0; hac.hac_vcaa.vcaa_caa.cpu_role = CPU_ROLE_BP; hac.hac_vcaa.vcaa_caa.cpu_func = NULL; /* See xen/x86/cpu.c:vcpu_attach() */ config_found_ia(self, "xendevbus", &hac.hac_vcaa, hypervisor_print); #ifdef MULTIPROCESSOR /* * The xenstore contains the configured number of vcpus. * The xenstore however, is not accessible until much later in * the boot sequence. We therefore bruteforce check for * allocated vcpus (See: cpu.c:vcpu_match()) by iterating * through the maximum supported by NetBSD MP. */ cpuid_t vcpuid; for (vcpuid = 1; vcpuid < maxcpus; vcpuid++) { memset(&hac, 0, sizeof(hac)); hac.hac_vcaa.vcaa_name = "vcpu"; hac.hac_vcaa.vcaa_caa.cpu_number = vcpuid; hac.hac_vcaa.vcaa_caa.cpu_role = CPU_ROLE_AP; hac.hac_vcaa.vcaa_caa.cpu_func = NULL; /* See xen/x86/cpu.c:vcpu_attach() */ if (NULL == config_found_ia(self, "xendevbus", &hac.hac_vcaa, hypervisor_vcpu_print)) { break; } } #endif /* MULTIPROCESSOR */ #if NXENBUS > 0 memset(&hac, 0, sizeof(hac)); hac.hac_xenbus.xa_device = "xenbus"; config_found_ia(self, "xendevbus", &hac.hac_xenbus, hypervisor_print); #endif #if NXENCONS > 0 memset(&hac, 0, sizeof(hac)); hac.hac_xencons.xa_device = "xencons"; config_found_ia(self, "xendevbus", &hac.hac_xencons, hypervisor_print); #endif #ifdef DOM0OPS #if NPCI > 0 #if NACPICA > 0 if (acpi_present) { memset(&hac, 0, sizeof(hac)); hac.hac_acpi.aa_iot = x86_bus_space_io; hac.hac_acpi.aa_memt = x86_bus_space_mem; hac.hac_acpi.aa_pc = NULL; hac.hac_acpi.aa_pciflags = PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY | PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | PCI_FLAGS_MWI_OKAY; hac.hac_acpi.aa_ic = &x86_isa_chipset; hac.hac_acpi.aa_dmat = &pci_bus_dma_tag; #ifdef _LP64 hac.hac_acpi.aa_dmat64 = &pci_bus_dma64_tag; #else hac.hac_acpi.aa_dmat64 = NULL; #endif /* _LP64 */ config_found_ia(self, "acpibus", &hac.hac_acpi, 0); } #endif /* NACPICA */ memset(&hac, 0, sizeof(hac)); hac.hac_pba.pba_iot = x86_bus_space_io; hac.hac_pba.pba_memt = x86_bus_space_mem; hac.hac_pba.pba_dmat = &pci_bus_dma_tag; #ifdef _LP64 hac.hac_pba.pba_dmat64 = &pci_bus_dma64_tag; #else hac.hac_pba.pba_dmat64 = NULL; #endif /* _LP64 */ hac.hac_pba.pba_flags = PCI_FLAGS_MEM_OKAY | PCI_FLAGS_IO_OKAY; hac.hac_pba.pba_bridgetag = NULL; hac.hac_pba.pba_bus = 0; #if NACPICA > 0 && defined(ACPI_SCANPCI) if (mpacpi_active) mp_pci_scan(self, &hac.hac_pba, pcibusprint); else #endif #if defined(MPBIOS) && defined(MPBIOS_SCANPCI) if (mpbios_scanned != 0) mp_pci_scan(self, &hac.hac_pba, pcibusprint); else #endif config_found_ia(self, "pcibus", &hac.hac_pba, pcibusprint); #if NACPICA > 0 if (mp_verbose) acpi_pci_link_state(); #endif #if NISA > 0 if (isa_has_been_seen == 0) { memset(&hac, 0, sizeof(hac)); hac.hac_iba._iba_busname = "isa"; hac.hac_iba.iba_iot = x86_bus_space_io; hac.hac_iba.iba_memt = x86_bus_space_mem; hac.hac_iba.iba_dmat = &isa_bus_dma_tag; hac.hac_iba.iba_ic = NULL; /* No isa DMA yet */ config_found_ia(self, "isabus", &hac.hac_iba, isabusprint); } #endif /* NISA */ #endif /* NPCI */ if (xendomain_is_privileged()) { xenprivcmd_init(); xen_shm_init(); } #endif /* DOM0OPS */ hypervisor_machdep_attach(); if (!pmf_device_register(self, hypervisor_suspend, hypervisor_resume)) aprint_error_dev(self, "couldn't establish power handler\n"); }
static void grackle_attach(device_t parent, device_t self, void *aux) { struct grackle_softc *sc = device_private(self); pci_chipset_tag_t pc = &sc->sc_pc; struct confargs *ca = aux; struct pcibus_attach_args pba; int len, node = ca->ca_node; uint32_t busrange[2]; struct ranges { uint32_t pci_hi, pci_mid, pci_lo; uint32_t host; uint32_t size_hi, size_lo; } ranges[6], *rp = ranges; aprint_normal("\n"); sc->sc_dev = self; /* PCI bus number */ if (OF_getprop(node, "bus-range", busrange, sizeof(busrange)) != 8) return; /* find i/o tag */ len = OF_getprop(node, "ranges", ranges, sizeof(ranges)); if (len == -1) return; while (len >= sizeof(ranges[0])) { if ((rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) == OFW_PCI_PHYS_HI_SPACE_IO) { sc->sc_iot.pbs_base = rp->host; sc->sc_iot.pbs_limit = rp->host + rp->size_lo; break; } len -= sizeof(ranges[0]); rp++; } sc->sc_iot.pbs_flags = _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_IO_TYPE; sc->sc_iot.pbs_offset = 0; if (ofwoea_map_space(RANGE_TYPE_PCI, RANGE_IO, node, &sc->sc_iot, "grackle io") != 0) panic("Can't init grackle io tag"); sc->sc_memt.pbs_flags = _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_MEM_TYPE; sc->sc_memt.pbs_base = 0x00000000; if (ofwoea_map_space(RANGE_TYPE_PCI, RANGE_MEM, node, &sc->sc_memt, "grackle mem") != 0) panic("Can't init grackle mem tag"); macppc_pci_get_chipset_tag(pc); pc->pc_node = node; pc->pc_addr = mapiodev(GRACKLE_ADDR, 4, false); pc->pc_data = mapiodev(GRACKLE_DATA, 4, false); pc->pc_bus = busrange[0]; pc->pc_conf_read = grackle_conf_read; pc->pc_conf_write = grackle_conf_write; pc->pc_memt = &sc->sc_memt; pc->pc_iot = &sc->sc_iot; memset(&pba, 0, sizeof(pba)); pba.pba_memt = pc->pc_memt; pba.pba_iot = pc->pc_iot; pba.pba_dmat = &pci_bus_dma_tag; pba.pba_dmat64 = NULL; pba.pba_bus = pc->pc_bus; pba.pba_bridgetag = NULL; pba.pba_pc = pc; pba.pba_flags = PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY; config_found_ia(self, "pcibus", &pba, pcibusprint); }
void ehci_arbus_attach(device_t parent, device_t self, void *aux) { ehci_softc_t *sc = device_private(self); struct arbus_attach_args * const aa = aux; void *ih = NULL; int error; sc->iot = aa->aa_bst_le; sc->sc_size = aa->aa_size; //sc->sc_bus.ub_hcpriv = sc; sc->sc_bus.ub_dmatag = aa->aa_dmat; sc->sc_bus.ub_revision = USBREV_1_0; sc->sc_flags |= EHCIF_ETTF; sc->sc_vendor_init = ehci_arbus_init; error = bus_space_map(aa->aa_bst, aa->aa_addr, aa->aa_size, 0, &sc->ioh); if (error) { aprint_error(": failed to map registers: %d\n", error); return; } /* The recommended value is 0x20 for both ports and the host */ REGVAL(AR9344_USB_CONFIG_BASE) = 0x20c00; /* magic */ DELAY(1000); /* get offset to operational regs */ uint32_t r = bus_space_read_4(aa->aa_bst, sc->ioh, 0); if (r != 0x40) { aprint_error(": error: CAPLENGTH (%#x) != 0x40\n", sc->sc_offs); return; } sc->sc_offs = EREAD1(sc, EHCI_CAPLENGTH); aprint_normal("\n"); /* Disable EHCI interrupts */ EOWRITE4(sc, EHCI_USBINTR, 0); /* establish interrupt */ ih = arbus_intr_establish(aa->aa_cirq, aa->aa_mirq, ehci_intr, sc); if (ih == NULL) panic("%s: couldn't establish interrupt", device_xname(self)); /* * There are no companion controllers */ sc->sc_ncomp = 0; error = ehci_init(sc); if (error) { aprint_error("%s: init failed, error=%d\n", device_xname(self), error); if (ih != NULL) arbus_intr_disestablish(ih); return; } /* Attach USB device */ sc->sc_child = config_found(self, &sc->sc_bus, usbctlprint); }
static void wdc_isapnp_attach(device_t parent, device_t self, void *aux) { struct wdc_isapnp_softc *sc = device_private(self); struct wdc_regs *wdr; struct isapnp_attach_args *ipa = aux; int i; if (ipa->ipa_nio != 2 || ipa->ipa_nmem != 0 || ipa->ipa_nmem32 != 0 || ipa->ipa_nirq != 1 || ipa->ipa_ndrq > 1) { aprint_error(": unexpected configuration\n"); return; } if (isapnp_config(ipa->ipa_iot, ipa->ipa_memt, ipa)) { aprint_error(": couldn't map registers\n"); return; } aprint_normal(": %s %s\n", ipa->ipa_devident, ipa->ipa_devclass); sc->sc_wdcdev.sc_atac.atac_dev = self; sc->sc_wdcdev.regs = wdr = &sc->wdc_regs; wdr->cmd_iot = ipa->ipa_iot; wdr->ctl_iot = ipa->ipa_iot; /* * An IDE controller can feed us the regions in any order. Pass * them along with the 8-byte region in sc_ad.ioh, and the other * (2 byte) region in auxioh. */ if (ipa->ipa_io[0].length == 8) { wdr->cmd_baseioh = ipa->ipa_io[0].h; wdr->ctl_ioh = ipa->ipa_io[1].h; } else { wdr->cmd_baseioh = ipa->ipa_io[1].h; wdr->ctl_ioh = ipa->ipa_io[0].h; } for (i = 0; i < WDC_NREG; i++) { if (bus_space_subregion(wdr->cmd_iot, wdr->cmd_baseioh, i, i == 0 ? 4 : 1, &wdr->cmd_iohs[i]) != 0) { aprint_error(": couldn't subregion registers\n"); return; } } wdr->data32iot = wdr->cmd_iot; wdr->data32ioh = wdr->cmd_iohs[0]; sc->sc_ic = ipa->ipa_ic; sc->sc_ih = isa_intr_establish(ipa->ipa_ic, ipa->ipa_irq[0].num, ipa->ipa_irq[0].type, IPL_BIO, wdcintr, &sc->ata_channel); #ifdef notyet if (ipa->ipa_ndrq > 0) { sc->sc_drq = ipa->ipa_drq[0].num; sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA; sc->sc_wdcdev.dma_start = &wdc_isapnp_dma_start; sc->sc_wdcdev.dma_finish = &wdc_isapnp_dma_finish; wdc_isapnp_dma_setup(sc); } #endif sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DATA16 | ATAC_CAP_DATA32; sc->sc_wdcdev.sc_atac.atac_pio_cap = 0; sc->wdc_chanlist[0] = &sc->ata_channel; sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanlist; sc->sc_wdcdev.sc_atac.atac_nchannels = 1; sc->sc_wdcdev.wdc_maxdrives = 2; sc->ata_channel.ch_channel = 0; sc->ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac; sc->ata_channel.ch_queue = &sc->wdc_chqueue; wdc_init_shadow_regs(&sc->ata_channel); wdcattach(&sc->ata_channel); }
void pmsattach(device_t parent, device_t self, void *aux) { struct pms_softc *sc = device_private(self); struct pckbport_attach_args *pa = aux; struct wsmousedev_attach_args a; u_char cmd[2], resp[2]; int res; sc->sc_dev = self; sc->sc_kbctag = pa->pa_tag; sc->sc_kbcslot = pa->pa_slot; aprint_naive("\n"); aprint_normal("\n"); /* Flush any garbage. */ pckbport_flush(pa->pa_tag, pa->pa_slot); /* reset the device */ cmd[0] = PMS_RESET; res = pckbport_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 2, resp, 1); if (res || resp[0] != PMS_RSTDONE || resp[1] != 0) { aprint_debug("pmsattach: reset error\n"); return; } sc->inputstate = 0; sc->buttons = 0; sc->protocol = PMS_UNKNOWN; #ifdef PMS_SYNAPTICS_TOUCHPAD /* Probe for synaptics touchpad. */ if (pms_synaptics_probe_init(sc) == 0) { sc->protocol = PMS_SYNAPTICS; } else #endif #ifdef PMS_ELANTECH_TOUCHPAD if (pms_elantech_probe_init(sc) == 0) { sc->protocol = PMS_ELANTECH; } else #endif /* Install generic handler. */ pckbport_set_inputhandler(sc->sc_kbctag, sc->sc_kbcslot, pmsinput, sc, device_xname(sc->sc_dev)); a.accessops = &pms_accessops; a.accesscookie = sc; /* * Attach the wsmouse, saving a handle to it. * Note that we don't need to check this pointer against NULL * here or in pmsintr, because if this fails pms_enable() will * never be called, so pmsinput() will never be called. */ sc->sc_wsmousedev = config_found_ia(self, "wsmousedev", &a, wsmousedevprint); /* no interrupts until enabled */ cmd[0] = PMS_DEV_DISABLE; res = pckbport_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 0, 0, 0); if (res) aprint_error("pmsattach: disable error\n"); pckbport_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 0); kthread_create(PRI_NONE, 0, NULL, pms_reset_thread, sc, &sc->sc_event_thread, device_xname(sc->sc_dev)); #ifndef PMS_DISABLE_POWERHOOK sc->sc_suspended = 0; #endif if (!pmf_device_register(self, pms_suspend, pms_resume)) aprint_error_dev(self, "couldn't establish power handler\n"); }
static void cuda_attach(device_t parent, device_t self, void *aux) { struct confargs *ca = aux; struct cuda_softc *sc = device_private(self); struct i2cbus_attach_args iba; static struct cuda_attach_args caa; int irq = ca->ca_intr[0]; int node, i, child; char name[32]; sc->sc_dev = self; node = of_getnode_byname(OF_parent(ca->ca_node), "extint-gpio1"); if (node) OF_getprop(node, "interrupts", &irq, 4); aprint_normal(" irq %d", irq); sc->sc_node = ca->ca_node; sc->sc_memt = ca->ca_tag; sc->sc_sent = 0; sc->sc_received = 0; sc->sc_waiting = 0; sc->sc_polling = 0; sc->sc_state = CUDA_NOTREADY; sc->sc_error = 0; sc->sc_i2c_read_len = 0; if (bus_space_map(sc->sc_memt, ca->ca_reg[0] + ca->ca_baseaddr, ca->ca_reg[1], 0, &sc->sc_memh) != 0) { aprint_normal(": unable to map registers\n"); return; } sc->sc_ih = intr_establish(irq, IST_EDGE, IPL_TTY, cuda_intr, sc); printf("\n"); for (i = 0; i < 16; i++) { sc->sc_handlers[i].handler = NULL; sc->sc_handlers[i].cookie = NULL; } cuda_init(sc); /* now attach children */ config_interrupts(self, cuda_final); cuda_set_handler(sc, CUDA_ERROR, cuda_error_handler, sc); cuda_set_handler(sc, CUDA_PSEUDO, cuda_todr_handler, sc); child = OF_child(ca->ca_node); while (child != 0) { if (OF_getprop(child, "name", name, 32) == 0) continue; if (strncmp(name, "adb", 4) == 0) { cuda_set_handler(sc, CUDA_ADB, cuda_adb_handler, sc); sc->sc_adbops.cookie = sc; sc->sc_adbops.send = cuda_adb_send; sc->sc_adbops.poll = cuda_adb_poll; sc->sc_adbops.autopoll = cuda_autopoll; sc->sc_adbops.set_handler = cuda_adb_set_handler; config_found_ia(self, "adb_bus", &sc->sc_adbops, nadb_print); } else if (strncmp(name, "rtc", 4) == 0) { sc->sc_todr.todr_gettime = cuda_todr_get; sc->sc_todr.todr_settime = cuda_todr_set; sc->sc_todr.cookie = sc; todr_attach(&sc->sc_todr); } child = OF_peer(child); } caa.cookie = sc; caa.set_handler = cuda_set_handler; caa.send = cuda_send; caa.poll = cuda_poll; #if notyet config_found(self, &caa, cuda_print); #endif mutex_init(&sc->sc_buslock, MUTEX_DEFAULT, IPL_NONE); memset(&iba, 0, sizeof(iba)); iba.iba_tag = &sc->sc_i2c; sc->sc_i2c.ic_cookie = sc; sc->sc_i2c.ic_acquire_bus = cuda_i2c_acquire_bus; sc->sc_i2c.ic_release_bus = cuda_i2c_release_bus; sc->sc_i2c.ic_send_start = NULL; sc->sc_i2c.ic_send_stop = NULL; sc->sc_i2c.ic_initiate_xfer = NULL; sc->sc_i2c.ic_read_byte = NULL; sc->sc_i2c.ic_write_byte = NULL; sc->sc_i2c.ic_exec = cuda_i2c_exec; config_found_ia(self, "i2cbus", &iba, iicbus_print); if (cuda0 == NULL) cuda0 = &caa; }
static void pq3ehci_attach(device_t parent, device_t self, void *aux) { struct cpunode_softc * const psc = device_private(parent); struct pq3ehci_softc * const sc = device_private(self); struct cpunode_attach_args * const cna = aux; struct cpunode_locators * const cnl = &cna->cna_locs; int error; psc->sc_children |= cna->cna_childmask; sc->sc.iot = cna->cna_le_memt; /* EHCI registers are little endian */ sc->sc.sc_dev = self; sc->sc.sc_bus.ub_dmatag = cna->cna_dmat; sc->sc.sc_bus.ub_hcpriv = sc; sc->sc.sc_bus.ub_revision = USBREV_2_0; sc->sc.sc_ncomp = 0; sc->sc.sc_flags |= EHCIF_ETTF; sc->sc.sc_vendor_init = pq3ehci_init; aprint_naive(": USB controller\n"); aprint_normal(": USB controller\n"); error = bus_space_map(sc->sc.iot, cnl->cnl_addr, cnl->cnl_size, 0, &sc->sc.ioh); if (error) { aprint_error_dev(self, "can't map registers for %s#%u: %d\n", cnl->cnl_name, cnl->cnl_instance, error); return; } sc->sc.sc_size = cnl->cnl_size; /* * We need to tell the USB interface to snoop all off RAM starting * at 0. Since it can do it by powers of 2, get the highest RAM * address and roughly round it to the next power of 2 and find * the number of leading zero bits. */ cpu_write_4(cnl->cnl_addr + USB_SNOOP1, SNOOP_2GB - __builtin_clz(curcpu()->ci_softc->cpu_highmem * 2 - 1)); cpu_write_4(cnl->cnl_addr + USB_CONTROL, USB_EN); sc->sc_ih = intr_establish(cnl->cnl_intrs[0], IPL_USB, IST_ONCHIP, ehci_intr, sc); if (sc->sc_ih == NULL) { aprint_error_dev(self, "failed to establish interrupt %d\n", cnl->cnl_intrs[0]); goto fail; } aprint_normal_dev(self, "interrupting on irq %d\n", cnl->cnl_intrs[0]); /* offs is needed for EOWRITEx */ sc->sc.sc_offs = EREAD1(&sc->sc, EHCI_CAPLENGTH); /* Disable interrupts, so we don't get any spurious ones. */ DPRINTF(("%s: offs=%d\n", device_xname(self), sc->sc.sc_offs)); EOWRITE4(&sc->sc, EHCI_USBINTR, 0); error = ehci_init(&sc->sc); if (error) { aprint_error_dev(self, "init failed, error=%d\n", error); goto fail; } /* Attach usb device. */ sc->sc.sc_child = config_found(self, &sc->sc.sc_bus, usbctlprint); return; fail: if (sc->sc_ih) { intr_disestablish(sc->sc_ih); sc->sc_ih = NULL; } if (sc->sc.sc_size) { bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size); sc->sc.sc_size = 0; } return; }
static void tlp_smc9332dst_tmsw_init(struct tulip_softc *sc) { struct tulip_21x4x_media *tm; const char *sep = ""; uint32_t reg; int i, cnt; sc->sc_gp_dir = GPP_SMC9332DST_PINS; sc->sc_opmode = OPMODE_MBO | OPMODE_PS; TULIP_WRITE(sc, CSR_OPMODE, sc->sc_opmode); ifmedia_init(&sc->sc_mii.mii_media, 0, tlp_mediachange, tlp_mediastatus); aprint_normal_dev(sc->sc_dev, ""); #define ADD(m, c) \ tm = malloc(sizeof(*tm), M_DEVBUF, M_WAITOK|M_ZERO); \ tm->tm_opmode = (c); \ tm->tm_gpdata = GPP_SMC9332DST_INIT; \ ifmedia_add(&sc->sc_mii.mii_media, (m), 0, tm) #define PRINT(str) aprint_normal("%s%s", sep, str); sep = ", " ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, 0), OPMODE_TTM); PRINT("10baseT"); ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, 0), OPMODE_TTM | OPMODE_FD); PRINT("10baseT-FDX"); ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, 0), OPMODE_PS | OPMODE_PCS | OPMODE_SCR); PRINT("100baseTX"); ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, 0), OPMODE_PS | OPMODE_PCS | OPMODE_SCR | OPMODE_FD); PRINT("100baseTX-FDX"); #undef ADD #undef PRINT aprint_normal("\n"); tlp_reset(sc); TULIP_WRITE(sc, CSR_OPMODE, sc->sc_opmode | OPMODE_PCS | OPMODE_SCR); TULIP_WRITE(sc, CSR_GPP, GPP_GPC | sc->sc_gp_dir); delay(10); TULIP_WRITE(sc, CSR_GPP, GPP_SMC9332DST_INIT); delay(200000); cnt = 0; for (i = 1000; i > 0; i--) { reg = TULIP_READ(sc, CSR_GPP); if ((~reg & (GPP_SMC9332DST_OK10 | GPP_SMC9332DST_OK100)) == 0) { if (cnt++ > 100) { break; } } else if ((reg & GPP_SMC9332DST_OK10) == 0) { break; } else { cnt = 0; } delay(1000); } if (cnt > 100) { ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_100_TX); } else { ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_10_T); } }
/* * Attach all the sub-devices we can find */ static void bha_pci_attach(device_t parent, device_t self, void *aux) { struct pci_attach_args *pa = aux; struct bha_softc *sc = device_private(self); bus_space_tag_t iot; bus_space_handle_t ioh; pci_chipset_tag_t pc = pa->pa_pc; pci_intr_handle_t ih; pcireg_t csr; const char *model, *intrstr; sc->sc_dev = self; aprint_naive(": SCSI controller\n"); if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BUSLOGIC_MULTIMASTER_NC) model = "BusLogic 9xxC SCSI"; else if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BUSLOGIC_MULTIMASTER) model = "BusLogic 9xxC SCSI"; else model = "unknown model!"; aprint_normal(": %s\n", model); if (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0, &iot, &ioh, NULL, NULL)) { aprint_error_dev(sc->sc_dev, "unable to map device registers\n"); return; } sc->sc_iot = iot; sc->sc_ioh = ioh; sc->sc_dmat = pa->pa_dmat; if (!bha_find(iot, ioh)) panic("bha_pci_attach: bha_find failed"); sc->sc_dmaflags = 0; csr = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, csr | PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_IO_ENABLE); if (pci_intr_map(pa, &ih)) { aprint_error_dev(sc->sc_dev, "couldn't map interrupt\n"); return; } intrstr = pci_intr_string(pc, ih); sc->sc_ih = pci_intr_establish(pc, ih, IPL_BIO, bha_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"); return; } aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr); bha_attach(sc); bha_disable_isacompat(sc); }
static void tlp_pci_attach(device_t parent, device_t self, void *aux) { struct tulip_pci_softc *psc = device_private(self); struct tulip_softc *sc = &psc->sc_tulip; struct pci_attach_args *pa = aux; pci_chipset_tag_t pc = pa->pa_pc; pci_intr_handle_t ih; const char *intrstr = NULL; bus_space_tag_t iot, memt; bus_space_handle_t ioh, memh; int ioh_valid, memh_valid, i, j; const struct tulip_pci_product *tpp; prop_data_t ea; uint8_t enaddr[ETHER_ADDR_LEN]; uint32_t val = 0; pcireg_t reg; int error; bus_size_t iosize = 0, memsize = 0; sc->sc_dev = self; sc->sc_devno = pa->pa_device; psc->sc_pc = pa->pa_pc; psc->sc_pcitag = pa->pa_tag; LIST_INIT(&psc->sc_intrslaves); tpp = tlp_pci_lookup(pa); if (tpp == NULL) { printf("\n"); panic("tlp_pci_attach: impossible"); } sc->sc_chip = tpp->tpp_chip; /* * By default, Tulip registers are 8 bytes long (4 bytes * followed by a 4 byte pad). */ sc->sc_regshift = 3; /* * No power management hooks. * XXX Maybe we should add some! */ sc->sc_flags |= TULIPF_ENABLED; /* * Get revision info, and set some chip-specific variables. */ sc->sc_rev = PCI_REVISION(pa->pa_class); switch (sc->sc_chip) { case TULIP_CHIP_21140: if (sc->sc_rev >= 0x20) sc->sc_chip = TULIP_CHIP_21140A; break; case TULIP_CHIP_21142: if (sc->sc_rev >= 0x20) sc->sc_chip = TULIP_CHIP_21143; break; case TULIP_CHIP_82C168: if (sc->sc_rev >= 0x20) sc->sc_chip = TULIP_CHIP_82C169; break; case TULIP_CHIP_MX98713: if (sc->sc_rev >= 0x10) sc->sc_chip = TULIP_CHIP_MX98713A; break; case TULIP_CHIP_MX98715: if (sc->sc_rev >= 0x20) sc->sc_chip = TULIP_CHIP_MX98715A; if (sc->sc_rev >= 0x25) sc->sc_chip = TULIP_CHIP_MX98715AEC_X; if (sc->sc_rev >= 0x30) sc->sc_chip = TULIP_CHIP_MX98725; break; case TULIP_CHIP_WB89C840F: sc->sc_regshift = 2; break; case TULIP_CHIP_AN985: /* * The AN983 and AN985 are very similar, and are * differentiated by a "signature" register that * is like, but not identical, to a PCI ID register. */ reg = pci_conf_read(pc, pa->pa_tag, 0x80); switch (reg) { case 0x09811317: sc->sc_chip = TULIP_CHIP_AN985; break; case 0x09851317: sc->sc_chip = TULIP_CHIP_AN983; break; default: /* Unknown -- use default. */ break; } break; case TULIP_CHIP_AX88140: if (sc->sc_rev >= 0x10) sc->sc_chip = TULIP_CHIP_AX88141; break; case TULIP_CHIP_DM9102: if (sc->sc_rev >= 0x30) sc->sc_chip = TULIP_CHIP_DM9102A; break; default: /* Nothing. */ break; } aprint_normal(": %s Ethernet, pass %d.%d\n", tlp_chip_name(sc->sc_chip), (sc->sc_rev >> 4) & 0xf, sc->sc_rev & 0xf); switch (sc->sc_chip) { case TULIP_CHIP_21040: if (sc->sc_rev < 0x20) { aprint_normal_dev(self, "21040 must be at least pass 2.0\n"); return; } break; case TULIP_CHIP_21140: if (sc->sc_rev < 0x11) { aprint_normal_dev(self, "21140 must be at least pass 1.1\n"); return; } break; default: /* Nothing. */ break; } /* * Check to see if the device is in power-save mode, and * being it out if necessary. */ switch (sc->sc_chip) { case TULIP_CHIP_21140: case TULIP_CHIP_21140A: case TULIP_CHIP_21142: case TULIP_CHIP_21143: case TULIP_CHIP_MX98713A: case TULIP_CHIP_MX98715: case TULIP_CHIP_MX98715A: case TULIP_CHIP_MX98715AEC_X: case TULIP_CHIP_MX98725: case TULIP_CHIP_DM9102: case TULIP_CHIP_DM9102A: case TULIP_CHIP_AX88140: case TULIP_CHIP_AX88141: case TULIP_CHIP_RS7112: /* * Clear the "sleep mode" bit in the CFDA register. */ reg = pci_conf_read(pc, pa->pa_tag, TULIP_PCI_CFDA); if (reg & (CFDA_SLEEP|CFDA_SNOOZE)) pci_conf_write(pc, pa->pa_tag, TULIP_PCI_CFDA, reg & ~(CFDA_SLEEP|CFDA_SNOOZE)); break; default: /* Nothing. */ break; } /* power up chip */ if ((error = pci_activate(pa->pa_pc, pa->pa_tag, self, NULL)) && error != EOPNOTSUPP) { aprint_error_dev(self, "cannot activate %d\n", error); return; } /* * Map the device. */ ioh_valid = (pci_mapreg_map(pa, TULIP_PCI_IOBA, PCI_MAPREG_TYPE_IO, 0, &iot, &ioh, NULL, &iosize) == 0); memh_valid = (pci_mapreg_map(pa, TULIP_PCI_MMBA, PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, &memt, &memh, NULL, &memsize) == 0); if (memh_valid) { sc->sc_st = memt; sc->sc_sh = memh; psc->sc_mapsize = memsize; if (ioh_valid) { bus_space_unmap(iot, ioh, iosize); ioh_valid = 0; } } else if (ioh_valid) { sc->sc_st = iot; sc->sc_sh = ioh; psc->sc_mapsize = iosize; if (memh_valid) { bus_space_unmap(memt, memh, memsize); memh_valid = 0; } } else { aprint_error_dev(self, "unable to map device registers\n"); goto fail; } sc->sc_dmat = pa->pa_dmat; /* * Make sure bus mastering is enabled. */ pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) | PCI_COMMAND_MASTER_ENABLE); /* * Get the cacheline size. */ sc->sc_cacheline = PCI_CACHELINE(pci_conf_read(pc, pa->pa_tag, PCI_BHLC_REG)); /* * Get PCI data moving command info. */ if (pa->pa_flags & PCI_FLAGS_MRL_OKAY) sc->sc_flags |= TULIPF_MRL; if (pa->pa_flags & PCI_FLAGS_MRM_OKAY) sc->sc_flags |= TULIPF_MRM; if (pa->pa_flags & PCI_FLAGS_MWI_OKAY) sc->sc_flags |= TULIPF_MWI; /* * Read the contents of the Ethernet Address ROM/SROM. */ switch (sc->sc_chip) { case TULIP_CHIP_21040: sc->sc_srom_addrbits = 6; sc->sc_srom = malloc(TULIP_ROM_SIZE(6), M_DEVBUF, M_NOWAIT); TULIP_WRITE(sc, CSR_MIIROM, MIIROM_SROMCS); for (i = 0; i < TULIP_ROM_SIZE(6); i++) { for (j = 0; j < 10000; j++) { val = TULIP_READ(sc, CSR_MIIROM); if ((val & MIIROM_DN) == 0) break; } sc->sc_srom[i] = val & MIIROM_DATA; } break; case TULIP_CHIP_82C168: case TULIP_CHIP_82C169: { sc->sc_srom_addrbits = 2; sc->sc_srom = malloc(TULIP_ROM_SIZE(2), M_DEVBUF, M_NOWAIT); /* * The Lite-On PNIC stores the Ethernet address in * the first 3 words of the EEPROM. EEPROM access * is not like the other Tulip chips. */ for (i = 0; i < 6; i += 2) { TULIP_WRITE(sc, CSR_PNIC_SROMCTL, PNIC_SROMCTL_READ | (i >> 1)); for (j = 0; j < 500; j++) { delay(2); val = TULIP_READ(sc, CSR_MIIROM); if ((val & PNIC_MIIROM_BUSY) == 0) break; } if (val & PNIC_MIIROM_BUSY) { aprint_error_dev(self, "EEPROM timed out\n"); goto fail; } val &= PNIC_MIIROM_DATA; sc->sc_srom[i] = val >> 8; sc->sc_srom[i + 1] = val & 0xff; } break; } default: /* * XXX This isn't quite the right way to do this; we should * XXX be attempting to fetch the mac-addr property in the * XXX bus-agnostic part of the driver independently. But * XXX that requires a larger change in the SROM handling * XXX logic, and for now we can at least remove a machine- * XXX dependent wart from the PCI front-end. */ ea = prop_dictionary_get(device_properties(self), "mac-address"); if (ea != NULL) { extern int tlp_srom_debug; KASSERT(prop_object_type(ea) == PROP_TYPE_DATA); KASSERT(prop_data_size(ea) == ETHER_ADDR_LEN); memcpy(enaddr, prop_data_data_nocopy(ea), ETHER_ADDR_LEN); sc->sc_srom_addrbits = 6; sc->sc_srom = malloc(TULIP_ROM_SIZE(6), M_DEVBUF, M_NOWAIT|M_ZERO); memcpy(sc->sc_srom, enaddr, sizeof(enaddr)); if (tlp_srom_debug) { aprint_normal("SROM CONTENTS:"); for (i = 0; i < TULIP_ROM_SIZE(6); i++) { if ((i % 8) == 0) aprint_normal("\n\t"); aprint_normal("0x%02x ", sc->sc_srom[i]); } aprint_normal("\n"); } break; } /* Check for a slaved ROM on a multi-port board. */ tlp_pci_check_slaved(psc, TULIP_PCI_SHAREDROM, TULIP_PCI_SLAVEROM); if (psc->sc_flags & TULIP_PCI_SLAVEROM) { sc->sc_srom_addrbits = psc->sc_master->sc_tulip.sc_srom_addrbits; sc->sc_srom = psc->sc_master->sc_tulip.sc_srom; enaddr[5] += sc->sc_devno - psc->sc_master->sc_tulip.sc_devno; } else if (tlp_read_srom(sc) == 0) goto cant_cope; break; } /* * Deal with chip/board quirks. This includes setting up * the mediasw, and extracting the Ethernet address from * the rombuf. */ switch (sc->sc_chip) { case TULIP_CHIP_21040: /* * Parse the Ethernet Address ROM. */ if (tlp_parse_old_srom(sc, enaddr) == 0) goto cant_cope; /* * All 21040 boards start out with the same * media switch. */ sc->sc_mediasw = &tlp_21040_mediasw; /* * Deal with any quirks this board might have. */ tlp_pci_get_quirks(psc, enaddr, tlp_pci_21040_quirks); break; case TULIP_CHIP_21041: /* Check for new format SROM. */ if (tlp_isv_srom_enaddr(sc, enaddr) == 0) { /* * Not an ISV SROM; try the old DEC Ethernet Address * ROM format. */ if (tlp_parse_old_srom(sc, enaddr) == 0) goto cant_cope; } /* * All 21041 boards use the same media switch; they all * work basically the same! Yippee! */ sc->sc_mediasw = &tlp_21041_mediasw; /* * Deal with any quirks this board might have. */ tlp_pci_get_quirks(psc, enaddr, tlp_pci_21041_quirks); break; case TULIP_CHIP_21140: case TULIP_CHIP_21140A: /* Check for new format SROM. */ if (tlp_isv_srom_enaddr(sc, enaddr) == 0) { /* * Not an ISV SROM; try the old DEC Ethernet Address * ROM format. */ if (tlp_parse_old_srom(sc, enaddr) == 0) goto cant_cope; } else { /* * We start out with the 2114x ISV media switch. * When we search for quirks, we may change to * a different switch. */ sc->sc_mediasw = &tlp_2114x_isv_mediasw; } /* * Deal with any quirks this board might have. */ tlp_pci_get_quirks(psc, enaddr, tlp_pci_21140_quirks); /* * Bail out now if we can't deal with this board. */ if (sc->sc_mediasw == NULL) goto cant_cope; break; case TULIP_CHIP_21142: case TULIP_CHIP_21143: /* Check for new format SROM. */ if (tlp_isv_srom_enaddr(sc, enaddr) == 0) { /* * Not an ISV SROM; try the old DEC Ethernet Address * ROM format. */ if (tlp_parse_old_srom(sc, enaddr) == 0) { /* * One last try: just copy the address * from offset 20 and try to look * up quirks. */ memcpy(enaddr, &sc->sc_srom[20], ETHER_ADDR_LEN); } } else { /* * We start out with the 2114x ISV media switch. * When we search for quirks, we may change to * a different switch. */ sc->sc_mediasw = &tlp_2114x_isv_mediasw; } /* * Deal with any quirks this board might have. */ tlp_pci_get_quirks(psc, enaddr, tlp_pci_21142_quirks); /* * Bail out now if we can't deal with this board. */ if (sc->sc_mediasw == NULL) goto cant_cope; break; case TULIP_CHIP_82C168: case TULIP_CHIP_82C169: /* * Lite-On PNIC's Ethernet address is the first 6 * bytes of its EEPROM. */ memcpy(enaddr, sc->sc_srom, ETHER_ADDR_LEN); /* * Lite-On PNICs always use the same mediasw; we * select MII vs. internal NWAY automatically. */ sc->sc_mediasw = &tlp_pnic_mediasw; break; case TULIP_CHIP_MX98713: /* * The Macronix MX98713 has an MII and GPIO, but no * internal Nway block. This chip is basically a * perfect 21140A clone, with the exception of the * a magic register frobbing in order to make the * interface function. */ if (tlp_isv_srom_enaddr(sc, enaddr)) { sc->sc_mediasw = &tlp_2114x_isv_mediasw; break; } /* FALLTHROUGH */ case TULIP_CHIP_82C115: /* * Yippee! The Lite-On 82C115 is a clone of * the MX98725 (the data sheet even says `MXIC' * on it)! Imagine that, a clone of a clone. * * The differences are really minimal: * * - Wake-On-LAN support * - 128-bit multicast hash table, rather than * the standard 512-bit hash table */ /* FALLTHROUGH */ case TULIP_CHIP_MX98713A: case TULIP_CHIP_MX98715A: case TULIP_CHIP_MX98715AEC_X: case TULIP_CHIP_MX98725: /* * The MX98713A has an MII as well as an internal Nway block, * but no GPIO. The MX98715 and MX98725 have an internal * Nway block only. * * The internal Nway block, unlike the Lite-On PNIC's, does * just that - performs Nway. Once autonegotiation completes, * we must program the GPR media information into the chip. * * The byte offset of the Ethernet address is stored at * offset 0x70. */ memcpy(enaddr, &sc->sc_srom[sc->sc_srom[0x70]], ETHER_ADDR_LEN); sc->sc_mediasw = &tlp_pmac_mediasw; break; case TULIP_CHIP_WB89C840F: /* * Winbond 89C840F's Ethernet address is the first * 6 bytes of its EEPROM. */ memcpy(enaddr, sc->sc_srom, ETHER_ADDR_LEN); /* * Winbond 89C840F has an MII attached to the SIO. */ sc->sc_mediasw = &tlp_sio_mii_mediasw; break; case TULIP_CHIP_AL981: /* * The ADMtek AL981's Ethernet address is located * at offset 8 of its EEPROM. */ memcpy(enaddr, &sc->sc_srom[8], ETHER_ADDR_LEN); /* * ADMtek AL981 has a built-in PHY accessed through * special registers. */ sc->sc_mediasw = &tlp_al981_mediasw; break; case TULIP_CHIP_AN983: case TULIP_CHIP_AN985: /* * The ADMtek AN985's Ethernet address is located * at offset 8 of its EEPROM. */ memcpy(enaddr, &sc->sc_srom[8], ETHER_ADDR_LEN); /* * The ADMtek AN985 can be configured in Single-Chip * mode or MAC-only mode. Single-Chip uses the built-in * PHY, MAC-only has an external PHY (usually HomePNA). * The selection is based on an EEPROM setting, and both * PHYs are accessed via MII attached to SIO. * * The AN985 "ghosts" the internal PHY onto all * MII addresses, so we have to use a media init * routine that limits the search. * XXX How does this work with MAC-only mode? */ sc->sc_mediasw = &tlp_an985_mediasw; break; case TULIP_CHIP_DM9102: case TULIP_CHIP_DM9102A: /* * Some boards with the Davicom chip have an ISV * SROM (mostly DM9102A boards -- trying to describe * the HomePNA PHY, probably) although the data in * them is generally wrong. Check for ISV format * and grab the Ethernet address that way, and if * that fails, fall back on grabbing it from an * observed offset of 20 (which is where it would * be in an ISV SROM anyhow, tho ISV can cope with * multi-port boards). */ if (!tlp_isv_srom_enaddr(sc, enaddr)) { prop_data_t eaddrprop; eaddrprop = prop_dictionary_get( device_properties(self), "mac-address"); if (eaddrprop != NULL && prop_data_size(eaddrprop) == ETHER_ADDR_LEN) memcpy(enaddr, prop_data_data_nocopy(eaddrprop), ETHER_ADDR_LEN); else memcpy(enaddr, &sc->sc_srom[20], ETHER_ADDR_LEN); } /* * Davicom chips all have an internal MII interface * and a built-in PHY. DM9102A also has a an external * MII interface, usually with a HomePNA PHY attached * to it. */ sc->sc_mediasw = &tlp_dm9102_mediasw; break; case TULIP_CHIP_AX88140: case TULIP_CHIP_AX88141: /* * ASIX AX88140/AX88141 Ethernet Address is located at offset * 20 of the SROM. */ memcpy(enaddr, &sc->sc_srom[20], ETHER_ADDR_LEN); /* * ASIX AX88140A/AX88141 chip can have a built-in PHY or * an external MII interface. */ sc->sc_mediasw = &tlp_asix_mediasw; break; case TULIP_CHIP_RS7112: /* * RS7112 Ethernet Address is located of offset 0x19a * of the SROM */ memcpy(enaddr, &sc->sc_srom[0x19a], ETHER_ADDR_LEN); /* RS7112 chip has a PHY at MII address 1 */ sc->sc_mediasw = &tlp_rs7112_mediasw; break; default: cant_cope: aprint_error_dev(self, "sorry, unable to handle your board\n"); goto fail; } /* * Handle shared interrupts. */ if (psc->sc_flags & TULIP_PCI_SHAREDINTR) { if (psc->sc_master) psc->sc_flags |= TULIP_PCI_SLAVEINTR; else { tlp_pci_check_slaved(psc, TULIP_PCI_SHAREDINTR, TULIP_PCI_SLAVEINTR); if (psc->sc_master == NULL) psc->sc_master = psc; } LIST_INSERT_HEAD(&psc->sc_master->sc_intrslaves, psc, sc_intrq); } if (psc->sc_flags & TULIP_PCI_SLAVEINTR) { aprint_normal_dev(self, "sharing interrupt with %s\n", device_xname(psc->sc_master->sc_tulip.sc_dev)); } else { /* * Map and establish our interrupt. */ if (pci_intr_map(pa, &ih)) { aprint_error_dev(self, "unable to map interrupt\n"); goto fail; } intrstr = pci_intr_string(pc, ih); psc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, (psc->sc_flags & TULIP_PCI_SHAREDINTR) ? tlp_pci_shared_intr : tlp_intr, sc); if (psc->sc_ih == NULL) { aprint_error_dev(self, "unable to establish interrupt"); if (intrstr != NULL) aprint_error(" at %s", intrstr); aprint_error("\n"); goto fail; } aprint_normal_dev(self, "interrupting at %s\n", intrstr); } /* * Finish off the attach. */ error = tlp_attach(sc, enaddr); if (error) goto fail; return; fail: if (psc->sc_ih != NULL) { pci_intr_disestablish(psc->sc_pc, psc->sc_ih); psc->sc_ih = NULL; } if (ioh_valid) bus_space_unmap(iot, ioh, iosize); if (memh_valid) bus_space_unmap(memt, memh, memsize); psc->sc_mapsize = 0; return; }
/* ARGSUSED */ static void bcmemmc_attach(device_t parent, device_t self, void *aux) { struct bcmemmc_softc *sc = device_private(self); prop_dictionary_t dict = device_properties(self); struct amba_attach_args *aaa = aux; prop_number_t frequency; int error; sc->sc.sc_dev = self; sc->sc.sc_dmat = aaa->aaa_dmat; sc->sc.sc_flags = 0; sc->sc.sc_flags |= SDHC_FLAG_32BIT_ACCESS; sc->sc.sc_flags |= SDHC_FLAG_HOSTCAPS; sc->sc.sc_flags |= SDHC_FLAG_NO_HS_BIT; sc->sc.sc_caps = SDHC_VOLTAGE_SUPP_3_3V | SDHC_HIGH_SPEED_SUPP | (SDHC_MAX_BLK_LEN_1024 << SDHC_MAX_BLK_LEN_SHIFT); sc->sc.sc_caps2 = SDHC_SDR50_SUPP; sc->sc.sc_host = sc->sc_hosts; sc->sc.sc_clkbase = 50000; /* Default to 50MHz */ sc->sc_iot = aaa->aaa_iot; /* Fetch the EMMC clock frequency from property if set. */ frequency = prop_dictionary_get(dict, "frequency"); if (frequency != NULL) { sc->sc.sc_clkbase = prop_number_integer_value(frequency) / 1000; } error = bus_space_map(sc->sc_iot, aaa->aaa_addr, aaa->aaa_size, 0, &sc->sc_ioh); if (error) { aprint_error_dev(self, "can't map registers for %s: %d\n", aaa->aaa_name, error); return; } sc->sc_ios = aaa->aaa_size; sc->sc_physaddr = aaa->aaa_addr; aprint_naive(": SDHC controller\n"); aprint_normal(": SDHC controller\n"); sc->sc_ih = intr_establish(aaa->aaa_intr, IPL_SDMMC, IST_LEVEL, sdhc_intr, &sc->sc); if (sc->sc_ih == NULL) { aprint_error_dev(self, "failed to establish interrupt %d\n", aaa->aaa_intr); goto fail; } aprint_normal_dev(self, "interrupting on intr %d\n", aaa->aaa_intr); #if NBCMDMAC > 0 sc->sc_dmac = bcm_dmac_alloc(BCM_DMAC_TYPE_NORMAL, IPL_SDMMC, bcmemmc_dma_done, sc); if (sc->sc_dmac == NULL) goto done; sc->sc.sc_flags |= SDHC_FLAG_USE_DMA; sc->sc.sc_flags |= SDHC_FLAG_EXTERNAL_DMA; sc->sc.sc_caps |= SDHC_DMA_SUPPORT; sc->sc.sc_vendor_transfer_data_dma = bcmemmc_xfer_data_dma; sc->sc_state = EMMC_DMA_STATE_IDLE; cv_init(&sc->sc_cv, "bcmemmcdma"); int rseg; error = bus_dmamem_alloc(sc->sc.sc_dmat, PAGE_SIZE, PAGE_SIZE, PAGE_SIZE, sc->sc_segs, 1, &rseg, BUS_DMA_WAITOK); if (error) { aprint_error_dev(self, "dmamem_alloc failed (%d)\n", error); goto fail; } error = bus_dmamem_map(sc->sc.sc_dmat, sc->sc_segs, rseg, PAGE_SIZE, (void **)&sc->sc_cblk, BUS_DMA_WAITOK); if (error) { aprint_error_dev(self, "dmamem_map failed (%d)\n", error); goto fail; } KASSERT(sc->sc_cblk != NULL); memset(sc->sc_cblk, 0, PAGE_SIZE); error = bus_dmamap_create(sc->sc.sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, 0, BUS_DMA_WAITOK, &sc->sc_dmamap); if (error) { aprint_error_dev(self, "dmamap_create failed (%d)\n", error); goto fail; } error = bus_dmamap_load(sc->sc.sc_dmat, sc->sc_dmamap, sc->sc_cblk, PAGE_SIZE, NULL, BUS_DMA_WAITOK|BUS_DMA_WRITE); if (error) { aprint_error_dev(self, "dmamap_load failed (%d)\n", error); goto fail; } done: #endif config_interrupts(self, bcmemmc_attach_i); return; fail: /* XXX add bus_dma failure cleanup */ if (sc->sc_ih) { intr_disestablish(sc->sc_ih); sc->sc_ih = NULL; } bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios); }
static void p5bus_attach(device_t parent, device_t self, void *aux) { struct p5bus_softc *sc; struct zbus_args *zap; struct p5bus_attach_args p5baa; char *sn; zap = aux; sc = device_private(self); sc->sc_dev = self; sn = p5bus_cardsn(); aprint_normal(": Phase5 PowerUP on-board bus\n"); /* "Detect" what devices are present and attach the right drivers. */ if (zap->prodid == ZORRO_PRODID_CSPPC) { if (sn[0] == 'F') { aprint_normal_dev(sc->sc_dev, "CyberStorm Mk-III (sn %s)\n", sn); sc->sc_has_ppc = P5BUS_PPC_NONE; } else { aprint_normal_dev(sc->sc_dev, "CyberStorm PPC 604e (sn %s)\n", sn); sc->sc_has_ppc = P5BUS_PPC_OK; } sc->sc_cardtype = P5_CARDTYPE_CS; sc->sc_has_scsi = P5BUS_SCSI_770; } else if (zap->prodid == ZORRO_PRODID_BPPC) { if (sn[0] != 'I') { /* only "+" model has SCSI */ aprint_normal_dev(sc->sc_dev, "BlizzardPPC 603e (sn %s)\n", sn); sc->sc_has_scsi = P5BUS_SCSI_NONE; } else { aprint_normal_dev(sc->sc_dev, "BlizzardPPC 603e+ (sn %s)\n", sn); sc->sc_has_scsi = P5BUS_SCSI_710; } sc->sc_cardtype = P5_CARDTYPE_BPPC; sc->sc_has_ppc = P5BUS_PPC_OK; } p5baa.p5baa_cardtype = sc->sc_cardtype; /* Attach the SCSI host adapters. */ switch (sc->sc_has_scsi) { case P5BUS_SCSI_710: strcpy(p5baa.p5baa_name, "bppcsc"); config_found_ia(sc->sc_dev, "p5bus", &p5baa, p5bus_print); break; case P5BUS_SCSI_770: strcpy(p5baa.p5baa_name, "cbiiisc"); config_found_ia(sc->sc_dev, "p5bus", &p5baa, p5bus_print); break; default: break; } /* * We need to wait for possible p5membar attachments. Defer the rest * until parent (zbus) is completely configured. */ config_defer(self, p5bus_callback); }
static void ld_virtio_attach(device_t parent, device_t self, void *aux) { struct ld_virtio_softc *sc = device_private(self); struct ld_softc *ld = &sc->sc_ld; struct virtio_softc *vsc = device_private(parent); uint32_t features; int qsize, maxxfersize; if (vsc->sc_child != NULL) { aprint_normal(": child already attached for %s; " "something wrong...\n", device_xname(parent)); return; } aprint_normal("\n"); aprint_naive("\n"); sc->sc_dev = self; sc->sc_virtio = vsc; vsc->sc_child = self; vsc->sc_ipl = IPL_BIO; vsc->sc_vqs = &sc->sc_vq[0]; vsc->sc_nvqs = 1; vsc->sc_config_change = 0; vsc->sc_intrhand = virtio_vq_intr; features = virtio_negotiate_features(vsc, (VIRTIO_BLK_F_SIZE_MAX | VIRTIO_BLK_F_SEG_MAX | VIRTIO_BLK_F_GEOMETRY | VIRTIO_BLK_F_RO | VIRTIO_BLK_F_BLK_SIZE | VIRTIO_BLK_F_SECTOR_MAX)); if (features & VIRTIO_BLK_F_RO) sc->sc_readonly = 1; else sc->sc_readonly = 0; maxxfersize = MAXPHYS; if (features & VIRTIO_BLK_F_SECTOR_MAX) { maxxfersize = virtio_read_device_config_4(vsc, VIRTIO_BLK_CONFIG_SECTORS_MAX) * ld->sc_secsize; if (maxxfersize > MAXPHYS) maxxfersize = MAXPHYS; } if (virtio_alloc_vq(vsc, &sc->sc_vq[0], 0, maxxfersize, maxxfersize / NBPG + 2, "I/O request") != 0) { goto err; } qsize = sc->sc_vq[0].vq_num; sc->sc_vq[0].vq_done = ld_virtio_vq_done; ld->sc_dv = self; ld->sc_secperunit = virtio_read_device_config_8(vsc, VIRTIO_BLK_CONFIG_CAPACITY); ld->sc_secsize = 512; if (features & VIRTIO_BLK_F_BLK_SIZE) { ld->sc_secsize = virtio_read_device_config_4(vsc, VIRTIO_BLK_CONFIG_BLK_SIZE); } ld->sc_maxxfer = maxxfersize; if (features & VIRTIO_BLK_F_GEOMETRY) { ld->sc_ncylinders = virtio_read_device_config_2(vsc, VIRTIO_BLK_CONFIG_GEOMETRY_C); ld->sc_nheads = virtio_read_device_config_1(vsc, VIRTIO_BLK_CONFIG_GEOMETRY_H); ld->sc_nsectors = virtio_read_device_config_1(vsc, VIRTIO_BLK_CONFIG_GEOMETRY_S); } ld->sc_maxqueuecnt = qsize; if (ld_virtio_alloc_reqs(sc, qsize) < 0) goto err; mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_BIO); ld->sc_dump = ld_virtio_dump; ld->sc_flush = NULL; ld->sc_start = ld_virtio_start; ld->sc_flags = LDF_ENABLED; ldattach(ld); return; err: vsc->sc_child = (void*)1; return; }
static void artisea_mapregs(struct pci_attach_args *pa, struct pciide_channel *cp, bus_size_t *cmdsizep, bus_size_t *ctlsizep, int (*pci_intr)(void *)) { struct pciide_softc *sc = CHAN_TO_PCIIDE(&cp->ata_channel); struct ata_channel *wdc_cp = &cp->ata_channel; struct wdc_regs *wdr = CHAN_TO_WDC_REGS(wdc_cp); const char *intrstr; pci_intr_handle_t intrhandle; int i; cp->compat = 0; if (sc->sc_pci_ih == NULL) { if (pci_intr_map(pa, &intrhandle) != 0) { aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, "couldn't map native-PCI interrupt\n"); goto bad; } intrstr = pci_intr_string(pa->pa_pc, intrhandle); sc->sc_pci_ih = pci_intr_establish(pa->pa_pc, intrhandle, IPL_BIO, pci_intr, sc); if (sc->sc_pci_ih != NULL) { aprint_normal_dev(sc->sc_wdcdev.sc_atac.atac_dev, "using %s for native-PCI interrupt\n", intrstr ? intrstr : "unknown interrupt"); } else { aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, "couldn't establish native-PCI interrupt"); if (intrstr != NULL) aprint_normal(" at %s", intrstr); aprint_normal("\n"); goto bad; } } cp->ih = sc->sc_pci_ih; wdr->cmd_iot = sc->sc_ba5_st; if (bus_space_subregion (sc->sc_ba5_st, sc->sc_ba5_sh, ARTISEA_DPA_PORT_BASE(wdc_cp->ch_channel), 0x200, &wdr->cmd_baseioh) != 0) { aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, "couldn't map %s channel cmd regs\n", cp->name); goto bad; } wdr->ctl_iot = sc->sc_ba5_st; if (bus_space_subregion(wdr->cmd_iot, wdr->cmd_baseioh, ARTISEA_SUPDDCTLR, 1, &cp->ctl_baseioh) != 0) { aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, "couldn't map %s channel ctl regs\n", cp->name); goto bad; } wdr->ctl_ioh = cp->ctl_baseioh; for (i = 0; i < WDC_NREG + 2; i++) { if (bus_space_subregion(wdr->cmd_iot, wdr->cmd_baseioh, artisea_dpa_cmd_map[i].offset, artisea_dpa_cmd_map[i].size, &wdr->cmd_iohs[i]) != 0) { aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, "couldn't subregion %s channel cmd regs\n", cp->name); goto bad; } } wdr->data32iot = wdr->cmd_iot; wdr->data32ioh = wdr->cmd_iohs[0]; wdr->sata_iot = wdr->cmd_iot; wdr->sata_baseioh = wdr->cmd_baseioh; if (bus_space_subregion(wdr->sata_iot, wdr->sata_baseioh, ARTISEA_SUPERSET_DPA_OFF + ARTISEA_SUPDSSSR, 1, &wdr->sata_status) != 0) { aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, "couldn't map channel %d sata_status regs\n", wdc_cp->ch_channel); goto bad; } if (bus_space_subregion(wdr->sata_iot, wdr->sata_baseioh, ARTISEA_SUPERSET_DPA_OFF + ARTISEA_SUPDSSER, 1, &wdr->sata_error) != 0) { aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, "couldn't map channel %d sata_error regs\n", wdc_cp->ch_channel); goto bad; } if (bus_space_subregion(wdr->sata_iot, wdr->sata_baseioh, ARTISEA_SUPERSET_DPA_OFF + ARTISEA_SUPDSSCR, 1, &wdr->sata_control) != 0) { aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, "couldn't map channel %d sata_control regs\n", wdc_cp->ch_channel); goto bad; } wdcattach(wdc_cp); return; bad: wdc_cp->ch_flags |= ATACH_DISABLED; return; }
static void iavc_pci_attach(struct device * parent, struct device * self, void *aux) { struct iavc_pci_softc *psc = (void *) self; struct iavc_softc *sc = (void *) self; struct pci_attach_args *pa = aux; pci_chipset_tag_t pc = pa->pa_pc; const struct iavc_pci_product *pp; pci_intr_handle_t ih; const char *intrstr; int ret; pp = find_cardname(pa); if (pp == NULL) return; sc->sc_t1 = 0; sc->sc_dma = 0; sc->dmat = pa->pa_dmat; iavc_b1dma_reset(sc); if (pci_mapreg_map(pa, IAVC_PCI_IOBA, PCI_MAPREG_TYPE_IO, 0, &sc->sc_io_bt, &sc->sc_io_bh, &psc->io_base, &psc->io_size)) { aprint_error(": unable to map i/o registers\n"); return; } if (pci_mapreg_map(pa, IAVC_PCI_MMBA, PCI_MAPREG_TYPE_MEM, 0, &sc->sc_mem_bt, &sc->sc_mem_bh, &psc->mem_base, &psc->mem_size)) { aprint_error(": unable to map mem registers\n"); return; } aprint_normal(": %s\n", pp->name); if (pp->npp_product == PCI_PRODUCT_AVM_T1) { aprint_error("%s: sorry, PRI not yet supported\n", sc->sc_dev.dv_xname); return; #if 0 sc->sc_capi.card_type = CARD_TYPEC_AVM_T1_PCI; sc->sc_capi.sc_nbch = NBCH_PRI; ret = iavc_t1_detect(sc); if (ret) { if (ret < 6) { aprint_error("%s: no card detected?\n", sc->sc_dev.dv_xname); } else { aprint_error("%s: black box not on\n", sc->sc_dev.dv_xname); } return; } else { sc->sc_dma = 1; sc->sc_t1 = 1; } #endif } else if (pp->npp_product == PCI_PRODUCT_AVM_B1) { sc->sc_capi.card_type = CARD_TYPEC_AVM_B1_PCI; sc->sc_capi.sc_nbch = NBCH_BRI; ret = iavc_b1dma_detect(sc); if (ret) { ret = iavc_b1_detect(sc); if (ret) { aprint_error("%s: no card detected?\n", sc->sc_dev.dv_xname); return; } } else { sc->sc_dma = 1; } } if (sc->sc_dma) iavc_b1dma_reset(sc); #if 0 /* * XXX: should really be done this way, but this freezes the card */ if (sc->sc_t1) iavc_t1_reset(sc); else iavc_b1_reset(sc); #endif if (pci_intr_map(pa, &ih)) { aprint_error("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname); return; } intrstr = pci_intr_string(pc, ih); psc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, iavc_pci_intr, psc); if (psc->sc_ih == NULL) { aprint_error("%s: couldn't establish interrupt", sc->sc_dev.dv_xname); if (intrstr != NULL) aprint_normal(" at %s", intrstr); aprint_normal("\n"); return; } psc->sc_pc = pc; aprint_normal("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr); memset(&sc->sc_txq, 0, sizeof(struct ifqueue)); sc->sc_txq.ifq_maxlen = sc->sc_capi.sc_nbch * 4; sc->sc_intr = 0; sc->sc_state = IAVC_DOWN; sc->sc_blocked = 0; /* setup capi link */ sc->sc_capi.load = iavc_load; sc->sc_capi.reg_appl = iavc_register; sc->sc_capi.rel_appl = iavc_release; sc->sc_capi.send = iavc_send; sc->sc_capi.ctx = (void *) sc; /* lock & load DMA for TX */ if ((ret = bus_dmamem_alloc(sc->dmat, IAVC_DMA_SIZE, PAGE_SIZE, 0, &sc->txseg, 1, &sc->ntxsegs, BUS_DMA_ALLOCNOW)) != 0) { aprint_error("%s: can't allocate tx DMA memory, error = %d\n", sc->sc_dev.dv_xname, ret); goto fail1; } if ((ret = bus_dmamem_map(sc->dmat, &sc->txseg, sc->ntxsegs, IAVC_DMA_SIZE, &sc->sc_sendbuf, BUS_DMA_NOWAIT)) != 0) { aprint_error("%s: can't map tx DMA memory, error = %d\n", sc->sc_dev.dv_xname, ret); goto fail2; } if ((ret = bus_dmamap_create(sc->dmat, IAVC_DMA_SIZE, 1, IAVC_DMA_SIZE, 0, BUS_DMA_ALLOCNOW | BUS_DMA_NOWAIT, &sc->tx_map)) != 0) { aprint_error("%s: can't create tx DMA map, error = %d\n", sc->sc_dev.dv_xname, ret); goto fail3; } if ((ret = bus_dmamap_load(sc->dmat, sc->tx_map, sc->sc_sendbuf, IAVC_DMA_SIZE, NULL, BUS_DMA_WRITE | BUS_DMA_NOWAIT)) != 0) { aprint_error("%s: can't load tx DMA map, error = %d\n", sc->sc_dev.dv_xname, ret); goto fail4; } /* do the same for RX */ if ((ret = bus_dmamem_alloc(sc->dmat, IAVC_DMA_SIZE, PAGE_SIZE, 0, &sc->rxseg, 1, &sc->nrxsegs, BUS_DMA_ALLOCNOW)) != 0) { aprint_error("%s: can't allocate rx DMA memory, error = %d\n", sc->sc_dev.dv_xname, ret); goto fail5; } if ((ret = bus_dmamem_map(sc->dmat, &sc->rxseg, sc->nrxsegs, IAVC_DMA_SIZE, &sc->sc_recvbuf, BUS_DMA_NOWAIT)) != 0) { aprint_error("%s: can't map rx DMA memory, error = %d\n", sc->sc_dev.dv_xname, ret); goto fail6; } if ((ret = bus_dmamap_create(sc->dmat, IAVC_DMA_SIZE, 1, IAVC_DMA_SIZE, 0, BUS_DMA_ALLOCNOW | BUS_DMA_NOWAIT, &sc->rx_map)) != 0) { aprint_error("%s: can't create rx DMA map, error = %d\n", sc->sc_dev.dv_xname, ret); goto fail7; } if ((ret = bus_dmamap_load(sc->dmat, sc->rx_map, sc->sc_recvbuf, IAVC_DMA_SIZE, NULL, BUS_DMA_READ | BUS_DMA_NOWAIT)) != 0) { aprint_error("%s: can't load rx DMA map, error = %d\n", sc->sc_dev.dv_xname, ret); goto fail8; } if (capi_ll_attach(&sc->sc_capi, sc->sc_dev.dv_xname, pp->name)) { aprint_error("%s: capi attach failed\n", sc->sc_dev.dv_xname); goto fail9; } return; /* release resources in case of failed attach */ fail9: bus_dmamap_unload(sc->dmat, sc->rx_map); fail8: bus_dmamap_destroy(sc->dmat, sc->rx_map); fail7: bus_dmamem_unmap(sc->dmat, sc->sc_recvbuf, IAVC_DMA_SIZE); fail6: bus_dmamem_free(sc->dmat, &sc->rxseg, sc->nrxsegs); fail5: bus_dmamap_unload(sc->dmat, sc->tx_map); fail4: bus_dmamap_destroy(sc->dmat, sc->tx_map); fail3: bus_dmamem_unmap(sc->dmat, sc->sc_sendbuf, IAVC_DMA_SIZE); fail2: bus_dmamem_free(sc->dmat, &sc->txseg, sc->ntxsegs); fail1: pci_intr_disestablish(psc->sc_pc, psc->sc_ih); return; }
void ex_cardbus_attach(device_t parent, device_t self, void *aux) { struct ex_cardbus_softc *csc = device_private(self); struct ex_softc *sc = &csc->sc_softc; struct cardbus_attach_args *ca = aux; cardbus_devfunc_t ct = ca->ca_ct; #if rbus #else cardbus_chipset_tag_t cc = ct->ct_cc; #endif const struct ex_cardbus_product *ecp; bus_addr_t adr, adr1; sc->sc_dev = self; sc->ex_bustype = EX_BUS_CARDBUS; sc->sc_dmat = ca->ca_dmat; csc->sc_ct = ca->ca_ct; csc->sc_intrline = ca->ca_intrline; csc->sc_tag = ca->ca_tag; ecp = ex_cardbus_lookup(ca); if (ecp == NULL) { printf("\n"); panic("ex_cardbus_attach: impossible"); } aprint_normal(": 3Com %s\n", ecp->ecp_name); sc->ex_conf = ecp->ecp_flags; csc->sc_cardtype = ecp->ecp_cardtype; csc->sc_csr = ecp->ecp_csr; if (Cardbus_mapreg_map(ct, CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO, 0, &sc->sc_iot, &sc->sc_ioh, &adr, &csc->sc_mapsize) == 0) { #if rbus #else (*ct->ct_cf->cardbus_io_open)(cc, 0, adr, adr + csc->sc_mapsize); #endif csc->sc_bar_reg = CARDBUS_BASE0_REG; csc->sc_bar_val = adr | CARDBUS_MAPREG_TYPE_IO; if (csc->sc_cardtype == EX_CB_CYCLONE) { /* Map CardBus function status window. */ if (Cardbus_mapreg_map(ct, CARDBUS_3C575BTX_FUNCSTAT_PCIREG, CARDBUS_MAPREG_TYPE_MEM, 0, &csc->sc_funct, &csc->sc_funch, &adr1, &csc->sc_funcsize) == 0) { csc->sc_bar_reg1 = CARDBUS_3C575BTX_FUNCSTAT_PCIREG; csc->sc_bar_val1 = adr1 | CARDBUS_MAPREG_TYPE_MEM; } else { aprint_error_dev(self, "unable to map function " "status window\n"); return; } /* Setup interrupt acknowledge hook */ sc->intr_ack = ex_cardbus_intr_ack; } } else { aprint_naive(": can't map i/o space\n"); return; } /* Power management hooks. */ sc->enable = ex_cardbus_enable; sc->disable = ex_cardbus_disable; /* * Handle power management nonsense and * initialize the configuration registers. */ ex_cardbus_setup(csc); ex_config(sc); if (csc->sc_cardtype == EX_CB_CYCLONE) bus_space_write_4(csc->sc_funct, csc->sc_funch, EX_CB_INTR, EX_CB_INTR_ACK); Cardbus_function_disable(csc->sc_ct); }
static void piixpm_attach(device_t parent, device_t self, void *aux) { struct piixpm_softc *sc = device_private(self); struct pci_attach_args *pa = aux; struct i2cbus_attach_args iba; pcireg_t base, conf; pcireg_t pmmisc; pci_intr_handle_t ih; char devinfo[256]; const char *intrstr = NULL; sc->sc_dev = self; sc->sc_pc = pa->pa_pc; sc->sc_pcitag = pa->pa_tag; aprint_naive("\n"); aprint_normal("\n"); pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo)); aprint_normal_dev(self, "%s (rev. 0x%02x)\n", devinfo, PCI_REVISION(pa->pa_class)); if (!pmf_device_register(self, piixpm_suspend, piixpm_resume)) aprint_error_dev(self, "couldn't establish power handler\n"); /* Read configuration */ conf = pci_conf_read(pa->pa_pc, pa->pa_tag, PIIX_SMB_HOSTC); DPRINTF(("%s: conf 0x%x\n", device_xname(self), conf)); if ((PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL) || (PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_INTEL_82371AB_PMC)) goto nopowermanagement; /* check whether I/O access to PM regs is enabled */ pmmisc = pci_conf_read(pa->pa_pc, pa->pa_tag, PIIX_PMREGMISC); if (!(pmmisc & 1)) goto nopowermanagement; sc->sc_pm_iot = pa->pa_iot; /* Map I/O space */ base = pci_conf_read(pa->pa_pc, pa->pa_tag, PIIX_PM_BASE); if (bus_space_map(sc->sc_pm_iot, PCI_MAPREG_IO_ADDR(base), PIIX_PM_SIZE, 0, &sc->sc_pm_ioh)) { aprint_error_dev(self, "can't map power management I/O space\n"); goto nopowermanagement; } /* * Revision 0 and 1 are PIIX4, 2 is PIIX4E, 3 is PIIX4M. * PIIX4 and PIIX4E have a bug in the timer latch, see Errata #20 * in the "Specification update" (document #297738). */ acpipmtimer_attach(self, sc->sc_pm_iot, sc->sc_pm_ioh, PIIX_PM_PMTMR, (PCI_REVISION(pa->pa_class) < 3) ? ACPIPMT_BADLATCH : 0 ); nopowermanagement: if ((conf & PIIX_SMB_HOSTC_HSTEN) == 0) { aprint_normal_dev(self, "SMBus disabled\n"); return; } /* Map I/O space */ sc->sc_smb_iot = pa->pa_iot; base = pci_conf_read(pa->pa_pc, pa->pa_tag, PIIX_SMB_BASE) & 0xffff; if (bus_space_map(sc->sc_smb_iot, PCI_MAPREG_IO_ADDR(base), PIIX_SMB_SIZE, 0, &sc->sc_smb_ioh)) { aprint_error_dev(self, "can't map smbus I/O space\n"); return; } sc->sc_poll = 1; if ((conf & PIIX_SMB_HOSTC_INTMASK) == PIIX_SMB_HOSTC_SMI) { /* No PCI IRQ */ aprint_normal_dev(self, "interrupting at SMI"); } else if ((conf & PIIX_SMB_HOSTC_INTMASK) == PIIX_SMB_HOSTC_IRQ) { /* Install interrupt handler */ if (pci_intr_map(pa, &ih) == 0) { intrstr = pci_intr_string(pa->pa_pc, ih); sc->sc_smb_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, piixpm_intr, sc); if (sc->sc_smb_ih != NULL) { aprint_normal_dev(self, "interrupting at %s", intrstr); sc->sc_poll = 0; } } } if (sc->sc_poll) aprint_normal_dev(self, "polling"); aprint_normal("\n"); /* Attach I2C bus */ rw_init(&sc->sc_i2c_rwlock); sc->sc_i2c_tag.ic_cookie = sc; sc->sc_i2c_tag.ic_acquire_bus = piixpm_i2c_acquire_bus; sc->sc_i2c_tag.ic_release_bus = piixpm_i2c_release_bus; sc->sc_i2c_tag.ic_exec = piixpm_i2c_exec; bzero(&iba, sizeof(iba)); iba.iba_tag = &sc->sc_i2c_tag; config_found_ia(self, "i2cbus", &iba, iicbus_print); return; }
void uhidev_attach(device_t parent, device_t self, void *aux) { struct uhidev_softc *sc = device_private(self); struct usbif_attach_arg *uiaa = aux; struct usbd_interface *iface = uiaa->uiaa_iface; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; struct uhidev_attach_arg uha; device_t dev; struct uhidev *csc; int maxinpktsize, size, nrepid, repid, repsz; int *repsizes; int i; void *desc; const void *descptr; usbd_status err; char *devinfop; int locs[UHIDBUSCF_NLOCS]; sc->sc_dev = self; sc->sc_udev = uiaa->uiaa_device; sc->sc_iface = iface; aprint_naive("\n"); aprint_normal("\n"); mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB); id = usbd_get_interface_descriptor(iface); devinfop = usbd_devinfo_alloc(uiaa->uiaa_device, 0); aprint_normal_dev(self, "%s, iclass %d/%d\n", devinfop, id->bInterfaceClass, id->bInterfaceSubClass); usbd_devinfo_free(devinfop); if (!pmf_device_register(self, NULL, NULL)) aprint_error_dev(self, "couldn't establish power handler\n"); (void)usbd_set_idle(iface, 0, 0); #if 0 if ((usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_NO_SET_PROTO) == 0 && id->bInterfaceSubClass != UISUBCLASS_BOOT) (void)usbd_set_protocol(iface, 1); #endif maxinpktsize = 0; sc->sc_iep_addr = sc->sc_oep_addr = -1; for (i = 0; i < id->bNumEndpoints; i++) { ed = usbd_interface2endpoint_descriptor(iface, i); if (ed == NULL) { aprint_error_dev(self, "could not read endpoint descriptor\n"); sc->sc_dying = 1; return; } DPRINTFN(10,("uhidev_attach: bLength=%d bDescriptorType=%d " "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d" " bInterval=%d\n", ed->bLength, ed->bDescriptorType, ed->bEndpointAddress & UE_ADDR, UE_GET_DIR(ed->bEndpointAddress)==UE_DIR_IN? "in" : "out", ed->bmAttributes & UE_XFERTYPE, UGETW(ed->wMaxPacketSize), ed->bInterval)); if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) { maxinpktsize = UGETW(ed->wMaxPacketSize); sc->sc_iep_addr = ed->bEndpointAddress; } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) { sc->sc_oep_addr = ed->bEndpointAddress; } else { aprint_verbose_dev(self, "endpoint %d: ignored\n", i); } } /* * Check that we found an input interrupt endpoint. The output interrupt * endpoint is optional */ if (sc->sc_iep_addr == -1) { aprint_error_dev(self, "no input interrupt endpoint\n"); sc->sc_dying = 1; return; } /* XXX need to extend this */ descptr = NULL; if (uiaa->uiaa_vendor == USB_VENDOR_WACOM) { static uByte reportbuf[] = {2, 2, 2}; /* The report descriptor for the Wacom Graphire is broken. */ switch (uiaa->uiaa_product) { case USB_PRODUCT_WACOM_GRAPHIRE: case USB_PRODUCT_WACOM_GRAPHIRE2: case USB_PRODUCT_WACOM_GRAPHIRE3_4X5: case USB_PRODUCT_WACOM_GRAPHIRE3_6X8: case USB_PRODUCT_WACOM_GRAPHIRE4_4X5: /* The 6x8 too? */ /* * The Graphire3 needs 0x0202 to be written to * feature report ID 2 before it'll start * returning digitizer data. */ usbd_set_report(uiaa->uiaa_iface, UHID_FEATURE_REPORT, 2, &reportbuf, sizeof(reportbuf)); size = sizeof(uhid_graphire3_4x5_report_descr); descptr = uhid_graphire3_4x5_report_descr; break; default: /* Keep descriptor */ break; } } if (USBIF_IS_XINPUT(uiaa)) { size = sizeof(uhid_xinput_report_descr); descptr = uhid_xinput_report_descr; } if (USBIF_IS_X1INPUT(uiaa)) { sc->sc_flags |= UHIDEV_F_XB1; size = sizeof(uhid_x1input_report_descr); descptr = uhid_x1input_report_descr; } if (descptr) { desc = kmem_alloc(size, KM_SLEEP); if (desc == NULL) err = USBD_NOMEM; else { err = USBD_NORMAL_COMPLETION; memcpy(desc, descptr, size); } } else { desc = NULL; err = usbd_read_report_desc(uiaa->uiaa_iface, &desc, &size); } if (err) { aprint_error_dev(self, "no report descriptor\n"); sc->sc_dying = 1; return; } if (uiaa->uiaa_vendor == USB_VENDOR_HOSIDEN && uiaa->uiaa_product == USB_PRODUCT_HOSIDEN_PPP) { static uByte reportbuf[] = { 1 }; /* * This device was sold by Konami with its ParaParaParadise * game for PlayStation2. It needs to be "turned on" * before it will send any reports. */ usbd_set_report(uiaa->uiaa_iface, UHID_FEATURE_REPORT, 0, &reportbuf, sizeof(reportbuf)); } if (uiaa->uiaa_vendor == USB_VENDOR_LOGITECH && uiaa->uiaa_product == USB_PRODUCT_LOGITECH_CBT44 && size == 0xb1) { uint8_t *data = desc; /* * This device has a odd USAGE_MINIMUM value that would * cause the multimedia keys to have their usage number * shifted up one usage. Adjust so the usages are sane. */ if (data[0x56] == 0x19 && data[0x57] == 0x01 && data[0x58] == 0x2a && data[0x59] == 0x8c) data[0x57] = 0x00; } /* * Enable the Six Axis and DualShock 3 controllers. * See http://ps3.jim.sh/sixaxis/usb/ */ if (uiaa->uiaa_vendor == USB_VENDOR_SONY && uiaa->uiaa_product == USB_PRODUCT_SONY_PS3CONTROLLER) { usb_device_request_t req; char data[17]; int actlen; req.bmRequestType = UT_READ_CLASS_INTERFACE; req.bRequest = 1; USETW(req.wValue, 0x3f2); USETW(req.wIndex, 0); USETW(req.wLength, sizeof(data)); usbd_do_request_flags(sc->sc_udev, &req, data, USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT); } sc->sc_repdesc = desc; sc->sc_repdesc_size = size; uha.uiaa = uiaa; nrepid = uhidev_maxrepid(desc, size); if (nrepid < 0) return; if (nrepid > 0) aprint_normal_dev(self, "%d report ids\n", nrepid); nrepid++; repsizes = kmem_alloc(nrepid * sizeof(*repsizes), KM_SLEEP); if (repsizes == NULL) goto nomem; sc->sc_subdevs = kmem_zalloc(nrepid * sizeof(device_t), KM_SLEEP); if (sc->sc_subdevs == NULL) { kmem_free(repsizes, nrepid * sizeof(*repsizes)); nomem: aprint_error_dev(self, "no memory\n"); return; } /* Just request max packet size for the interrupt pipe */ sc->sc_isize = maxinpktsize; sc->sc_nrepid = nrepid; usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); for (repid = 0; repid < nrepid; repid++) { repsz = hid_report_size(desc, size, hid_input, repid); DPRINTF(("uhidev_match: repid=%d, repsz=%d\n", repid, repsz)); repsizes[repid] = repsz; } DPRINTF(("uhidev_attach: isize=%d\n", sc->sc_isize)); uha.parent = sc; for (repid = 0; repid < nrepid; repid++) { DPRINTF(("uhidev_match: try repid=%d\n", repid)); if (hid_report_size(desc, size, hid_input, repid) == 0 && hid_report_size(desc, size, hid_output, repid) == 0 && hid_report_size(desc, size, hid_feature, repid) == 0) { ; /* already NULL in sc->sc_subdevs[repid] */ } else { uha.reportid = repid; locs[UHIDBUSCF_REPORTID] = repid; dev = config_found_sm_loc(self, "uhidbus", locs, &uha, uhidevprint, config_stdsubmatch); sc->sc_subdevs[repid] = dev; if (dev != NULL) { csc = device_private(dev); csc->sc_in_rep_size = repsizes[repid]; #ifdef DIAGNOSTIC DPRINTF(("uhidev_match: repid=%d dev=%p\n", repid, dev)); if (csc->sc_intr == NULL) { kmem_free(repsizes, nrepid * sizeof(*repsizes)); aprint_error_dev(self, "sc_intr == NULL\n"); return; } #endif rnd_attach_source(&csc->rnd_source, device_xname(dev), RND_TYPE_TTY, RND_FLAG_DEFAULT); } } } kmem_free(repsizes, nrepid * sizeof(*repsizes)); return; }
/* * 1st pass on BIOS's Intel MP specification table. * * initializes: * mp_ncpus = 1 * * determines: * cpu_apic_address (common to all CPUs) * ioapic_address[N] * mp_naps * mp_nbus * mp_napics * nintrs */ void mpbios_scan(device_t self, int *ncpup) { const uint8_t *position, *end; size_t i; int count; int type; int intr_cnt, cur_intr; paddr_t lapic_base; const struct dflt_conf_entry *dflt_conf; const int *dflt_bus_irq; const struct mpbios_int *iep; struct mpbios_int ie; aprint_normal_dev(self, "Intel MP Specification "); switch (mp_fps->spec_rev) { case 1: aprint_normal("(Version 1.1)"); break; case 4: aprint_normal("(Version 1.4)"); break; default: aprint_normal("(unrecognized rev %d)", mp_fps->spec_rev); } /* * looks like we've got a MP system. start setting up * infrastructure.. * XXX is this the right place?? */ #if NACPICA > 0 if (mpacpi_ncpu == 0) { #endif lapic_base = LAPIC_BASE; if (mp_cth != NULL) lapic_base = (paddr_t)mp_cth->apic_address; #if NLAPIC > 0 lapic_boot_init(lapic_base); #endif #if NACPICA > 0 } #endif /* check for use of 'default' configuration */ if (mp_fps->mpfb1 != 0) { if (mp_fps->mpfb1 > __arraycount(dflt_conf_tab)) panic("Unsupported MP default configuration %d\n", mp_fps->mpfb1); aprint_normal("\n"); aprint_normal_dev(self, "MP default configuration %d\n", mp_fps->mpfb1); dflt_conf = &dflt_conf_tab[mp_fps->mpfb1 - 1]; dflt_bus_irq = dflt_bus_irq_tab[(dflt_conf->flags & IRQ_VAR) != 0]; #if NACPICA > 0 if (mpacpi_ncpu == 0) #endif mpbios_dflt_conf_cpu(self); #if NACPICA > 0 if (mpacpi_nioapic == 0) #endif mpbios_dflt_conf_ioapic(self); /* * Walk the table once, counting items. */ mp_nbus = 0; for (i = 0; i < __arraycount(dflt_conf->bus_type); i++) { if (dflt_conf->bus_type[i] != NULL) mp_nbus++; } KASSERT(mp_nbus != 0); mp_busses = kmem_zalloc(sizeof(struct mp_bus) * mp_nbus, KM_SLEEP); KASSERT(mp_busses != NULL); /* INTIN0 */ intr_cnt = (dflt_conf->flags & INTIN0_NC) ? 0 : 1; /* INTINx */ for (i = 0; i < __arraycount(dflt_bus_irq_tab[0]); i++) { if (dflt_bus_irq[i] >= 0) intr_cnt++; } KASSERT(intr_cnt != 0); /* LINTINx */ for (i = 0; i < __arraycount(dflt_lint_tab); i++) intr_cnt++; mp_intrs = kmem_zalloc(sizeof(struct mp_intr_map) * intr_cnt, KM_SLEEP); KASSERT(mp_intrs != NULL); mp_nintr = intr_cnt; /* * Re-walk the table, recording info of interest. */ mpbios_dflt_conf_bus(self, dflt_conf); mpbios_dflt_conf_int(self, dflt_conf, dflt_bus_irq); } else { /* * should not happen; mp_probe returns 0 in this case, * but.. */ if (mp_cth == NULL) panic ("mpbios_scan: no config (can't happen?)"); printf(" (%8.8s %12.12s)\n", mp_cth->oem_id, mp_cth->product_id); /* * Walk the table once, counting items */ position = (const uint8_t *)(mp_cth); end = position + mp_cth->base_len; position += sizeof(*mp_cth); count = mp_cth->entry_count; intr_cnt = 0; while ((count--) && (position < end)) { type = *position; if (type >= MPS_MCT_NTYPES) { aprint_error_dev(self, "unknown entry type %x" " in MP config table\n", type); break; } mp_conf[type].count++; if (type == MPS_MCT_BUS) { const struct mpbios_bus *bp = (const struct mpbios_bus *)position; if (bp->bus_id >= mp_nbus) mp_nbus = bp->bus_id + 1; } /* * Count actual interrupt instances. * dst_apic_id of MPS_ALL_APICS means "wired to all * apics of this type". */ if (type == MPS_MCT_IOINT) { iep = (const struct mpbios_int *)position; if (iep->dst_apic_id == MPS_ALL_APICS) intr_cnt += mp_conf[MPS_MCT_IOAPIC].count; else intr_cnt++; } else if (type == MPS_MCT_LINT) intr_cnt++; position += mp_conf[type].length; } mp_busses = kmem_zalloc(sizeof(struct mp_bus)*mp_nbus, KM_SLEEP); KASSERT(mp_busses != NULL); mp_intrs = kmem_zalloc(sizeof(struct mp_intr_map)*intr_cnt, KM_SLEEP); KASSERT(mp_intrs != NULL); mp_nintr = intr_cnt; /* re-walk the table, recording info of interest */ position = (const uint8_t *) mp_cth + sizeof(*mp_cth); count = mp_cth->entry_count; cur_intr = 0; while ((count--) && (position < end)) { switch (type = *position) { case MPS_MCT_CPU: #if NACPICA > 0 /* ACPI has done this for us */ if (mpacpi_ncpu) break; #endif mpbios_cpu(position, self); break; case MPS_MCT_BUS: mpbios_bus(position, self); break; case MPS_MCT_IOAPIC: #if NACPICA > 0 /* ACPI has done this for us */ if (mpacpi_nioapic) break; #endif mpbios_ioapic(position, self); break; case MPS_MCT_IOINT: iep = (const struct mpbios_int *)position; ie = *iep; if (iep->dst_apic_id == MPS_ALL_APICS) { #if NIOAPIC > 0 struct ioapic_softc *sc; for (sc = ioapics ; sc != NULL; sc = sc->sc_next) { ie.dst_apic_id = sc->sc_apicid; mpbios_int((char *)&ie, type, &mp_intrs[cur_intr++]); } #endif } else { mpbios_int(position, type, &mp_intrs[cur_intr++]); } break; case MPS_MCT_LINT: mpbios_int(position, type, &mp_intrs[cur_intr]); cur_intr++; break; default: aprint_error_dev(self, "unknown entry type %x in MP config table\n", type); /* NOTREACHED */ return; } position += mp_conf[type].length; } if (mp_verbose && mp_cth->ext_len) aprint_verbose_dev(self, "MP WARNING: %d bytes of extended entries not examined\n", mp_cth->ext_len); } /* Clean up. */ mp_fps = NULL; mpbios_unmap (&mp_fp_map); if (mp_cth != NULL) { mp_cth = NULL; mpbios_unmap (&mp_cfg_table_map); } mpbios_scanned = 1; *ncpup = mpbios_ncpu; }
static void ne_intio_attach(device_t parent, device_t self, void *aux) { struct ne_intio_softc *sc = device_private(self); struct dp8390_softc *dsc = &sc->sc_dp8390; struct intio_attach_args *ia = aux; bus_space_tag_t iot = ia->ia_bst; bus_space_handle_t ioh; bus_space_tag_t asict; bus_space_handle_t asich; const char *typestr; int netype; dsc->sc_dev = self; aprint_normal(": Nereid Ethernet\n"); /* Map I/O space */ if (bus_space_map(iot, ia->ia_addr, NE2000_NPORTS*2, BUS_SPACE_MAP_SHIFTED_EVEN, &ioh)){ aprint_error_dev(self, "can't map I/O space\n"); return; } asict = iot; if (bus_space_subregion(iot, ioh, NE2000_ASIC_OFFSET*2, NE2000_ASIC_NPORTS*2, &asich)) { aprint_error_dev(self, "can't subregion I/O space\n"); return; } dsc->sc_regt = iot; dsc->sc_regh = ioh; sc->sc_asict = asict; sc->sc_asich = asich; /* * detect it again, so we can print some information about * the interface. * XXX: Should I check NE1000 or NE2000 for Nereid? */ netype = ne2000_detect(iot, ioh, asict, asich); switch (netype) { case NE2000_TYPE_NE1000: typestr = "NE1000"; break; case NE2000_TYPE_NE2000: typestr = "NE2000"; break; case NE2000_TYPE_RTL8019: typestr = "NE2000 (RTL8019)"; break; default: aprint_error_dev(self, "where did the card go?!\n"); return; } aprint_normal_dev(self, "%s Ethernet\n", typestr); /* This interface is always enabled */ dsc->sc_enabled = 1; /* * Do generic NE2000 attach. * This will read the mac address from the EEPROM. */ ne2000_attach(sc, NULL); /* Establish the interrupt handler */ if (intio_intr_establish(ia->ia_intr, "ne", dp8390_intr, dsc)) aprint_error_dev(self, "couldn't establish interrupt handler\n"); }
/* * Get the base address for the monitoring registers and set up the * sysmon_envsys(9) framework. */ static void smsc_attach(device_t parent, device_t self, void *aux) { struct smsc_softc *sc = device_private(self); struct isa_attach_args *ia = aux; bus_space_handle_t ioh; uint8_t rev, msb, lsb, chipid; unsigned address; int i; sc->sc_iot = ia->ia_iot; aprint_naive("\n"); /* * To attach we need to find the actual Hardware Monitor * I/O address space. */ if (bus_space_map(ia->ia_iot, ia->ia_io[0].ir_addr, 2, 0, &ioh)) { aprint_error(": can't map base i/o space\n"); return; } /* Enter config mode */ bus_space_write_1(ia->ia_iot, ioh, SMSC_ADDR, SMSC_CONFIG_START); /* * While we have the base registers mapped, grab the chip * revision and device ID. */ rev = smsc_readreg(ia->ia_iot, ioh, SMSC_DEVICE_REVISION); chipid = smsc_readreg(ia->ia_iot, ioh, SMSC_DEVICE_ID); /* Select the Hardware Monitor LDN */ smsc_writereg(ia->ia_iot, ioh, SMSC_LOGICAL_DEV_SEL, SMSC_LOGICAL_DEVICE); /* Read the base address for the registers. */ msb = smsc_readreg(ia->ia_iot, ioh, SMSC_IO_BASE_MSB); lsb = smsc_readreg(ia->ia_iot, ioh, SMSC_IO_BASE_LSB); address = (msb << 8) | lsb; /* Exit config mode */ bus_space_write_1(ia->ia_iot, ioh, SMSC_ADDR, SMSC_CONFIG_END); bus_space_unmap(ia->ia_iot, ioh, 2); /* Map the Hardware Monitor I/O space. */ if (bus_space_map(ia->ia_iot, address, 2, 0, &sc->sc_ioh)) { aprint_error(": can't map register i/o space\n"); return; } sc->sc_sme = sysmon_envsys_create(); #define INITSENSOR(index, string, reg, type) \ do { \ strlcpy(sc->sc_sensor[index].desc, string, \ sizeof(sc->sc_sensor[index].desc)); \ sc->sc_sensor[index].units = type; \ sc->sc_regs[index] = reg; \ sc->sc_sensor[index].state = ENVSYS_SVALID; \ } while (/* CONSTCOND */ 0) /* Temperature sensors */ INITSENSOR(0, "Temp0", SMSC_TEMP1, ENVSYS_STEMP); INITSENSOR(1, "Temp1", SMSC_TEMP2, ENVSYS_STEMP); INITSENSOR(2, "Temp2", SMSC_TEMP3, ENVSYS_STEMP); INITSENSOR(3, "Temp3", SMSC_TEMP4, ENVSYS_STEMP); /* Fan sensors */ INITSENSOR(4, "Fan0", SMSC_FAN1_LSB, ENVSYS_SFANRPM); INITSENSOR(5, "Fan1", SMSC_FAN2_LSB, ENVSYS_SFANRPM); INITSENSOR(6, "Fan2", SMSC_FAN3_LSB, ENVSYS_SFANRPM); INITSENSOR(7, "Fan3", SMSC_FAN4_LSB, ENVSYS_SFANRPM); for (i = 0; i < SMSC_MAX_SENSORS; i++) { sc->sc_sensor[i].state = ENVSYS_SINVALID; if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[i])) { sysmon_envsys_destroy(sc->sc_sme); bus_space_unmap(sc->sc_iot, sc->sc_ioh, 2); return; } } sc->sc_sme->sme_name = device_xname(self); sc->sc_sme->sme_cookie = sc; sc->sc_sme->sme_refresh = smsc_refresh; if ((i = sysmon_envsys_register(sc->sc_sme)) != 0) { aprint_error(": unable to register with sysmon (%d)\n", i); sysmon_envsys_destroy(sc->sc_sme); bus_space_unmap(sc->sc_iot, sc->sc_ioh, 2); return; } switch (chipid) { case SMSC_ID_47B397: aprint_normal(": SMSC LPC47B397 Super I/O"); break; case SMSC_ID_SCH5307NS: aprint_normal(": SMSC SCH5307-NS Super I/O"); break; case SMSC_ID_SCH5317: aprint_normal(": SMSC SCH5317 Super I/O"); break; } aprint_normal(" (rev %u)\n", rev); aprint_normal_dev(self, "Hardware Monitor registers at 0x%04x\n", address); }
STATIC void cardslotattach(device_t parent, device_t self, void *aux) { struct cardslot_softc *sc = device_private(self); struct cardslot_attach_args *caa = aux; struct cbslot_attach_args *cba = caa->caa_cb_attach; struct pcmciabus_attach_args *pa = caa->caa_16_attach; struct cardbus_softc *csc = NULL; struct pcmcia_softc *psc = NULL; sc->sc_dev = self; sc->sc_cb_softc = NULL; sc->sc_16_softc = NULL; SIMPLEQ_INIT(&sc->sc_events); sc->sc_th_enable = 0; aprint_naive("\n"); aprint_normal("\n"); DPRINTF(("%s attaching CardBus bus...\n", device_xname(self))); if (cba != NULL) { csc = device_private(config_found_ia(self, "cbbus", cba, cardslot_cb_print)); if (csc) { /* cardbus found */ DPRINTF(("%s: found cardbus on %s\n", __func__, device_xname(self))); sc->sc_cb_softc = csc; } } if (pa != NULL) { sc->sc_16_softc = config_found_sm_loc(self, "pcmciabus", NULL, pa, cardslot_16_print, cardslot_16_submatch); if (sc->sc_16_softc) { /* pcmcia 16-bit bus found */ DPRINTF(("%s: found 16-bit pcmcia bus\n", __func__)); psc = device_private(sc->sc_16_softc); } } if (csc != NULL || psc != NULL) { config_pending_incr(self); if (kthread_create(PRI_NONE, 0, NULL, cardslot_event_thread, sc, &sc->sc_event_thread, "%s", device_xname(self))) { aprint_error_dev(sc->sc_dev, "unable to create thread\n"); panic("cardslotattach"); } sc->sc_th_enable = 1; } if (csc && (csc->sc_cf->cardbus_ctrl)(csc->sc_cc, CARDBUS_CD)) { DPRINTF(("%s: CardBus card found\n", __func__)); /* attach deferred */ cardslot_event_throw(sc, CARDSLOT_EVENT_INSERTION_CB); } if (psc && (psc->pct->card_detect)(psc->pch)) { DPRINTF(("%s: 16-bit card found\n", __func__)); /* attach deferred */ cardslot_event_throw(sc, CARDSLOT_EVENT_INSERTION_16); } if (!pmf_device_register(self, NULL, NULL)) aprint_error_dev(self, "couldn't establish power handler\n"); }