示例#1
0
文件: uhidev.c 项目: ryo/netbsd-src
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;
}
示例#2
0
static void
fwohci_pci_attach(device_t parent, device_t self, void *aux)
{
	struct pci_attach_args *pa = (struct pci_attach_args *) aux;
	struct fwohci_pci_softc *psc = device_private(self);
	char const *intrstr;
	pci_intr_handle_t ih;
	uint32_t csr;
	char intrbuf[PCI_INTRSTR_LEN];

	pci_aprint_devinfo(pa, "IEEE 1394 Controller");

	fwohci_init(&psc->psc_sc);

	psc->psc_sc.fc.dev = self;
	psc->psc_sc.fc.dmat = pa->pa_dmat;
	psc->psc_pc = pa->pa_pc;
	psc->psc_tag = pa->pa_tag;

	/* Map I/O registers */
	if (pci_mapreg_map(pa, PCI_OHCI_MAP_REGISTER, PCI_MAPREG_TYPE_MEM, 0,
	    &psc->psc_sc.bst, &psc->psc_sc.bsh, NULL, &psc->psc_sc.bssize)) {
		aprint_error_dev(self, "can't map OHCI register space\n");
		goto fail;
	}

	/* Disable interrupts, so we don't get any spurious ones. */
	OWRITE(&psc->psc_sc, FWOHCI_INTMASKCLR, OHCI_INT_EN);

	/* Enable the device. */
	csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
	csr |= PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_MEM_ENABLE;
	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, csr);

	/*
	 * Some Sun FireWire controllers have their intpin register
	 * bogusly set to 0, although it should be 3. Correct that.
	 */
	if ((PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SUN) &&
	    (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SUN_FIREWIRE))
		if (pa->pa_intrpin == 0)
			pa->pa_intrpin = 3;

	/* Map and establish the interrupt. */
	if (pci_intr_map(pa, &ih)) {
		aprint_error_dev(self, "couldn't map interrupt\n");
		goto fail;
	}
	intrstr = pci_intr_string(pa->pa_pc, ih, intrbuf, sizeof(intrbuf));
	psc->psc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, fwohci_intr,
	    &psc->psc_sc);
	if (psc->psc_ih == NULL) {
		aprint_error_dev(self, "couldn't establish interrupt");
		if (intrstr != NULL)
			aprint_error(" at %s", intrstr);
		aprint_error("\n");
		goto fail;
	}
	aprint_normal_dev(self, "interrupting at %s\n", intrstr);

	if (fwohci_attach(&psc->psc_sc) != 0)
		goto fail;

	if (!pmf_device_register(self, fwohci_pci_suspend, fwohci_pci_resume))
		aprint_error_dev(self, "couldn't establish power handler\n");

	return;

fail:
	/* In the event that we fail to attach, register a null pnp handler */
	if (!pmf_device_register(self, NULL, NULL))
		aprint_error_dev(self, "couldn't establish power handler\n");

	return;
}
示例#3
0
static void
coram_attach(device_t parent, device_t self, void *aux)
{
	struct coram_softc *sc = device_private(self);
	const struct pci_attach_args *pa = aux;
	pci_intr_handle_t ih;
	pcireg_t reg;
	const char *intrstr;
	struct coram_iic_softc *cic;
	uint32_t value;
	int i;
#ifdef CORAM_ATTACH_I2C
	struct i2cbus_attach_args iba;
#endif

	sc->sc_dev = self;

	pci_aprint_devinfo(pa, NULL);

	reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
	sc->sc_board = coram_board_lookup(PCI_VENDOR(reg), PCI_PRODUCT(reg));
	KASSERT(sc->sc_board != NULL);

	if (pci_mapreg_map(pa, CX23885_MMBASE, PCI_MAPREG_TYPE_MEM, 0,
			   &sc->sc_memt, &sc->sc_memh, NULL, &sc->sc_mems)) {
		aprint_error_dev(self, "couldn't map memory space\n");
		return;
	}

	sc->sc_dmat = pa->pa_dmat;
	sc->sc_pc = pa->pa_pc;

	if (pci_intr_map(pa, &ih)) {
		aprint_error_dev(self, "couldn't map interrupt\n");
		return;
	}
	intrstr = pci_intr_string(pa->pa_pc, ih);
	sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_VM, coram_intr, self);
	if (sc->sc_ih == NULL) {
		aprint_error_dev(self, "couldn't establish interrupt");
		if (intrstr != NULL)
			aprint_error(" at %s", intrstr);
		aprint_error("\n");
		return;
	}
	aprint_normal_dev(self, "interrupting at %s\n", intrstr);

	/* set master */
	reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
	reg |= PCI_COMMAND_MASTER_ENABLE;
	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, reg);

	/* I2C */
	for(i = 0; i < I2C_NUM; i++) {
		cic = &sc->sc_iic[i];

		cic->cic_sc = sc;
		if (bus_space_subregion(sc->sc_memt, sc->sc_memh,
		    I2C_BASE + (I2C_SIZE * i), I2C_SIZE, &cic->cic_regh))
			panic("failed to subregion i2c");

		mutex_init(&cic->cic_busmutex, MUTEX_DRIVER, IPL_NONE);
		cic->cic_i2c.ic_cookie = cic;
		cic->cic_i2c.ic_acquire_bus = coram_iic_acquire_bus;
		cic->cic_i2c.ic_release_bus = coram_iic_release_bus;
		cic->cic_i2c.ic_exec = coram_iic_exec;

#ifdef CORAM_ATTACH_I2C
		/* attach iic(4) */
		memset(&iba, 0, sizeof(iba));
		iba.iba_tag = &cic->cic_i2c;
		iba.iba_type = I2C_TYPE_SMBUS;
		cic->cic_i2cdev = config_found_ia(self, "i2cbus", &iba,
		    iicbus_print);
#endif
	}

	/* HVR1250 GPIO */
	value = bus_space_read_4(sc->sc_memt, sc->sc_memh, 0x110010);
#if 1
	value &= ~0x00010001;
	bus_space_write_4(sc->sc_memt, sc->sc_memh, 0x110010, value);
	delay(5000);
#endif
	value |= 0x00010001;
	bus_space_write_4(sc->sc_memt, sc->sc_memh, 0x110010, value);

#if 0
	int i;
	uint8_t foo[256];
	uint8_t bar;
	bar = 0;
//	seeprom_bootstrap_read(&sc->sc_i2c, 0x50, 0, 256, foo, 256);

	iic_acquire_bus(&sc->sc_i2c, I2C_F_POLL);
	iic_exec(&sc->sc_i2c, I2C_OP_READ_WITH_STOP, 0x50, &bar, 1, foo, 256,
	    I2C_F_POLL);
	iic_release_bus(&sc->sc_i2c, I2C_F_POLL);

	printf("\n");
	for ( i = 0; i < 256; i++) {
		if ( (i % 8) == 0 )
			printf("%02x: ", i);

		printf("%02x", foo[i]);

		if ( (i % 8) == 7 )
			printf("\n");
		else
			printf(" ");
	}
	printf("\n");
#endif

	sc->sc_demod = cx24227_open(sc->sc_dev, &sc->sc_iic[0].cic_i2c, 0x19);
	if (sc->sc_demod == NULL)
		aprint_error_dev(self, "couldn't open cx24227\n");
	sc->sc_tuner = mt2131_open(sc->sc_dev, &sc->sc_iic[0].cic_i2c, 0x61);
	if (sc->sc_tuner == NULL)
		aprint_error_dev(self, "couldn't open mt2131\n");

	coram_mpeg_attach(sc);

	if (!pmf_device_register(self, NULL, coram_resume))
		aprint_error_dev(self, "couldn't establish power handler\n");

	return;
}
示例#4
0
/*
 * Attach hardware to driver, attach hardware driver to audio
 * pseudo-device driver.
 */
void
wss_isapnp_attach(device_t parent, device_t self, void *aux)
{
	struct wss_softc *sc;
	struct ad1848_softc *ac;
	struct isapnp_attach_args *ipa;
	int variant;

	sc = device_private(self);
	ac = &sc->sc_ad1848.sc_ad1848;
	ac->sc_dev = self;
	ipa = aux;
	printf("\n");

	if (!isapnp_devmatch(aux, &isapnp_wss_devinfo, &variant)) {
		aprint_error_dev(self, "match failed?\n");
		return;
	}

	if (isapnp_config(ipa->ipa_iot, ipa->ipa_memt, ipa)) {
		aprint_error_dev(self, "error in region allocation\n");
		return;
	}

	switch (variant) {
	case 1:
		/* We have to put the chip into `WSS mode'. */
		{
			bus_space_tag_t iot;
			bus_space_handle_t ioh;

			iot = ipa->ipa_iot;
			ioh = ipa->ipa_io[0].h;

			while (bus_space_read_1(iot, ioh,
			    SBP_DSP_WSTAT) & SB_DSP_BUSY);
			bus_space_write_1(iot, ioh, SBP_DSP_WRITE, 0x09);
			while (bus_space_read_1(iot, ioh,
			    SBP_DSP_WSTAT) & SB_DSP_BUSY);
			bus_space_write_1(iot, ioh, SBP_DSP_WRITE, 0x00);
			while (bus_space_read_1(iot, ioh,
			    SBP_DSP_WSTAT) & SB_DSP_BUSY);

			delay(1000);
		}

		sc->sc_iot = ipa->ipa_iot;
		sc->sc_ioh = ipa->ipa_io[2].h;
		break;

	default:
		sc->sc_iot = ipa->ipa_iot;
		sc->sc_ioh = ipa->ipa_io[0].h;
		break;
	}

	sc->mad_chip_type = MAD_NONE;

	/* Set up AD1848 I/O handle. */
	ac->sc_iot = sc->sc_iot;
	ac->sc_ioh = sc->sc_ioh;

	sc->sc_ad1848.sc_ic = ipa->ipa_ic;

	sc->wss_ic = ipa->ipa_ic;
	sc->wss_irq = ipa->ipa_irq[0].num;
	sc->wss_playdrq = ipa->ipa_drq[0].num;
	sc->wss_recdrq =
	    ipa->ipa_ndrq > 1 ? ipa->ipa_drq[1].num : ipa->ipa_drq[0].num;

	if (!ad1848_isa_probe(&sc->sc_ad1848)) {
		aprint_error_dev(self, "ad1848_probe failed\n");
		return;
	}

	aprint_error_dev(self, "%s %s", ipa->ipa_devident,
	    ipa->ipa_devclass);

	ac->mode = 2;

	wssattach(sc);

	/* set up OPL I/O handle for ISAPNP boards w/o MAD */
	if (ipa->ipa_nio > 1 && sc->mad_chip_type == MAD_NONE) {
		struct audio_attach_args arg;

		sc->sc_opl_ioh = ipa->ipa_io[1].h;

		arg.type = AUDIODEV_TYPE_OPL;
		arg.hwif = 0;
		arg.hdl = 0;
		(void)config_found(self, &arg, audioprint);
	}
}
示例#5
0
/*
 * Attach a display.  We need to notice if it is the console, too.
 */
