Esempio n. 1
0
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);
	}
}
Esempio n. 2
0
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");
}
Esempio n. 3
0
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;
}
Esempio n. 4
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);
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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);
}
Esempio n. 7
0
/*
 * 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);
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
/*
 * 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");

}
Esempio n. 10
0
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);
}
Esempio n. 11
0
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);
}
Esempio n. 12
0
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);
}
Esempio n. 13
0
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");
}
Esempio n. 14
0
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;
}
Esempio n. 15
0
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);
	}
}
Esempio n. 17
0
/*
 * 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;
}
Esempio n. 19
0
/* 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);
}
Esempio n. 20
0
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);

}
Esempio n. 21
0
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;
}
Esempio n. 23
0
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;
}
Esempio n. 24
0
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);
}
Esempio n. 25
0
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;
}
Esempio n. 26
0
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;
}
Esempio n. 27
0
/*
 * 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;
}
Esempio n. 28
0
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");
}
Esempio n. 29
0
/*
 * 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);
}
Esempio n. 30
0
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");
}