static void
p9100_sbus_attach(struct device *parent, struct device *self, void *args)
{
	struct p9100_softc *sc = device_private(self);
	struct sbus_attach_args *sa = args;
	struct fbdevice *fb = &sc->sc_fb;
	int isconsole;
	int node;
	int i, j;
	uint8_t ver;

#if NWSDISPLAY > 0
	struct wsemuldisplaydev_attach_args aa;
	struct rasops_info *ri;
	unsigned long defattr;
#endif

	sc->sc_last_offset = 0xffffffff;

	/* Remember cookies for p9100_mmap() */
	sc->sc_bustag = sa->sa_bustag;
	sc->sc_ctl_paddr = sbus_bus_addr(sa->sa_bustag,
		sa->sa_reg[0].oa_space, sa->sa_reg[0].oa_base);
	sc->sc_ctl_psize = 0x8000;/*(bus_size_t)sa->sa_reg[0].oa_size;*/

	sc->sc_cmd_paddr = sbus_bus_addr(sa->sa_bustag,
		sa->sa_reg[1].oa_space, sa->sa_reg[1].oa_base);
	sc->sc_cmd_psize = (bus_size_t)sa->sa_reg[1].oa_size;

	sc->sc_fb_paddr = sbus_bus_addr(sa->sa_bustag,
		sa->sa_reg[2].oa_space, sa->sa_reg[2].oa_base);
	sc->sc_fb_psize = (bus_size_t)sa->sa_reg[2].oa_size;

	fb->fb_driver = &p9100fbdriver;
	fb->fb_device = &sc->sc_dev;
	fb->fb_flags = device_cfdata(&sc->sc_dev)->cf_flags & FB_USERMASK;
#ifdef PNOZZ_EMUL_CG3
	fb->fb_type.fb_type = FBTYPE_SUN3COLOR;
#else
	fb->fb_type.fb_type = FBTYPE_P9100;
#endif
	fb->fb_pixels = NULL;

	sc->sc_mode = WSDISPLAYIO_MODE_EMUL;

	node = sa->sa_node;
	isconsole = fb_is_console(node);
	if (!isconsole) {
		aprint_normal("\n");
		aprint_error_dev(self, "fatal error: PROM didn't configure device\n");
		return;
	}

	/*
	 * When the ROM has mapped in a p9100 display, the address
	 * maps only the video RAM, so in any case we have to map the
	 * registers ourselves.  We only need the video RAM if we are
	 * going to print characters via rconsole.
	 */
	if (sbus_bus_map(sc->sc_bustag,
			 sa->sa_reg[0].oa_space,
			 sa->sa_reg[0].oa_base,
			 /*
			  * XXX for some reason the SBus resources don't cover
			  * all registers, so we just map what we need
			  */
			 /*sc->sc_ctl_psize*/ 0x8000,
			 /*BUS_SPACE_MAP_LINEAR*/0, &sc->sc_ctl_memh) != 0) {
		aprint_error_dev(self, "cannot map control registers\n");
		return;
	}

	if (sa->sa_npromvaddrs != 0)
		fb->fb_pixels = (void *)sa->sa_promvaddrs[0];

	if (fb->fb_pixels == NULL) {
		if (sbus_bus_map(sc->sc_bustag,
				sa->sa_reg[2].oa_space,
				sa->sa_reg[2].oa_base,
				sc->sc_fb_psize,
				BUS_SPACE_MAP_LINEAR, &sc->sc_fb_memh) != 0) {
			aprint_error_dev(self, "cannot map framebuffer\n");
			return;
		}
		fb->fb_pixels = (char *)sc->sc_fb_memh;
	} else {
		sc->sc_fb_memh = (bus_space_handle_t) fb->fb_pixels;
	}

	i = p9100_ctl_read_4(sc, 0x0004);
	switch ((i >> 26) & 7) {
	    case 5: fb->fb_type.fb_depth = 32; break;
	    case 7: fb->fb_type.fb_depth = 24; break;
	    case 3: fb->fb_type.fb_depth = 16; break;
	    case 2: fb->fb_type.fb_depth = 8; break;
	    default: {
		panic("pnozz: can't determine screen depth (0x%02x)", i);
	    }
	}
	sc->sc_depth = (fb->fb_type.fb_depth >> 3);

	/* XXX for some reason I get a kernel trap with this */
	sc->sc_width = prom_getpropint(node, "width", 800);
	sc->sc_height = prom_getpropint(node, "height", 600);

	sc->sc_stride = prom_getpropint(node, "linebytes", sc->sc_width *
	    (fb->fb_type.fb_depth >> 3));

	/* check the RAMDAC */
	ver = p9100_ramdac_read_ctl(sc, DAC_VERSION);

	p9100_init_engine(sc);

	fb_setsize_obp(fb, fb->fb_type.fb_depth, sc->sc_width, sc->sc_height,
	    node);

	sbus_establish(&sc->sc_sd, &sc->sc_dev);
	bus_intr_establish(sc->sc_bustag, sa->sa_pri, IPL_BIO,
	    p9100_intr, sc);

	fb->fb_type.fb_size = fb->fb_type.fb_height * fb->fb_linebytes;
	printf(": rev %d / %x, %dx%d, depth %d mem %x",
	       (i & 7), ver, fb->fb_type.fb_width, fb->fb_type.fb_height,
	       fb->fb_type.fb_depth, (unsigned int)sc->sc_fb_psize);

	fb->fb_type.fb_cmsize = prom_getpropint(node, "cmsize", 256);
	if ((1 << fb->fb_type.fb_depth) != fb->fb_type.fb_cmsize)
		printf(", %d entry colormap", fb->fb_type.fb_cmsize);

	/* Initialize the default color map. */
	/*bt_initcmap(&sc->sc_cmap, 256);*/
	j = 0;
	for (i = 0; i < 256; i++) {
		sc->sc_cmap.cm_map[i][0] = rasops_cmap[j];
		j++;
		sc->sc_cmap.cm_map[i][1] = rasops_cmap[j];
		j++;
		sc->sc_cmap.cm_map[i][2] = rasops_cmap[j];
		j++;
	}
	p9100loadcmap(sc, 0, 256);

	/* make sure we are not blanked */
	if (isconsole)
		p9100_set_video(sc, 1);

	if (shutdownhook_establish(p9100_shutdown, sc) == NULL) {
		panic("%s: could not establish shutdown hook",
		      device_xname(&sc->sc_dev));
	}

	if (isconsole) {
		printf(" (console)\n");
#ifdef RASTERCONSOLE
		/*p9100loadcmap(sc, 255, 1);*/
		fbrcons_init(fb);
#endif
	} else
		printf("\n");

#if NWSDISPLAY > 0
	wsfont_init();

	vcons_init(&sc->vd, sc, &p9100_defscreendesc, &p9100_accessops);
	sc->vd.init_screen = p9100_init_screen;

	vcons_init_screen(&sc->vd, &p9100_console_screen, 1, &defattr);
	p9100_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;

	sc->sc_bg = (defattr >> 16) & 0xff;
	p9100_clearscreen(sc);

	ri = &p9100_console_screen.scr_ri;

	p9100_defscreendesc.nrows = ri->ri_rows;
	p9100_defscreendesc.ncols = ri->ri_cols;
	p9100_defscreendesc.textops = &ri->ri_ops;
	p9100_defscreendesc.capabilities = ri->ri_caps;

	if(isconsole) {
		wsdisplay_cnattach(&p9100_defscreendesc, ri, 0, 0, defattr);
	}

	aa.console = isconsole;
	aa.scrdata = &p9100_screenlist;
	aa.accessops = &p9100_accessops;
	aa.accesscookie = &sc->vd;

	config_found(self, &aa, wsemuldisplaydevprint);
#endif
	/* cursor sprite handling */
	p9100_init_cursor(sc);

	/* attach the fb */
	fb_attach(fb, isconsole);

	/* register with power management */
	sc->sc_video = 1;
	sc->sc_powerstate = PWR_RESUME;
	powerhook_establish(device_xname(&sc->sc_dev), p9100_power_hook, sc);

#if NTCTRL > 0
	/* register callback for external monitor status change */
	tadpole_register_callback(p9100_set_extvga, sc);
#endif
}
示例#6
0
文件: pwmclock.c 项目: ryo/netbsd-src
static void
pwmclock_attach(device_t parent, device_t self, void *aux)
{
	struct pwmclock_softc *sc = device_private(self);
	struct voyager_attach_args *vaa = aux;
	const struct sysctlnode *sysctl_node, *me, *freq;
	uint32_t reg, last, curr, diff, acc;
	int i, clk;

	sc->sc_dev = self;
	sc->sc_memt = vaa->vaa_tag;
	sc->sc_regh = vaa->vaa_regh;

	aprint_normal("\n");

	/* NULL here gets us the clockframe */
	voyager_establish_intr(parent, 22, pwmclock_intr, NULL);
	reg = voyager_set_pwm(100, 100); /* 100Hz, 10% duty cycle */
	reg |= SM502_PWM_ENABLE | SM502_PWM_ENABLE_INTR |
	       SM502_PWM_INTR_PENDING;
	sc->sc_reg = reg;
	pwmclock = sc;
	initclocks_ptr = pwmclock_start;

	/*
	 * Establish a hook so on shutdown we can set the CPU clock back to
	 * full speed. This is necessary because PMON doesn't change the 
	 * clock scale register on a warm boot, the MIPS clock code gets
	 * confused if we're too slow and the loongson-specific bits run
	 * too late in the boot process
	 */
	sc->sc_shutdown_cookie = shutdownhook_establish(pwmclock_shutdown, sc);

	/* ok, let's see how far the cycle counter gets between interrupts */
	DPRINTF("calibrating CPU timer...\n");
	for (clk = 1; clk < 8; clk++) {

		REGVAL(LS2F_CHIPCFG0) =
		    (REGVAL(LS2F_CHIPCFG0) & ~LS2FCFG_FREQSCALE_MASK) | clk;
		bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_PWM1,
		    sc->sc_reg);
		acc = 0;
		last = pwmclock_wait_edge(sc);
		for (i = 0; i < 16; i++) {
			curr = pwmclock_wait_edge(sc);
			diff = curr - last;
			acc += diff;
			last = curr;
		}
		sc->sc_scale[clk] = (acc >> 4) / 5000;
	}
#ifdef PWMCLOCK_DEBUG
	for (clk = 1; clk < 8; clk++) {
		aprint_normal_dev(sc->sc_dev, "%d/8: %d\n", clk + 1,
		    sc->sc_scale[clk]);
	}
#endif
	sc->sc_step = 7;
	sc->sc_step_wanted = 7;

	/* now setup sysctl */
	if (sysctl_createv(NULL, 0, NULL, 
	    &me, 
	    CTLFLAG_READWRITE, CTLTYPE_NODE, "loongson", NULL, NULL,
	    0, NULL, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL) != 0)
		aprint_error_dev(sc->sc_dev,
		    "couldn't create 'loongson' node\n");

	if (sysctl_createv(NULL, 0, NULL, 
	    &freq, 
	    CTLFLAG_READWRITE, CTLTYPE_NODE, "frequency", NULL, NULL, 0, NULL,
	    0, CTL_MACHDEP, me->sysctl_num, CTL_CREATE, CTL_EOL) != 0)
		aprint_error_dev(sc->sc_dev,
		    "couldn't create 'frequency' node\n");

	if (sysctl_createv(NULL, 0, NULL, 
	    &sysctl_node, 
	    CTLFLAG_READWRITE | CTLFLAG_OWNDESC,
	    CTLTYPE_INT, "target", "CPU speed", pwmclock_cpuspeed_temp, 
	    0, (void *)sc, 0, CTL_MACHDEP, me->sysctl_num, freq->sysctl_num, 
	    CTL_CREATE, CTL_EOL) == 0) {
	} else
		aprint_error_dev(sc->sc_dev,
		    "couldn't create 'target' node\n");

	if (sysctl_createv(NULL, 0, NULL, 
	    &sysctl_node, 
	    CTLFLAG_READWRITE,
	    CTLTYPE_INT, "current", NULL, pwmclock_cpuspeed_cur, 
	    1, (void *)sc, 0, CTL_MACHDEP, me->sysctl_num, freq->sysctl_num, 
	    CTL_CREATE, CTL_EOL) == 0) {
	} else
		aprint_error_dev(sc->sc_dev,
		    "couldn't create 'current' node\n");

	if (sysctl_createv(NULL, 0, NULL, 
	    &sysctl_node, 
	    CTLFLAG_READWRITE,
	    CTLTYPE_STRING, "available", NULL, pwmclock_cpuspeed_available, 
	    2, (void *)sc, 0, CTL_MACHDEP, me->sysctl_num, freq->sysctl_num, 
	    CTL_CREATE, CTL_EOL) == 0) {
	} else
		aprint_error_dev(sc->sc_dev,
		    "couldn't create 'available' node\n");
}
示例#7
0
static void
ecadc_attach(device_t parent, device_t self, void *aux)
{
	struct i2c_attach_args *ia = aux;
	struct ecadc_softc *sc = device_private(self);
	u_char term[256];
	u_char *cp, *desc;
	int64_t minv, warnv, crit, num, den;
	u_int8_t junk[PCF8591_CHANNELS + 1];
	envsys_data_t *sensor;
	int len, error, addr, chan, node = (int)ia->ia_cookie;
	u_int i;

	sc->sc_dev = self;
	if ((len = OF_getprop(node, "thermisters", term,
	    sizeof(term))) < 0) {
		aprint_error(": couldn't find \"thermisters\" property\n");
		return;
	}

	if (OF_getprop(node, "cpu-temp-factors", &sc->sc_cpu_xlate[2],
	    sizeof(sc->sc_cpu_xlate) - 2) < 0) {
		aprint_error(": couldn't find \"cpu-temp-factors\" property\n");
		return;
	}
	sc->sc_cpu_xlate[0] = sc->sc_cpu_xlate[1] = sc->sc_cpu_xlate[2];

	/* Only the Sun Enterprise 450 has these. */
	OF_getprop(node, "ps-temp-factors", &sc->sc_ps_xlate[2],
	    sizeof(sc->sc_ps_xlate) - 2);
	sc->sc_ps_xlate[0] = sc->sc_ps_xlate[1] = sc->sc_ps_xlate[2];

	cp = term;
	while (cp < term + len) {
		addr = cp[0] << 24 | cp[1] << 16 | cp[2] << 8 | cp[3]; cp += 4;
		chan = cp[0] << 24 | cp[1] << 16 | cp[2] << 8 | cp[3]; cp += 4;
		minv = cp[0] << 24 | cp[1] << 16 | cp[2] << 8 | cp[3]; cp += 4;
		warnv = cp[0] << 24 | cp[1] << 16 | cp[2] << 8 | cp[3]; cp += 4;
		crit = cp[0] << 24 | cp[1] << 16 | cp[2] << 8 | cp[3]; cp += 4;
		num = cp[0] << 24 | cp[1] << 16 | cp[2] << 8 | cp[3]; cp += 4;
		den = cp[0] << 24 | cp[1] << 16 | cp[2] << 8 | cp[3]; cp += 4;
		desc = cp;
		while (cp < term + len && *cp++);

		if (addr != (ia->ia_addr << 1))
			continue;

		if (num == 0 || den == 0)
			num = den = 1;

		sc->sc_channels[sc->sc_nchan].chan_num = chan;

		sensor = &sc->sc_channels[sc->sc_nchan].chan_sensor;
		sensor->units = ENVSYS_STEMP;
		sensor->flags |= ENVSYS_FMONLIMITS;
		sensor->state = ENVSYS_SINVALID;
		strlcpy(sensor->desc, desc, sizeof(sensor->desc));

		if (strncmp(desc, "CPU", 3) == 0)
			sc->sc_channels[sc->sc_nchan].chan_xlate =
			    sc->sc_cpu_xlate;
		else if (strncmp(desc, "PS", 2) == 0)
			sc->sc_channels[sc->sc_nchan].chan_xlate =
			    sc->sc_ps_xlate;
		else
			sc->sc_channels[sc->sc_nchan].chan_factor =
			    (1000000 * num) / den;
		sc->sc_channels[sc->sc_nchan].chan_min =
		    273150000 + 1000000 * minv;
		sc->sc_channels[sc->sc_nchan].chan_warn =
		    273150000 + 1000000 * warnv;
		sc->sc_channels[sc->sc_nchan].chan_crit =
		    273150000 + 1000000 * crit;
		sc->sc_nchan++;
	}

	sc->sc_tag = ia->ia_tag;
	sc->sc_addr = ia->ia_addr;

	iic_acquire_bus(sc->sc_tag, 0);

	/* Try a read now, so we can fail if it doesn't work */
	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr,
	    NULL, 0, junk, sc->sc_nchan + 1, 0)) {
		aprint_error(": read failed\n");
		iic_release_bus(sc->sc_tag, 0);
		return;
	}

	iic_release_bus(sc->sc_tag, 0);

	/* Hook us into the sysmon_envsys subsystem */
	sc->sc_sme = sysmon_envsys_create();
	sc->sc_sme->sme_name = device_xname(self);
	sc->sc_sme->sme_cookie = sc;
	sc->sc_sme->sme_refresh = ecadc_refresh;
	sc->sc_sme->sme_get_limits = ecadc_get_limits;

	/* Initialize sensor data. */
	for (i = 0; i < sc->sc_nchan; i++)
		sysmon_envsys_sensor_attach(sc->sc_sme,
		    &sc->sc_channels[i].chan_sensor);

	error = sysmon_envsys_register(sc->sc_sme);
	if (error) {
		aprint_error_dev(self, "error %d registering with sysmon\n",
			error);
		sysmon_envsys_destroy(sc->sc_sme);
		return;
	}

	aprint_naive(": Temp Sensors\n");
	aprint_normal(": %s Temp Sensors\n", ia->ia_name);
}
示例#8
0
static int
ld_virtio_alloc_reqs(struct ld_virtio_softc *sc, int qsize)
{
	int allocsize, r, rsegs, i;
	struct ld_softc *ld = &sc->sc_ld;
	void *vaddr;

	allocsize = sizeof(struct virtio_blk_req) * qsize;
	r = bus_dmamem_alloc(sc->sc_virtio->sc_dmat, allocsize, 0, 0,
			     &sc->sc_reqs_segs[0], 1, &rsegs, BUS_DMA_NOWAIT);
	if (r != 0) {
		aprint_error_dev(sc->sc_dev,
				 "DMA memory allocation failed, size %d, "
				 "error code %d\n", allocsize, r);
		goto err_none;
	}
	r = bus_dmamem_map(sc->sc_virtio->sc_dmat,
			   &sc->sc_reqs_segs[0], 1, allocsize,
			   &vaddr, BUS_DMA_NOWAIT);
	if (r != 0) {
		aprint_error_dev(sc->sc_dev,
				 "DMA memory map failed, "
				 "error code %d\n", r);
		goto err_dmamem_alloc;
	}
	sc->sc_reqs = vaddr;
	memset(vaddr, 0, allocsize);
	for (i = 0; i < qsize; i++) {
		struct virtio_blk_req *vr = &sc->sc_reqs[i];
		r = bus_dmamap_create(sc->sc_virtio->sc_dmat,
				      offsetof(struct virtio_blk_req, vr_bp),
				      1,
				      offsetof(struct virtio_blk_req, vr_bp),
				      0,
				      BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW,
				      &vr->vr_cmdsts);
		if (r != 0) {
			aprint_error_dev(sc->sc_dev,
					 "command dmamap creation failed, "
					 "error code %d\n", r);
			goto err_reqs;
		}
		r = bus_dmamap_load(sc->sc_virtio->sc_dmat, vr->vr_cmdsts,
				    &vr->vr_hdr,
				    offsetof(struct virtio_blk_req, vr_bp),
				    NULL, BUS_DMA_NOWAIT);
		if (r != 0) {
			aprint_error_dev(sc->sc_dev,
					 "command dmamap load failed, "
					 "error code %d\n", r);
			goto err_reqs;
		}
		r = bus_dmamap_create(sc->sc_virtio->sc_dmat,
				      ld->sc_maxxfer,
				      ld->sc_maxxfer / NBPG, ld->sc_maxxfer,
				      0,
				      BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW,
				      &vr->vr_payload);
		if (r != 0) {
			aprint_error_dev(sc->sc_dev,
					 "payload dmamap creation failed, "
					 "error code %d\n", r);
			goto err_reqs;
		}
	}
	return 0;

err_reqs:
	for (i = 0; i < qsize; i++) {
		struct virtio_blk_req *vr = &sc->sc_reqs[i];
		if (vr->vr_cmdsts) {
			bus_dmamap_destroy(sc->sc_virtio->sc_dmat,
					   vr->vr_cmdsts);
			vr->vr_cmdsts = 0;
		}
		if (vr->vr_payload) {
			bus_dmamap_destroy(sc->sc_virtio->sc_dmat,
					   vr->vr_payload);
			vr->vr_payload = 0;
		}
	}
	bus_dmamem_unmap(sc->sc_virtio->sc_dmat, sc->sc_reqs, allocsize);
err_dmamem_alloc:
	bus_dmamem_free(sc->sc_virtio->sc_dmat, &sc->sc_reqs_segs[0], 1);
err_none:
	return -1;
}
示例#9
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);
}
示例#10
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);
}
示例#11
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);
}
/*
 * 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);
}
示例#13
0
文件: pq3ehci.c 项目: ryo/netbsd-src
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;
}
示例#14
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");
}
示例#15
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;
}
int
mpt_dma_mem_alloc(mpt_softc_t *mpt)
{
	bus_dma_segment_t reply_seg, request_seg;
	int reply_rseg, request_rseg;
	bus_addr_t pptr, end;
	char *vptr;
	size_t len;
	int error, i;

	/* Check if we have already allocated the reply memory. */
	if (mpt->reply != NULL)
		return (0);

	/*
	 * Allocate the request pool.  This isn't really DMA'd memory,
	 * but it's a convenient place to do it.
	 */
	len = sizeof(request_t) * MPT_MAX_REQUESTS(mpt);
	mpt->request_pool = malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
	if (mpt->request_pool == NULL) {
		aprint_error_dev(mpt->sc_dev, "unable to allocate request pool\n");
		return (ENOMEM);
	}

	/*
	 * Allocate DMA resources for reply buffers.
	 */
	error = bus_dmamem_alloc(mpt->sc_dmat, PAGE_SIZE, PAGE_SIZE, 0,
	    &reply_seg, 1, &reply_rseg, 0);
	if (error) {
		aprint_error_dev(mpt->sc_dev, "unable to allocate reply area, error = %d\n",
		    error);
		goto fail_0;
	}

	error = bus_dmamem_map(mpt->sc_dmat, &reply_seg, reply_rseg, PAGE_SIZE,
	    (void **) &mpt->reply, BUS_DMA_COHERENT/*XXX*/);
	if (error) {
		aprint_error_dev(mpt->sc_dev, "unable to map reply area, error = %d\n",
		    error);
		goto fail_1;
	}

	error = bus_dmamap_create(mpt->sc_dmat, PAGE_SIZE, 1, PAGE_SIZE,
	    0, 0, &mpt->reply_dmap);
	if (error) {
		aprint_error_dev(mpt->sc_dev, "unable to create reply DMA map, error = %d\n",
		    error);
		goto fail_2;
	}

	error = bus_dmamap_load(mpt->sc_dmat, mpt->reply_dmap, mpt->reply,
	    PAGE_SIZE, NULL, 0);
	if (error) {
		aprint_error_dev(mpt->sc_dev, "unable to load reply DMA map, error = %d\n",
		    error);
		goto fail_3;
	}
	mpt->reply_phys = mpt->reply_dmap->dm_segs[0].ds_addr;

	/*
	 * Allocate DMA resources for request buffers.
	 */
	error = bus_dmamem_alloc(mpt->sc_dmat, MPT_REQ_MEM_SIZE(mpt),
	    PAGE_SIZE, 0, &request_seg, 1, &request_rseg, 0);
	if (error) {
		aprint_error_dev(mpt->sc_dev, "unable to allocate request area, "
		    "error = %d\n", error);
		goto fail_4;
	}

	error = bus_dmamem_map(mpt->sc_dmat, &request_seg, request_rseg,
	    MPT_REQ_MEM_SIZE(mpt), (void **) &mpt->request, 0);
	if (error) {
		aprint_error_dev(mpt->sc_dev, "unable to map request area, error = %d\n",
		    error);
		goto fail_5;
	}

	error = bus_dmamap_create(mpt->sc_dmat, MPT_REQ_MEM_SIZE(mpt), 1,
	    MPT_REQ_MEM_SIZE(mpt), 0, 0, &mpt->request_dmap);
	if (error) {
		aprint_error_dev(mpt->sc_dev, "unable to create request DMA map, "
		    "error = %d\n", error);
		goto fail_6;
	}

	error = bus_dmamap_load(mpt->sc_dmat, mpt->request_dmap, mpt->request,
	    MPT_REQ_MEM_SIZE(mpt), NULL, 0);
	if (error) {
		aprint_error_dev(mpt->sc_dev, "unable to load request DMA map, error = %d\n",
		    error);
		goto fail_7;
	}
	mpt->request_phys = mpt->request_dmap->dm_segs[0].ds_addr;

	pptr = mpt->request_phys;
	vptr = (void *) mpt->request;
	end = pptr + MPT_REQ_MEM_SIZE(mpt);

	for (i = 0; pptr < end; i++) {
		request_t *req = &mpt->request_pool[i];
		req->index = i;

		/* Store location of Request Data */
		req->req_pbuf = pptr;
		req->req_vbuf = vptr;

		pptr += MPT_REQUEST_AREA;
		vptr += MPT_REQUEST_AREA;

		req->sense_pbuf = (pptr - MPT_SENSE_SIZE);
		req->sense_vbuf = (vptr - MPT_SENSE_SIZE);

		error = bus_dmamap_create(mpt->sc_dmat, MAXPHYS,
		    MPT_SGL_MAX, MAXPHYS, 0, 0, &req->dmap);
		if (error) {
			aprint_error_dev(mpt->sc_dev, "unable to create req %d DMA map, "
			    "error = %d\n", i, error);
			goto fail_8;
		}
	}

	return (0);

 fail_8:
	for (--i; i >= 0; i--) {
		request_t *req = &mpt->request_pool[i];
		if (req->dmap != NULL)
			bus_dmamap_destroy(mpt->sc_dmat, req->dmap);
	}
	bus_dmamap_unload(mpt->sc_dmat, mpt->request_dmap);
 fail_7:
	bus_dmamap_destroy(mpt->sc_dmat, mpt->request_dmap);
 fail_6:
	bus_dmamem_unmap(mpt->sc_dmat, (void *)mpt->request, PAGE_SIZE);
 fail_5:
	bus_dmamem_free(mpt->sc_dmat, &request_seg, request_rseg);
 fail_4:
	bus_dmamap_unload(mpt->sc_dmat, mpt->reply_dmap);
 fail_3:
	bus_dmamap_destroy(mpt->sc_dmat, mpt->reply_dmap);
 fail_2:
	bus_dmamem_unmap(mpt->sc_dmat, (void *)mpt->reply, PAGE_SIZE);
 fail_1:
	bus_dmamem_free(mpt->sc_dmat, &reply_seg, reply_rseg);
 fail_0:
	free(mpt->request_pool, M_DEVBUF);

	mpt->reply = NULL;
	mpt->request = NULL;
	mpt->request_pool = NULL;

	return (error);
}
示例#17
0
static void
awin_gige_attach(device_t parent, device_t self, void *aux)
{
	struct awin_gige_softc * const sc = device_private(self);
	struct awinio_attach_args * const aio = aux;
	const struct awin_locators * const loc = &aio->aio_loc;
	struct awin_gpio_pinset pinset;
	prop_dictionary_t cfg = device_properties(self);
	uint32_t clkreg;
	const char *phy_type, *pin_name;
	bus_space_handle_t bsh;

	switch (awin_chip_id()) {
	case AWIN_CHIP_ID_A80:
		bsh = aio->aio_a80_core2_bsh;
		pinset = awin_gige_gpio_pinset_a80;
		break;
	case AWIN_CHIP_ID_A31:
		bsh = aio->aio_core_bsh;
		pinset = awin_gige_gpio_pinset_a31;
		break;
	default:
		bsh = aio->aio_core_bsh;
		pinset = awin_gige_gpio_pinset;
		break;
	}

	sc->sc_core.sc_dev = self;

	prop_dictionary_get_uint8(cfg, "pinset-func", &pinset.pinset_func);
	awin_gpio_pinset_acquire(&pinset);

	sc->sc_core.sc_bst = aio->aio_core_bst;
	sc->sc_core.sc_dmat = aio->aio_dmat;
	bus_space_subregion(sc->sc_core.sc_bst, bsh,
	    loc->loc_offset, loc->loc_size, &sc->sc_core.sc_bsh);

	aprint_naive("\n");
	aprint_normal(": Gigabit Ethernet Controller\n");

	awin_gige_pmu_init(self);

	/*
	 * Interrupt handler
	 */
	sc->sc_ih = intr_establish(loc->loc_intr, IPL_NET, IST_LEVEL,
	    awin_gige_intr, sc);
	if (sc->sc_ih == NULL) {
		aprint_error_dev(self, "failed to establish interrupt %d\n",
		     loc->loc_intr);
		return;
	}
	aprint_normal_dev(self, "interrupting on irq %d\n",
	     loc->loc_intr);

	if (prop_dictionary_get_cstring_nocopy(cfg, "phy-power", &pin_name)) {
		if (awin_gpio_pin_reserve(pin_name, &sc->sc_power_pin)) {
			awin_gpio_pindata_write(&sc->sc_power_pin, 1);
		} else {
			aprint_error_dev(self,
			    "failed to reserve GPIO \"%s\"\n", pin_name);
		}
	}

	/*
	 * Enable GMAC clock
	 */
	if (awin_chip_id() == AWIN_CHIP_ID_A80) {
		awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
		    AWIN_A80_CCU_SCLK_BUS_CLK_GATING1_REG,
		    AWIN_A80_CCU_SCLK_BUS_CLK_GATING1_GMAC, 0);
	} else if (awin_chip_id() == AWIN_CHIP_ID_A31) {
		awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
		    AWIN_AHB_GATING0_REG, AWIN_A31_AHB_GATING0_GMAC, 0);
	} else if (awin_chip_id() == AWIN_CHIP_ID_A20) {
		awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
		    AWIN_AHB_GATING1_REG, AWIN_AHB_GATING1_GMAC, 0);
	}

	/*
	 * Soft reset
	 */
	if (awin_chip_id() == AWIN_CHIP_ID_A80) {
		awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
		    AWIN_A80_CCU_SCLK_BUS_SOFT_RST1_REG,
		    AWIN_A80_CCU_SCLK_BUS_SOFT_RST1_GMAC, 0);
	} else if (awin_chip_id() == AWIN_CHIP_ID_A31) {
		awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
		    AWIN_A31_AHB_RESET0_REG,
		    AWIN_A31_AHB_RESET0_GMAC_RST, 0);
	}

	/*
	 * PHY clock setup
	 */
	if (!prop_dictionary_get_cstring_nocopy(cfg, "phy-type", &phy_type))
		phy_type = "rgmii";
	if (strcmp(phy_type, "rgmii") == 0) {
		clkreg = AWIN_GMAC_CLK_PIT | AWIN_GMAC_CLK_TCS_INT_RGMII;
	} else if (strcmp(phy_type, "rgmii-bpi") == 0) {
		clkreg = AWIN_GMAC_CLK_PIT | AWIN_GMAC_CLK_TCS_INT_RGMII;
		/*
		 * These magic bits seem to be necessary for RGMII at gigabit
		 * speeds on Banana Pi.
		 */
		clkreg |= __BITS(11,10);
	} else if (strcmp(phy_type, "gmii") == 0) {
		clkreg = AWIN_GMAC_CLK_TCS_INT_RGMII;
	} else if (strcmp(phy_type, "mii") == 0) {
		clkreg = AWIN_GMAC_CLK_TCS_MII;
	} else {
		panic("unknown phy type '%s'", phy_type);
	}
	if (awin_chip_id() == AWIN_CHIP_ID_A80) {
		awin_reg_set_clear(aio->aio_core_bst, aio->aio_a80_core2_bsh,
		    AWIN_A80_SYS_CTRL_OFFSET + AWIN_A80_SYS_CTRL_EMAC_CLK_REG,
		    clkreg, AWIN_GMAC_CLK_PIT|AWIN_GMAC_CLK_TCS);
	} else if (awin_chip_id() == AWIN_CHIP_ID_A31) {
		awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
		    AWIN_A31_GMAC_CLK_REG, clkreg,
		    AWIN_GMAC_CLK_PIT|AWIN_GMAC_CLK_TCS);
	} else {
		awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
		    AWIN_GMAC_CLK_REG, clkreg,
		    AWIN_GMAC_CLK_PIT|AWIN_GMAC_CLK_TCS);
	}

	dwc_gmac_attach(&sc->sc_core, GMAC_MII_CLK_150_250M_DIV102);
}
示例#18
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;
}
示例#19
0
/*
 * ym_acpi_attach: autoconf(9) attach routine
 */
static void
ym_acpi_attach(struct device *parent, struct device *self, void *aux)
{
	struct ym_softc *sc = (struct ym_softc *)self;
	struct acpi_attach_args *aa = aux;
	struct acpi_resources res;
	struct acpi_io *sb_io, *codec_io, *opl_io, *control_io;
#if NMPU_YM > 0
	struct acpi_io *mpu_io;
#endif
	struct acpi_irq *irq;
	struct acpi_drq *playdrq, *recdrq;
	struct ad1848_softc *ac = &sc->sc_ad1848.sc_ad1848;
	ACPI_STATUS rv;

	aprint_naive("\n");
	aprint_normal("\n");

	/* Parse our resources */
	rv = acpi_resource_parse(&sc->sc_ad1848.sc_ad1848.sc_dev,
	    aa->aa_node->ad_handle, "_CRS", &res,
	    &acpi_resource_parse_ops_default);
	if (ACPI_FAILURE(rv))
		return;

	/*
	 * sc_sb_ioh	 @ 0
	 * sc_ioh	 @ 1
	 * sc_opl_ioh	 @ 2
	 * sc_mpu_ioh	 @ 3
	 * sc_controlioh @ 4
	 */

	/* Find and map our i/o registers */
	sc->sc_iot = aa->aa_iot;
	sb_io	 = acpi_res_io(&res, 0);
	codec_io = acpi_res_io(&res, 1);
	opl_io	 = acpi_res_io(&res, 2);
#if NMPU_YM > 0
	mpu_io	 = acpi_res_io(&res, 3);
#endif
	control_io = acpi_res_io(&res, 4);

	if (sb_io == NULL || codec_io == NULL || opl_io == NULL ||
#if NMPU_YM > 0
	    mpu_io == NULL ||
#endif
	    control_io == NULL) {
		aprint_error_dev(self, "unable to find i/o registers resource\n");
		goto out;
	}
	if (bus_space_map(sc->sc_iot, sb_io->ar_base, sb_io->ar_length,
	    0, &sc->sc_sb_ioh) != 0) {
		aprint_error_dev(self, "unable to map i/o registers (sb)\n");
		goto out;
	}
	if (bus_space_map(sc->sc_iot, codec_io->ar_base, codec_io->ar_length,
	    0, &sc->sc_ioh) != 0) {
		aprint_error_dev(self, "unable to map i/o registers (codec)\n");
		goto out;
	}
	if (bus_space_map(sc->sc_iot, opl_io->ar_base, opl_io->ar_length,
	    0, &sc->sc_opl_ioh) != 0) {
		aprint_error_dev(self, "unable to map i/o registers (opl)\n");
		goto out;
	}
#if NMPU_YM > 0
	if (bus_space_map(sc->sc_iot, mpu_io->ar_base, mpu_io->ar_length,
	    0, &sc->sc_mpu_ioh) != 0) {
		aprint_error_dev(self, "unable to map i/o registers (mpu)\n");
		goto out;
	}
#endif
	if (bus_space_map(sc->sc_iot, control_io->ar_base,
	    control_io->ar_length, 0, &sc->sc_controlioh) != 0) {
		aprint_error_dev(self, "unable to map i/o registers (control)\n");
		goto out;
	}

	sc->sc_ic = aa->aa_ic;

	/* Find our IRQ */
	irq = acpi_res_irq(&res, 0);
	if (irq == NULL) {
		aprint_error_dev(self, "unable to find irq resource\n");
		/* XXX bus_space_unmap */
		goto out;
	}
	sc->ym_irq = irq->ar_irq;

	/* Find our playback and record DRQs */
	playdrq = acpi_res_drq(&res, 0);
	recdrq = acpi_res_drq(&res, 1);
	if (playdrq == NULL) {
		aprint_error_dev(self, "unable to find drq resources\n");
		/* XXX bus_space_unmap */
		goto out;
	}
	if (recdrq == NULL) {
		/* half-duplex mode */
		sc->ym_recdrq = sc->ym_playdrq = playdrq->ar_drq;
	} else {
		sc->ym_playdrq = playdrq->ar_drq;
		sc->ym_recdrq = recdrq->ar_drq;
	}

	ac->sc_iot = sc->sc_iot;
	if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, WSS_CODEC,
	    AD1848_NPORT, &ac->sc_ioh)) {
		aprint_error_dev(self, "bus_space_subregion failed\n");
		/* XXX cleanup */
		goto out;
	}

	aprint_normal_dev(self, "");

	ac->mode = 2;
	ac->MCE_bit = MODE_CHANGE_ENABLE;

	sc->sc_ad1848.sc_ic = sc->sc_ic;

	/* Attach our ym device */
	ym_attach(sc);

 out:
	acpi_resource_cleanup(&res);
}
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;
}
/*
 * ralink_ohci_attach
 */
static void
ralink_ohci_attach(device_t parent, device_t self, void *aux)
{
	struct ralink_ohci_softc * const sc = device_private(self);
	const struct mainbus_attach_args * const ma = aux;
	usbd_status status;
	int error;
#ifdef RALINK_OHCI_DEBUG
	const char * const devname = device_xname(self);
#endif

	aprint_naive(": OHCI USB controller\n");
	aprint_normal(": OHCI USB controller\n");

	sc->sc_ohci.sc_dev = self;
	sc->sc_ohci.sc_bus.hci_private = sc;
	sc->sc_ohci.iot = ma->ma_memt;
	sc->sc_ohci.sc_bus.dmatag = ma->ma_dmat;

	/* Map I/O registers */
	if ((error = bus_space_map(sc->sc_ohci.iot, RA_USB_OHCI_BASE,
	    RA_USB_BLOCK_SIZE, 0, &sc->sc_ohci.ioh)) != 0) {
		aprint_error_dev(self, "can't map OHCI registers, "
			"error=%d\n", error);
		return;
	}
	
	sc->sc_ohci.sc_size = RA_USB_BLOCK_SIZE;

#ifdef RALINK_OHCI_DEBUG
	printf("%s sc: %p ma: %p\n", devname, sc, ma);
	printf("%s memt: %p dmat: %p\n", devname, ma->ma_memt, ma->ma_dmat);

	printf("%s: OHCI HcRevision=0x%x\n", devname,
		OREAD4(&sc->sc_ohci, OHCI_REVISION));
	printf("%s: OHCI HcControl=0x%x\n", devname,
		OREAD4(&sc->sc_ohci, OHCI_CONTROL));
	printf("%s: OHCI HcCommandStatus=0x%x\n", devname,
		OREAD4(&sc->sc_ohci, OHCI_COMMAND_STATUS));
	printf("%s: OHCI HcInterruptStatus=0x%x\n", devname,
		OREAD4(&sc->sc_ohci, OHCI_INTERRUPT_STATUS));
#endif

	/* Disable OHCI interrupts. */
	OWRITE4(&sc->sc_ohci, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS);

	/* establish the MIPS level interrupt */
	sc->sc_ih = ra_intr_establish(RA_IRQ_USB, ohci_intr, sc, 0);
	if (sc->sc_ih == NULL) {
		aprint_error_dev(self, "unable to establish irq %d\n",
			RA_IRQ_USB);
		goto fail_0;
	}

	/* Set vendor for root hub descriptor. */
	sc->sc_ohci.sc_id_vendor = 0x1814;
	strlcpy(sc->sc_ohci.sc_vendor, "Ralink", sizeof(sc->sc_ohci.sc_vendor));

	/* Initialize OHCI */
	status = ohci_init(&sc->sc_ohci);
	if (status != USBD_NORMAL_COMPLETION) {
		aprint_error_dev(self, "init failed, error=%d\n", status);
		goto fail_0;
	}

#if NEHCI > 0
	ralink_usb_hc_add(&sc->sc_hc, self);
#endif

	if (!pmf_device_register1(self, ohci_suspend, ohci_resume,
	    ohci_shutdown))
		aprint_error_dev(self, "couldn't establish power handler\n");

	/* Attach usb device. */
	sc->sc_ohci.sc_child = config_found(self, &sc->sc_ohci.sc_bus,
		usbctlprint);

	return;

 fail_0:
	bus_space_unmap(sc->sc_ohci.iot, sc->sc_ohci.ioh, sc->sc_ohci.sc_size);
	sc->sc_ohci.sc_size = 0;
}
static int
piixpm_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr,
    const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags)
{
	struct piixpm_softc *sc = cookie;
	const u_int8_t *b;
	u_int8_t ctl = 0, st;
	int retries;

	DPRINTF(("%s: exec: op %d, addr 0x%x, cmdlen %d, len %d, flags 0x%x\n",
	    device_xname(sc->sc_dev), op, addr, cmdlen, len, flags));

	/* Wait for bus to be idle */
	for (retries = 100; retries > 0; retries--) {
		st = bus_space_read_1(sc->sc_smb_iot, sc->sc_smb_ioh,
		    PIIX_SMB_HS);
		if (!(st & PIIX_SMB_HS_BUSY))
			break;
		DELAY(PIIXPM_DELAY);
	}
	DPRINTF(("%s: exec: st 0x%d\n", device_xname(sc->sc_dev), st & 0xff));
	if (st & PIIX_SMB_HS_BUSY)
		return (1);

	if (cold || sc->sc_poll)
		flags |= I2C_F_POLL;

	if (!I2C_OP_STOP_P(op) || cmdlen > 1 || len > 2)
		return (1);

	/* Setup transfer */
	sc->sc_i2c_xfer.op = op;
	sc->sc_i2c_xfer.buf = buf;
	sc->sc_i2c_xfer.len = len;
	sc->sc_i2c_xfer.flags = flags;
	sc->sc_i2c_xfer.error = 0;

	/* Set slave address and transfer direction */
	bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, PIIX_SMB_TXSLVA,
	    PIIX_SMB_TXSLVA_ADDR(addr) |
	    (I2C_OP_READ_P(op) ? PIIX_SMB_TXSLVA_READ : 0));

	b = cmdbuf;
	if (cmdlen > 0)
		/* Set command byte */
		bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh,
		    PIIX_SMB_HCMD, b[0]);

	if (I2C_OP_WRITE_P(op)) {
		/* Write data */
		b = buf;
		if (len > 0)
			bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh,
			    PIIX_SMB_HD0, b[0]);
		if (len > 1)
			bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh,
			    PIIX_SMB_HD1, b[1]);
	}

	/* Set SMBus command */
	if (len == 0)
		ctl = PIIX_SMB_HC_CMD_BYTE;
	else if (len == 1)
		ctl = PIIX_SMB_HC_CMD_BDATA;
	else if (len == 2)
		ctl = PIIX_SMB_HC_CMD_WDATA;

	if ((flags & I2C_F_POLL) == 0)
		ctl |= PIIX_SMB_HC_INTREN;

	/* Start transaction */
	ctl |= PIIX_SMB_HC_START;
	bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, PIIX_SMB_HC, ctl);

	if (flags & I2C_F_POLL) {
		/* Poll for completion */
		DELAY(PIIXPM_DELAY);
		for (retries = 1000; retries > 0; retries--) {
			st = bus_space_read_1(sc->sc_smb_iot, sc->sc_smb_ioh,
			    PIIX_SMB_HS);
			if ((st & PIIX_SMB_HS_BUSY) == 0)
				break;
			DELAY(PIIXPM_DELAY);
		}
		if (st & PIIX_SMB_HS_BUSY)
			goto timeout;
		piixpm_intr(sc);
	} else {
		/* Wait for interrupt */
		if (tsleep(sc, PRIBIO, "iicexec", PIIXPM_TIMEOUT * hz))
			goto timeout;
	}

	if (sc->sc_i2c_xfer.error)
		return (1);

	return (0);

timeout:
	/*
	 * Transfer timeout. Kill the transaction and clear status bits.
	 */
	aprint_error_dev(sc->sc_dev, "timeout, status 0x%x\n", st);
	bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, PIIX_SMB_HC,
	    PIIX_SMB_HC_KILL);
	DELAY(PIIXPM_DELAY);
	st = bus_space_read_1(sc->sc_smb_iot, sc->sc_smb_ioh, PIIX_SMB_HS);
	if ((st & PIIX_SMB_HS_FAILED) == 0)
		aprint_error_dev(sc->sc_dev, "transaction abort failed, status 0x%x\n", st);
	bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, PIIX_SMB_HS, st);
	return (1);
}
示例#23
0
static void
mppb_attach(device_t parent, device_t self, void *aux)
{
	struct mppb_softc *sc;
	struct pcibus_attach_args pba;  
	struct zbus_args *zap;
	pci_chipset_tag_t pc;
#ifdef PCI_NETBSD_CONFIGURE
	struct extent *ioext, *memext;
#endif /* PCI_NETBSD_CONFIGURE */

	zap = aux;
	sc = device_private(self);
	pc = &sc->apc;
	sc->sc_dev = self;
	sc->ba = zap->va;

	aprint_normal(": Matay Prometheus PCI bridge\n"); 

	/* Setup bus space mappings. */
	sc->pci_conf_area.base = (bus_addr_t) sc->ba + MPPB_CONF_BASE;
	sc->pci_conf_area.absm = &amiga_bus_stride_1swap;

	sc->pci_mem_area.base = (bus_addr_t) sc->ba + MPPB_MEM_BASE;
	sc->pci_mem_area.absm = &amiga_bus_stride_1;

	sc->pci_io_area.base = (bus_addr_t) sc->ba + MPPB_IO_BASE;
	sc->pci_io_area.absm = &amiga_bus_stride_1;
	
#ifdef MPPB_DEBUG 
	aprint_normal("mppb mapped conf %x->%x, mem %x->%x\n, io %x->%x\n",
	    kvtop((void*) sc->pci_conf_area.base), sc->pci_conf_area.base,
	    kvtop((void*) sc->pci_mem_area.base), sc->pci_mem_area.base,
	    kvtop((void*) sc->pci_io_area.base), sc->pci_io_area.base); 
#endif 

	sc->apc.pci_conf_datat = &(sc->pci_conf_area);

	if (bus_space_map(sc->apc.pci_conf_datat, 0, MPPB_CONF_SIZE, 0, 
	    &sc->apc.pci_conf_datah)) 
		aprint_error_dev(self,
		    "couldn't map PCI configuration data space\n");
	
	/* Initialize the PCI chipset tag. */
	sc->apc.pc_conf_v = (void*) pc;
	sc->apc.pc_bus_maxdevs = mppb_pci_bus_maxdevs;
	sc->apc.pc_make_tag = amiga_pci_make_tag;
	sc->apc.pc_decompose_tag = amiga_pci_decompose_tag;
	sc->apc.pc_conf_read = mppb_pci_conf_read;
	sc->apc.pc_conf_write = mppb_pci_conf_write;
	sc->apc.pc_attach_hook = mppb_pci_attach_hook;

	sc->apc.pc_intr_map = mppb_pci_intr_map;
	sc->apc.pc_intr_string = amiga_pci_intr_string;
	sc->apc.pc_intr_establish = amiga_pci_intr_establish;
	sc->apc.pc_intr_disestablish = amiga_pci_intr_disestablish;

	sc->apc.pc_conf_hook = amiga_pci_conf_hook;
	sc->apc.pc_conf_interrupt = amiga_pci_conf_interrupt;

#ifdef PCI_NETBSD_CONFIGURE
	ioext = extent_create("mppbio",  MPPB_IO_BASE, 
	    MPPB_IO_BASE + MPPB_IO_SIZE, NULL, 0, EX_NOWAIT);
	memext = extent_create("mppbmem",  MPPB_MEM_BASE, 
	    MPPB_MEM_BASE + MPPB_MEM_SIZE, NULL, 0, EX_NOWAIT);

#ifdef MPPB_DEBUG	
	aprint_normal("mppb: reconfiguring the bus!\n");
#endif /* MPPB_DEBUG */
	pci_configure_bus(pc, ioext, memext, NULL, 0, CACHELINE_SIZE);

	extent_destroy(ioext);
	extent_destroy(memext);
#endif /* PCI_NETBSD_CONFIGURE */

	pba.pba_iot = &(sc->pci_io_area);
	pba.pba_memt = &(sc->pci_mem_area);
	pba.pba_dmat = NULL; 
	pba.pba_dmat64 = NULL;
	pba.pba_pc = pc;
	pba.pba_flags = PCI_FLAGS_MEM_OKAY | PCI_FLAGS_IO_OKAY;
	pba.pba_bus = 0;
	pba.pba_bridgetag = NULL;

	config_found_ia(self, "pcibus", &pba, pcibusprint);
}
示例#24
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");
}
示例#25
0
int
an_attach(struct an_softc *sc)
{
	struct ieee80211com *ic = &sc->sc_ic;
	struct ifnet *ifp = &sc->sc_if;
	int i, s;
	struct an_rid_wepkey *akey;
	int buflen, kid, rid;
	int chan, chan_min, chan_max;

	s = splnet();

	an_wait(sc);
	if (an_reset(sc) != 0) {
		config_deactivate(sc->sc_dev);
		splx(s);
		return 1;
	}

	/* Load factory config */
	if (an_cmd(sc, AN_CMD_READCFG, 0) != 0) {
		splx(s);
		aprint_error_dev(sc->sc_dev, "failed to load config data\n");
		return 1;
	}

	/* Read the current configuration */
	buflen = sizeof(sc->sc_config);
	if (an_read_rid(sc, AN_RID_GENCONFIG, &sc->sc_config, &buflen) != 0) {
		splx(s);
		aprint_error_dev(sc->sc_dev, "read config failed\n");
		return 1;
	}

	/* Read the card capabilities */
	buflen = sizeof(sc->sc_caps);
	if (an_read_rid(sc, AN_RID_CAPABILITIES, &sc->sc_caps, &buflen) != 0) {
		splx(s);
		aprint_error_dev(sc->sc_dev, "read caps failed\n");
		return 1;
	}

#ifdef AN_DEBUG
	if (an_debug) {
		static const int dumprid[] = {
		    AN_RID_GENCONFIG, AN_RID_CAPABILITIES, AN_RID_SSIDLIST,
		    AN_RID_APLIST, AN_RID_STATUS, AN_RID_ENCAP
		};

		for (rid = 0; rid < sizeof(dumprid)/sizeof(dumprid[0]); rid++) {
			buflen = sizeof(sc->sc_buf);
			if (an_read_rid(sc, dumprid[rid], &sc->sc_buf, &buflen)
			    != 0)
				continue;
			printf("%04x (%d):\n", dumprid[rid], buflen);
			for (i = 0; i < (buflen + 1) / 2; i++)
				printf(" %04x", sc->sc_buf.sc_val[i]);
			printf("\n");
		}
	}
#endif

	/* Read WEP settings from persistent memory */
	akey = &sc->sc_buf.sc_wepkey;
	buflen = sizeof(struct an_rid_wepkey);
	rid = AN_RID_WEP_VOLATILE;	/* first persistent key */
	while (an_read_rid(sc, rid, akey, &buflen) == 0) {
		kid = le16toh(akey->an_key_index);
		DPRINTF(("an_attach: wep rid=0x%x len=%d(%zu) index=0x%04x "
		    "mac[0]=%02x keylen=%d\n",
		    rid, buflen, sizeof(*akey), kid,
		    akey->an_mac_addr[0], le16toh(akey->an_key_len)));
		if (kid == 0xffff) {
			sc->sc_tx_perskey = akey->an_mac_addr[0];
			sc->sc_tx_key = -1;
			break;
		}
		if (kid >= IEEE80211_WEP_NKID)
			break;
		sc->sc_perskeylen[kid] = le16toh(akey->an_key_len);
		sc->sc_wepkeys[kid].an_wep_keylen = -1;
		rid = AN_RID_WEP_PERSISTENT;	/* for next key */
		buflen = sizeof(struct an_rid_wepkey);
	}

	aprint_normal_dev(sc->sc_dev, "%s %s (firmware %s)\n",
	    sc->sc_caps.an_manufname, sc->sc_caps.an_prodname,
	    sc->sc_caps.an_prodvers);

	memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);

	ifp->if_softc = sc;
	ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS | IFF_SIMPLEX |
	    IFF_MULTICAST | IFF_ALLMULTI;
	ifp->if_ioctl = an_ioctl;
	ifp->if_start = an_start;
	ifp->if_init = an_init;
	ifp->if_stop = an_stop;
	ifp->if_watchdog = an_watchdog;
	IFQ_SET_READY(&ifp->if_snd);

	ic->ic_ifp = ifp;
	ic->ic_phytype = IEEE80211_T_DS;
	ic->ic_opmode = IEEE80211_M_STA;
	ic->ic_caps = IEEE80211_C_WEP | IEEE80211_C_PMGT | IEEE80211_C_IBSS |
	    IEEE80211_C_MONITOR;
	ic->ic_state = IEEE80211_S_INIT;
	IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->sc_caps.an_oemaddr);

	switch (le16toh(sc->sc_caps.an_regdomain)) {
	default:
	case AN_REGDOMAIN_USA:
	case AN_REGDOMAIN_CANADA:
		chan_min = 1; chan_max = 11; break;
	case AN_REGDOMAIN_EUROPE:
	case AN_REGDOMAIN_AUSTRALIA:
		chan_min = 1; chan_max = 13; break;
	case AN_REGDOMAIN_JAPAN:
		chan_min = 14; chan_max = 14; break;
	case AN_REGDOMAIN_SPAIN:
		chan_min = 10; chan_max = 11; break;
	case AN_REGDOMAIN_FRANCE:
		chan_min = 10; chan_max = 13; break;
	case AN_REGDOMAIN_JAPANWIDE:
		chan_min = 1; chan_max = 14; break;
	}

	for (chan = chan_min; chan <= chan_max; chan++) {
		ic->ic_channels[chan].ic_freq =
		    ieee80211_ieee2mhz(chan, IEEE80211_CHAN_2GHZ);
		ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_B;
	}
	ic->ic_ibss_chan = &ic->ic_channels[chan_min];

	aprint_normal("%s: 802.11 address: %s, channel: %d-%d\n",
	    ifp->if_xname, ether_sprintf(ic->ic_myaddr), chan_min, chan_max);

	/* Find supported rate */
	for (i = 0; i < sizeof(sc->sc_caps.an_rates); i++) {
		if (sc->sc_caps.an_rates[i] == 0)
			continue;
		ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates[
		    ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates++] =
		    sc->sc_caps.an_rates[i];
	}

	/*
	 * Call MI attach routine.
	 */
	if_attach(ifp);
	ieee80211_ifattach(ic);

	sc->sc_newstate = ic->ic_newstate;
	ic->ic_newstate = an_newstate;

	ieee80211_media_init(ic, an_media_change, an_media_status);

	/*
	 * radiotap BPF device
	 */
	bpf_attach2(ifp, DLT_IEEE802_11_RADIO,
	    sizeof(struct ieee80211_frame) + 64, &sc->sc_drvbpf);

	memset(&sc->sc_rxtapu, 0, sizeof(sc->sc_rxtapu));
	sc->sc_rxtap.ar_ihdr.it_len = htole16(sizeof(sc->sc_rxtapu));
	sc->sc_rxtap.ar_ihdr.it_present = htole32(AN_RX_RADIOTAP_PRESENT);

	memset(&sc->sc_txtapu, 0, sizeof(sc->sc_txtapu));
	sc->sc_txtap.at_ihdr.it_len = htole16(sizeof(sc->sc_txtapu));
	sc->sc_txtap.at_ihdr.it_present = htole32(AN_TX_RADIOTAP_PRESENT);

	sc->sc_attached = 1;
	splx(s);

	ieee80211_announce(ic);
	return 0;
}
示例#26
0
/*
 * Look for an Intel MP spec table, indicating SMP capable hardware.
 */
int
mpbios_probe(device_t self)
{
	paddr_t  	ebda, memtop;

	paddr_t		cthpa;
	int		cthlen;
	const uint8_t	*mpbios_page;
	int 		scan_loc;

	struct		mp_map t;

	/* If MP is disabled, don't use MPBIOS or the ioapics. */
	if ((boothowto & RB_MD1) != 0)
		return 0;

	/* see if EBDA exists */

	mpbios_page = mpbios_map (0, PAGE_SIZE, &t);

	ebda =   *(const uint16_t *) (&mpbios_page[0x40e]);
	ebda <<= 4;

	memtop = *(const uint16_t *) (&mpbios_page[0x413]);
	memtop <<= 10;

	mpbios_page = NULL;
	mpbios_unmap(&t);

	scan_loc = 0;

	if (ebda && ebda < IOM_BEGIN ) {
		mp_fps = mpbios_search(self, ebda, 1024, &mp_fp_map);
		if (mp_fps != NULL)
			goto found;
	}

	scan_loc = 1;

	if (memtop && memtop <= IOM_BEGIN ) {
		mp_fps = mpbios_search(self, memtop - 1024, 1024, &mp_fp_map);
		if (mp_fps != NULL)
			goto found;
	}

	scan_loc = 2;

	mp_fps = mpbios_search(self, BIOS_BASE, BIOS_COUNT, &mp_fp_map);
	if (mp_fps != NULL)
		goto found;

	/* nothing found */
	return 0;

 found:
	if (mp_verbose)
		aprint_verbose_dev(self, "MP floating pointer found in %s at 0x%jx\n",
		    loc_where[scan_loc], (uintmax_t)mp_fp_map.pa);

	if (mp_fps->pap == 0) {
		if (mp_fps->mpfb1 == 0) {
			aprint_error_dev(self, "MP fps invalid: "
			    "no default config and no configuration table\n");

			goto err;
		}
		return 10;
	}

	cthpa = mp_fps->pap;

	mp_cth = mpbios_map (cthpa, sizeof (*mp_cth), &mp_cfg_table_map);
	cthlen = mp_cth->base_len;
	mpbios_unmap(&mp_cfg_table_map);

	mp_cth = mpbios_map (cthpa, cthlen, &mp_cfg_table_map);

	if (mp_verbose)
		aprint_verbose_dev(self, "MP config table at 0x%jx, %d bytes long\n",
		    (uintmax_t)cthpa, cthlen);

	if (mp_cth->signature != MP_CT_SIG) {
		aprint_error_dev(self, "MP signature mismatch (%x vs %x)\n",
		    MP_CT_SIG, mp_cth->signature);
		goto err;
	}

	if (mpbios_cksum(mp_cth, cthlen)) {
		aprint_error_dev(self, "MP Configuration Table checksum mismatch\n");
		goto err;
	}
	return 10;
 err:
	if (mp_fps) {
		mp_fps = NULL;
		mpbios_unmap(&mp_fp_map);
	}
	if (mp_cth) {
		mp_cth = NULL;
		mpbios_unmap(&mp_cfg_table_map);
	}
	return 0;
}
void
ym_pnpbios_attach(device_t parent, device_t self,
    void *aux)
{
	struct ym_softc *sc = device_private(self);
	struct ad1848_softc *ac = &sc->sc_ad1848.sc_ad1848;
	struct pnpbiosdev_attach_args *aa = aux;

	ac->sc_dev = self;

	if (pnpbios_io_map(aa->pbt, aa->resc, 0,
				&sc->sc_iot, &sc->sc_sb_ioh) != 0) {
		printf(": can't map sb i/o space\n");
		return;
	}
	if (pnpbios_io_map(aa->pbt, aa->resc, 1,
				&sc->sc_iot, &sc->sc_ioh) != 0) {
		printf(": can't map sb i/o space\n");
		return;
	}
	if (pnpbios_io_map(aa->pbt, aa->resc, 2,
				&sc->sc_iot, &sc->sc_opl_ioh) != 0) {
		printf(": can't map opl i/o space\n");
		return;
	}
#if NMPU_YM > 0
	if (pnpbios_io_map(aa->pbt, aa->resc, 3,
				&sc->sc_iot, &sc->sc_mpu_ioh) != 0) {
		printf(": can't map mpu i/o space\n");
		return;
	}
#endif
	if (pnpbios_io_map(aa->pbt, aa->resc, 4,
				&sc->sc_iot, &sc->sc_controlioh) != 0) {
		printf(": can't map control i/o space\n");
		return;
	}

	sc->sc_ic = aa->ic;

	if (pnpbios_getirqnum(aa->pbt, aa->resc, 0, &sc->ym_irq, NULL)) {
		printf(": can't get IRQ\n");
		return;
	}

	if (pnpbios_getdmachan(aa->pbt, aa->resc, 0, &sc->ym_playdrq)) {
		printf(": can't get DMA channel\n");
		return;
	}
	if (pnpbios_getdmachan(aa->pbt, aa->resc, 1, &sc->ym_recdrq))
		sc->ym_recdrq = sc->ym_playdrq;	/* half-duplex mode */

	printf("\n");
	pnpbios_print_devres(self, aa);

	printf("%s", device_xname(self));

	ac->sc_iot = sc->sc_iot;
	if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, WSS_CODEC, AD1848_NPORT,
	    &ac->sc_ioh)) {
		aprint_error_dev(self, "bus_space_subregion failed\n");
		return;
	}
	ac->mode = 2;
	ac->MCE_bit = MODE_CHANGE_ENABLE;

	sc->sc_ad1848.sc_ic  = sc->sc_ic;

	ym_attach(sc);
}
示例#28
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;
}
示例#29
0
文件: zs.c 项目: ryo/netbsd-src
/*
 * Attach a found zs.
 *
 * Match slave number to zs unit number, so that misconfiguration will
 * not set up the keyboard as ttya, etc.
 */
static void
zs_hpc_attach(device_t parent, device_t self, void *aux)
{
	struct zsc_softc *zsc = device_private(self);
	struct hpc_attach_args *haa = aux;
	struct zsc_attach_args zsc_args;
	struct zs_chanstate *cs;
	struct zs_channel *ch;
	int    zs_unit, channel, err, s;
	const char  *promconsdev;

	promconsdev = arcbios_GetEnvironmentVariable("ConsoleOut");

	zsc->zsc_dev = self;
	zsc->zsc_bustag = haa->ha_st;
	if ((err = bus_space_subregion(haa->ha_st, haa->ha_sh,
				       haa->ha_devoff, 0x10,
				       &zsc->zsc_base)) != 0) {
		aprint_error(": unable to map 85c30 registers, error = %d\n",
		    err);
		return;
	}

	zs_unit = device_unit(self);
	aprint_normal("\n");

	/*
	 * Initialize software state for each channel.
	 *
	 * Done in reverse order of channels since the first serial port
	 * is actually attached to the *second* channel, and vice versa.
	 * Doing it this way should force a 'zstty*' to attach zstty0 to
	 * channel 1 and zstty1 to channel 0.  They couldn't have wired
	 * it up in a more sensible fashion, could they?
	 */
	for (channel = 1; channel >= 0; channel--) {
		zsc_args.channel = channel;
		ch = &zsc->zsc_cs_store[channel];
		cs = zsc->zsc_cs[channel] = (struct zs_chanstate *)ch;

		zs_lock_init(cs);
		cs->cs_reg_csr = NULL;
		cs->cs_reg_data = NULL;
		cs->cs_channel = channel;
		cs->cs_private = NULL;
		cs->cs_ops = &zsops_null;
		cs->cs_brg_clk = PCLK / 16;

		if (bus_space_subregion(zsc->zsc_bustag, zsc->zsc_base,
					zs_chan_offset[channel],
					sizeof(struct zschan),
					&ch->cs_regs) != 0) {
			aprint_error_dev(self, "cannot map regs\n");
			return;
		}
		ch->cs_bustag = zsc->zsc_bustag;

		memcpy(cs->cs_creg, zs_init_reg, 16);
		memcpy(cs->cs_preg, zs_init_reg, 16);

		zsc_args.hwflags = 0;
		zsc_args.consdev = NULL;

		if (zs_consunit == -1 && zs_conschan == -1) {
		    /*
		     * If this channel is being used by the PROM console,
		     * pass the generic zs driver a 'no reset' flag so the
		     * channel gets left in the appropriate state after
		     * attach.
		     *
		     * Note: the channel mappings are swapped.
		     */
		    if (promconsdev != NULL &&
			strlen(promconsdev) == 9 &&
			strncmp(promconsdev, "serial", 6) == 0 &&
			(promconsdev[7] == '0' || promconsdev[7] == '1')) {
			if (promconsdev[7] == '1' && channel == 0)
			    zsc_args.hwflags |= ZS_HWFLAG_NORESET;
			else if (promconsdev[7] == '0' && channel == 1)
			    zsc_args.hwflags |= ZS_HWFLAG_NORESET;
		    }
		}

		/* If console, don't stomp speed, let zstty know */
		if (zs_unit == zs_consunit && channel == zs_conschan) {
			zsc_args.consdev = &zs_cn;
			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);
		}
	}


	zsc->sc_si = softint_establish(SOFTINT_SERIAL, zssoft, zsc);
	cpu_intr_establish(haa->ha_irq, IPL_TTY, zshard, NULL);

	evcnt_attach_dynamic(&zsc->zsc_intrcnt, EVCNT_TYPE_INTR, NULL,
			     device_xname(self), "intr");

	/*
	 * 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);
}
示例#30
0
static int
clmpcc_init(struct clmpcc_softc *sc)
{
	u_int tcor = 0, tbpr = 0;
	u_int rcor = 0, rbpr = 0;
	u_int msvr_rts, msvr_dtr;
	u_int ccr;
	int is_console;
	int i;

	/*
	 * All we're really concerned about here is putting the chip
	 * into a quiescent state so that it won't do anything until
	 * clmpccopen() is called. (Except the console channel.)
	 */

	/*
	 * If the chip is acting as console, set all channels to the supplied
	 * console baud rate. Otherwise, plump for 9600.
	 */
	if ( cons_sc &&
	     sc->sc_ioh == cons_sc->sc_ioh && sc->sc_iot == cons_sc->sc_iot ) {
		clmpcc_speed(sc, cons_rate, &tcor, &tbpr);
		clmpcc_speed(sc, cons_rate, &rcor, &rbpr);
		is_console = 1;
	} else {
		clmpcc_speed(sc, 9600, &tcor, &tbpr);
		clmpcc_speed(sc, 9600, &rcor, &rbpr);
		is_console = 0;
	}

	/* Allow any pending output to be sent */
	delay(10000);

	/* Send the Reset All command  to channel 0 (resets all channels!) */
	clmpcc_channel_cmd(sc, 0, CLMPCC_CCR_T0_RESET_ALL);

	delay(1000);

	/*
	 * The chip will set it's firmware revision register to a non-zero
	 * value to indicate completion of reset.
	 */
	for (i = 10000; clmpcc_rdreg(sc, CLMPCC_REG_GFRCR) == 0 && i; i--)
		delay(1);

	if ( i == 0 ) {
		/*
		 * Watch out... If this chip is console, the message
		 * probably won't be sent since we just reset it!
		 */
		aprint_error_dev(sc->sc_dev, "Failed to reset chip\n");
		return -1;
	}

	for (i = 0; i < CLMPCC_NUM_CHANS; i++) {
		clmpcc_select_channel(sc, i);

		/* All interrupts are disabled to begin with */
		clmpcc_wrreg(sc, CLMPCC_REG_IER, 0);

		/* Make sure the channel interrupts on the correct vectors */
		clmpcc_wrreg(sc, CLMPCC_REG_LIVR, sc->sc_vector_base);
		clmpcc_wr_pilr(sc, CLMPCC_REG_RPILR, sc->sc_rpilr);
		clmpcc_wr_pilr(sc, CLMPCC_REG_TPILR, sc->sc_tpilr);
		clmpcc_wr_pilr(sc, CLMPCC_REG_MPILR, sc->sc_mpilr);

		/* Receive timer prescaler set to 1ms */
		clmpcc_wrreg(sc, CLMPCC_REG_TPR,
				 CLMPCC_MSEC_TO_TPR(sc->sc_clk, 1));

		/* We support Async mode only */
		clmpcc_wrreg(sc, CLMPCC_REG_CMR, CLMPCC_CMR_ASYNC);

		/* Set the required baud rate */
		clmpcc_wrreg(sc, CLMPCC_REG_TCOR, CLMPCC_TCOR_CLK(tcor));
		clmpcc_wrreg(sc, CLMPCC_REG_TBPR, tbpr);
		clmpcc_wrreg(sc, CLMPCC_REG_RCOR, CLMPCC_RCOR_CLK(rcor));
		clmpcc_wrreg(sc, CLMPCC_REG_RBPR, rbpr);

		/* Always default to 8N1 (XXX what about console?) */
		clmpcc_wrreg(sc, CLMPCC_REG_COR1, CLMPCC_COR1_CHAR_8BITS |
						  CLMPCC_COR1_NO_PARITY |
						  CLMPCC_COR1_IGNORE_PAR);

		clmpcc_wrreg(sc, CLMPCC_REG_COR2, 0);

		clmpcc_wrreg(sc, CLMPCC_REG_COR3, CLMPCC_COR3_STOP_1);

		clmpcc_wrreg(sc, CLMPCC_REG_COR4, CLMPCC_COR4_DSRzd |
						  CLMPCC_COR4_CDzd |
						  CLMPCC_COR4_CTSzd);

		clmpcc_wrreg(sc, CLMPCC_REG_COR5, CLMPCC_COR5_DSRod |
						  CLMPCC_COR5_CDod |
						  CLMPCC_COR5_CTSod |
						  CLMPCC_COR5_FLOW_NORM);

		clmpcc_wrreg(sc, CLMPCC_REG_COR6, 0);
		clmpcc_wrreg(sc, CLMPCC_REG_COR7, 0);

		/* Set the receive FIFO timeout */
		clmpcc_wrreg(sc, CLMPCC_REG_RTPRl, CLMPCC_RTPR_DEFAULT);
		clmpcc_wrreg(sc, CLMPCC_REG_RTPRh, 0);

		/* At this point, we set up the console differently */
		if ( is_console && i == cons_chan ) {
			msvr_rts = CLMPCC_MSVR_RTS;
			msvr_dtr = CLMPCC_MSVR_DTR;
			ccr = CLMPCC_CCR_T0_RX_EN | CLMPCC_CCR_T0_TX_EN;
		} else {
			msvr_rts = 0;
			msvr_dtr = 0;
			ccr = CLMPCC_CCR_T0_RX_DIS | CLMPCC_CCR_T0_TX_DIS;
		}

		clmpcc_wrreg(sc, CLMPCC_REG_MSVR_RTS, msvr_rts);
		clmpcc_wrreg(sc, CLMPCC_REG_MSVR_DTR, msvr_dtr);
		clmpcc_channel_cmd(sc, i, CLMPCC_CCR_T0_INIT | ccr);
		delay(100);
	}

	return 0;
}