Пример #1
0
/*
 * Attach the interface. Allocate softc structures, do
 * setup and ethernet/BPF attach.
 */
void
kue_attach(struct device *parent, struct device *self, void *aux)
{
	struct kue_softc	*sc = (struct kue_softc *)self;
	struct usb_attach_arg	*uaa = aux;
	usbd_device_handle	dev = uaa->device;
	usbd_status		err;

	DPRINTFN(5,(" : kue_attach: sc=%p, dev=%p", sc, dev));

	err = usbd_set_config_no(dev, KUE_CONFIG_NO, 1);
	if (err) {
		printf("%s: setting config no failed\n",
		    sc->kue_dev.dv_xname);
		return;
	}

	sc->kue_udev = dev;
	sc->kue_product = uaa->product;
	sc->kue_vendor = uaa->vendor;

	if (rootvp == NULL)
		mountroothook_establish(kue_attachhook, sc);
	else
		kue_attachhook(sc);
}
Пример #2
0
void
pgt_pci_attach(struct device *parent, struct device *self, void *aux)
{
	struct pgt_pci_softc *psc = (struct pgt_pci_softc *)self;
	struct pgt_softc *sc = &psc->sc_pgt;
	struct pci_attach_args *pa = aux;
	const char *intrstr = NULL;
	pci_intr_handle_t ih;
	int error;

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

	/* remember chipset */
	if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTERSIL_ISL3877)
		sc->sc_flags |= SC_ISL3877;

	/* map control / status registers */
	error = pci_mapreg_map(pa, PGT_PCI_BAR0,
	    PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
	    &sc->sc_iotag, &sc->sc_iohandle, NULL, &psc->sc_mapsize, 0);
	if (error != 0) {
		printf(": can't map mem space\n");
		return;
	}

	/* map interrupt */
	if (pci_intr_map(pa, &ih) != 0) {
		printf(": can't map interrupt\n");
		return;
	}

	/* disable all interrupts */
	bus_space_write_4(sc->sc_iotag, sc->sc_iohandle, PGT_REG_INT_EN, 0);
	(void)bus_space_read_4(sc->sc_iotag, sc->sc_iohandle, PGT_REG_INT_EN);
	DELAY(PGT_WRITEIO_DELAY);

	/* establish interrupt */
	intrstr = pci_intr_string(psc->sc_pc, ih);
	psc->sc_ih = pci_intr_establish(psc->sc_pc, ih, IPL_NET, pgt_intr, sc,
	    sc->sc_dev.dv_xname);
	if (psc->sc_ih == NULL) {
		printf(": can't establish interrupt");
		if (intrstr != NULL)
			printf(" at %s", intrstr);
		printf("\n");
		return;
	}
	printf(": %s\n", intrstr);

	if (rootvp == NULL)
		mountroothook_establish(pgt_attach, sc);
	else
		pgt_attach(sc);
}
Пример #3
0
void
pgt_cardbus_attach(struct device *parent, struct device *self, void *aux)
{
	struct pgt_cardbus_softc *csc = (struct pgt_cardbus_softc *)self;
	struct pgt_softc *sc = &csc->sc_pgt;
	struct cardbus_attach_args *ca = aux;
	cardbus_devfunc_t ct = ca->ca_ct;
	bus_addr_t base;
	int error;

	sc->sc_dmat = ca->ca_dmat;
	csc->sc_ct = ct;
	csc->sc_tag = ca->ca_tag;
	csc->sc_intrline = ca->ca_intrline;
	csc->sc_pc = ca->ca_pc;

	/* power management hooks */
	sc->sc_enable = pgt_cardbus_enable;
	sc->sc_disable = pgt_cardbus_disable;
	sc->sc_power = pgt_cardbus_power;

	/* remember chipset */
	if (PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_INTERSIL_ISL3877)
		sc->sc_flags |= SC_ISL3877;

	/* map control / status registers */
	error = Cardbus_mapreg_map(ct, CARDBUS_BASE0_REG,
	    PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
	    &sc->sc_iotag, &sc->sc_iohandle, &base, &csc->sc_mapsize);
	if (error != 0) {
		printf(": can't map mem space\n");
		return;
	}
	csc->sc_bar0_val = base | PCI_MAPREG_TYPE_MEM;

	/* disable all interrupts */
	bus_space_write_4(sc->sc_iotag, sc->sc_iohandle, PGT_REG_INT_EN, 0);
	(void)bus_space_read_4(sc->sc_iotag, sc->sc_iohandle, PGT_REG_INT_EN);
	DELAY(PGT_WRITEIO_DELAY);

	/* set up the PCI configuration registers */
	pgt_cardbus_setup(csc);

	printf(": irq %d\n", csc->sc_intrline);

	if (rootvp == NULL)
		mountroothook_establish(pgt_attach, sc);
	else
		pgt_attach(sc);
}
Пример #4
0
/*
 * Controller is working, and drive responded.  Attach it.
 */
void
fdattach(device_t parent, device_t self, void *aux)
{
	struct fdc_softc *fdc = device_private(parent);
	struct fd_softc *fd = device_private(self);
	struct fdc_attach_args *fa = aux;
	const struct fd_type *type = fa->fa_deftype;
	int drive = fa->fa_drive;

	fd->sc_dev = self;

	callout_init(&fd->sc_motoron_ch, 0);
	callout_init(&fd->sc_motoroff_ch, 0);

	/* XXX Allow `flags' to override device type? */

	if (type)
		aprint_normal(": %s, %d cyl, %d head, %d sec\n", type->name,
		    type->cyls, type->heads, type->sectrac);
	else
		aprint_normal(": density unknown\n");

	bufq_alloc(&fd->sc_q, "disksort", BUFQ_SORT_CYLINDER);
	fd->sc_cylin = -1;
	fd->sc_drive = drive;
	fd->sc_deftype = type;
	fdc->sc_fd[drive] = fd;

	/*
	 * Initialize and attach the disk structure.
	 */
	disk_init(&fd->sc_dk, device_xname(fd->sc_dev), &fddkdriver);
	disk_attach(&fd->sc_dk);

	/*
	 * Establish a mountroot hook.
	 */
	fd->sc_roothook =
	    mountroothook_establish(fd_mountroot_hook, fd->sc_dev);

#if NRND > 0
	rnd_attach_source(&fd->rnd_source, device_xname(fd->sc_dev),
			  RND_TYPE_DISK, 0);
#endif

	fd_set_properties(fd);

	if (!pmf_device_register(self, NULL, NULL))
		aprint_error_dev(self, "cannot set power mgmt handler\n");
}
Пример #5
0
void
uticom_attach(struct device *parent, struct device *self, void *aux)
{
	struct uticom_softc	*sc = (struct uticom_softc *)self;
	struct usb_attach_arg	*uaa = aux;
	struct usbd_device	*dev = uaa->device;

	sc->sc_udev = dev;
	sc->sc_iface = uaa->iface;

	if (rootvp == NULL)
		mountroothook_establish(uticom_attach_hook, sc);
	else
		uticom_attach_hook(sc);
}
Пример #6
0
void
uyap_attach(struct device *parent, struct device *self, void *aux)
{
	struct uyap_softc *sc = (struct uyap_softc *)self;
	struct usb_attach_arg *uaa = aux;
	usbd_device_handle dev = uaa->device;

	printf("%s: downloading firmware\n", sc->sc_dev.dv_xname);

	sc->sc_udev = dev;
	if (rootvp == NULL)
		mountroothook_establish(uyap_attachhook, sc);
	else
		uyap_attachhook(sc);
}
Пример #7
0
void
lcd_attach(struct device *parent, struct device *self, void *aux)
{
	struct lcd_softc *sc = (struct lcd_softc *)self;
	struct confargs *ca = aux;
	struct pdc_chassis_lcd *pdc_lcd = (void *)ca->ca_pdc_iodc_read;
	int i;

	sc->sc_iot = ca->ca_iot;
	if (bus_space_map(sc->sc_iot, pdc_lcd->cmd_addr,
		1, 0, &sc->sc_cmdh)) {
		printf(": cannot map cmd register\n");
		return;
	}
		
	if (bus_space_map(sc->sc_iot, pdc_lcd->data_addr,
		1, 0, &sc->sc_datah)) {
		printf(": cannot map data register\n");
		bus_space_unmap(sc->sc_iot, sc->sc_cmdh, 1);
		return;
	}

	printf(": model %d\n", pdc_lcd->model);

	sc->sc_delay = pdc_lcd->delay;
	for (i = 0; i < 3; i++)
		sc->sc_heartbeat[i] = pdc_lcd->heartbeat[i];

	timeout_set(&sc->sc_to, lcd_blink_finish, sc);

	sc->sc_blink.bl_func = lcd_blink;
	sc->sc_blink.bl_arg = sc;
	blink_led_register(&sc->sc_blink);

	mountroothook_establish(lcd_mountroot, sc);
}
Пример #8
0
void
yds_attach(struct device *parent, struct device *self, void *aux)
{
	struct yds_softc *sc = (struct yds_softc *)self;
	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
	pci_chipset_tag_t pc = pa->pa_pc;
	char const *intrstr;
	pci_intr_handle_t ih;
	bus_size_t size;
	pcireg_t reg;
	int i;

	/* Map register to memory */
	if (pci_mapreg_map(pa, YDS_PCI_MBA, PCI_MAPREG_TYPE_MEM, 0,
	    &sc->memt, &sc->memh, NULL, &size, 0)) {
		printf(": can't map mem space\n");
		return;
	}

	/* Map and establish the interrupt. */
	if (pci_intr_map(pa, &ih)) {
		printf(": couldn't map interrupt\n");
		bus_space_unmap(sc->memt, sc->memh, size);
		return;
	}
	intrstr = pci_intr_string(pc, ih);
	sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO | IPL_MPSAFE,
	    yds_intr, sc, self->dv_xname);
	if (sc->sc_ih == NULL) {
		printf(": couldn't establish interrupt");
		if (intrstr != NULL)
			printf(" at %s", intrstr);
		printf("\n");
		bus_space_unmap(sc->memt, sc->memh, size);
		return;
	}
	printf(": %s\n", intrstr);

	sc->sc_dmatag = pa->pa_dmat;
	sc->sc_pc = pc;
	sc->sc_pcitag = pa->pa_tag;
	sc->sc_id = pa->pa_id;
	sc->sc_revision = PCI_REVISION(pa->pa_class);
	sc->sc_flags = yds_get_dstype(sc->sc_id);
	if (sc->sc_dev.dv_cfdata->cf_flags & YDS_CAP_LEGACY_SMOD_DISABLE)
		sc->sc_flags |= YDS_CAP_LEGACY_SMOD_DISABLE;
#ifdef AUDIO_DEBUG
	if (ydsdebug)
		printf("%s: chip has %b\n", sc->sc_dev.dv_xname,
			YDS_CAP_BITS, sc->sc_flags);
#endif

	/* Disable legacy mode */
	reg = pci_conf_read(pc, pa->pa_tag, YDS_PCI_LEGACY);
	pci_conf_write(pc, pa->pa_tag, YDS_PCI_LEGACY,
		       reg & YDS_PCI_LEGACY_LAD);

	/* Mute all volumes */
	for (i = 0x80; i < 0xc0; i += 2)
		YWRITE2(sc, i, 0);

	sc->sc_legacy_iot = pa->pa_iot;
	mountroothook_establish(yds_attachhook, sc);
}
Пример #9
0
/**
 * radeon_driver_load_kms - Main load function for KMS.
 *
 * @dev: drm dev pointer
 * @flags: device flags
 *
 * This is the main load function for KMS (all asics).
 * It calls radeon_device_init() to set up the non-display
 * parts of the chip (asic init, CP, writeback, etc.), and
 * radeon_modeset_init() to set up the display parts
 * (crtcs, encoders, hotplug detect, etc.).
 * Returns 0 on success, error on failure.
 */
void
radeondrm_attach_kms(struct device *parent, struct device *self, void *aux)
{
	struct radeon_device	*rdev = (struct radeon_device *)self;
	struct drm_device	*dev;
	struct pci_attach_args	*pa = aux;
	const struct drm_pcidev *id_entry;
	int			 is_agp;
	pcireg_t		 type;
	uint8_t			 iobar;

#if defined(__sparc64__) || defined(__macppc__)
	extern int fbnode;
#endif

	id_entry = drm_find_description(PCI_VENDOR(pa->pa_id),
	    PCI_PRODUCT(pa->pa_id), radeondrm_pciidlist);
	rdev->flags = id_entry->driver_data;
	rdev->pc = pa->pa_pc;
	rdev->pa_tag = pa->pa_tag;
	rdev->iot = pa->pa_iot;
	rdev->memt = pa->pa_memt;
	rdev->dmat = pa->pa_dmat;

#if defined(__sparc64__) || defined(__macppc__)
	if (fbnode == PCITAG_NODE(rdev->pa_tag))
		rdev->console = 1;
#else
	if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY &&
	    PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_DISPLAY_VGA &&
	    (pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG)
	    & (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE))
	    == (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE)) {
		rdev->console = 1;
#if NVGA > 0
		vga_console_attached = 1;
#endif
	}
#endif

#define RADEON_PCI_MEM		0x10
#define RADEON_PCI_IO		0x14
#define RADEON_PCI_MMIO		0x18
#define RADEON_PCI_IO2		0x20

	type = pci_mapreg_type(pa->pa_pc, pa->pa_tag, RADEON_PCI_MEM);
	if (PCI_MAPREG_TYPE(type) != PCI_MAPREG_TYPE_MEM ||
	    pci_mapreg_info(pa->pa_pc, pa->pa_tag, RADEON_PCI_MEM,
	    type, &rdev->fb_aper_offset, &rdev->fb_aper_size, NULL)) {
		printf(": can't get frambuffer info\n");
		return;
	}

	if (PCI_MAPREG_MEM_TYPE(type) != PCI_MAPREG_MEM_TYPE_64BIT)
		iobar = RADEON_PCI_IO;
	else
		iobar = RADEON_PCI_IO2;
	
	if (pci_mapreg_map(pa, iobar, PCI_MAPREG_TYPE_IO, 0,
	    NULL, &rdev->rio_mem, NULL, &rdev->rio_mem_size, 0)) {
		printf(": can't map IO space\n");
		return;
	}

	type = pci_mapreg_type(pa->pa_pc, pa->pa_tag, RADEON_PCI_MMIO);
	if (PCI_MAPREG_TYPE(type) != PCI_MAPREG_TYPE_MEM ||
	    pci_mapreg_map(pa, RADEON_PCI_MMIO, type, 0, NULL,
	    &rdev->rmmio, &rdev->rmmio_base, &rdev->rmmio_size, 0)) {
		printf(": can't map mmio space\n");
		return;
	}

	if (pci_intr_map(pa, &rdev->intrh) != 0) {
		printf(": couldn't map interrupt\n");
		return;
	}
	printf(": %s\n", pci_intr_string(pa->pa_pc, rdev->intrh));
#ifdef notyet
	mtx_init(&rdev->swi_lock, IPL_TTY);
#endif

	/* update BUS flag */
	if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP, NULL, NULL)) {
		rdev->flags |= RADEON_IS_AGP;
	} else if (pci_get_capability(pa->pa_pc, pa->pa_tag,
	    PCI_CAP_PCIEXPRESS, NULL, NULL)) {
		rdev->flags |= RADEON_IS_PCIE;
	} else {
		rdev->flags |= RADEON_IS_PCI;
	}

	DRM_DEBUG("%s card detected\n",
		 ((rdev->flags & RADEON_IS_AGP) ? "AGP" :
		 (((rdev->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI"))));

	is_agp = pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP,
	    NULL, NULL);

	dev = (struct drm_device *)drm_attach_pci(&kms_driver, pa, is_agp, self);
	rdev->ddev = dev;

	rdev->irqh = pci_intr_establish(pa->pa_pc, rdev->intrh, IPL_TTY,
	    radeon_driver_irq_handler_kms, rdev->ddev, rdev->dev.dv_xname);
	if (rdev->irqh == NULL) {
		printf("%s: couldn't establish interrupt\n",
		    rdev->dev.dv_xname);
		return;
	}

#ifdef __sparc64__
{
	struct rasops_info *ri;
	int node, console;

	node = PCITAG_NODE(pa->pa_tag);
	console = (fbnode == node);

	fb_setsize(&rdev->sf, 8, 1152, 900, node, 0);

	/*
	 * The firmware sets up the framebuffer such that at starts at
	 * an offset from the start of video memory.
	 */
	rdev->fb_offset =
	    bus_space_read_4(rdev->memt, rdev->rmmio, RADEON_CRTC_OFFSET);
	if (bus_space_map(rdev->memt, rdev->fb_aper_offset + rdev->fb_offset,
	    rdev->sf.sf_fbsize, BUS_SPACE_MAP_LINEAR, &rdev->memh)) {
		printf("%s: can't map video memory\n", rdev->dev.dv_xname);
		return;
	}

	ri = &rdev->sf.sf_ro;
	ri->ri_bits = bus_space_vaddr(rdev->memt, rdev->memh);
	ri->ri_hw = rdev;
	ri->ri_updatecursor = NULL;

	fbwscons_init(&rdev->sf, RI_VCONS | RI_WRONLY | RI_BSWAP, console);
	if (console)
		fbwscons_console_init(&rdev->sf, -1);
}
#endif

	rdev->shutdown = true;
	if (rootvp == NULL)
		mountroothook_establish(radeondrm_attachhook, rdev);
	else
		radeondrm_attachhook(rdev);
}
Пример #10
0
void
cs4280_attach(struct device *parent, struct device *self, void *aux)
{
	struct cs4280_softc *sc = (struct cs4280_softc *) self;
	struct pci_attach_args *pa = (struct pci_attach_args *) aux;
	pci_chipset_tag_t pc = pa->pa_pc;
	char const *intrstr;
	pci_intr_handle_t ih;
	u_int32_t mem;
    
	/* Map I/O register */
	if (pci_mapreg_map(pa, CSCC_PCI_BA0, 
	    PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
	    &sc->ba0t, &sc->ba0h, NULL, NULL, 0)) {
		printf(": can't map BA0 space\n");
		return;
	}
	if (pci_mapreg_map(pa, CSCC_PCI_BA1,
	    PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
	    &sc->ba1t, &sc->ba1h, NULL, NULL, 0)) {
		printf(": can't map BA1 space\n");
		return;
	}

	sc->sc_dmatag = pa->pa_dmat;

	/* Get out of power save mode if needed. */
	pci_set_powerstate(pc, pa->pa_tag, PCI_PMCSR_STATE_D0);

	/* LATENCY_TIMER setting */
	mem = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG);
	if ( PCI_LATTIMER(mem) < 32 ) {
		mem &= 0xffff00ff;
		mem |= 0x00002000;
		pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, mem);
	}
	
	/* Map and establish the interrupt. */
	if (pci_intr_map(pa, &ih)) {
		printf(": couldn't map interrupt\n");
		return;
	}
	intrstr = pci_intr_string(pc, ih);

	sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO | IPL_MPSAFE,
	    cs4280_intr, sc, sc->sc_dev.dv_xname);
	if (sc->sc_ih == NULL) {
		printf(": couldn't establish interrupt");
		if (intrstr != NULL)
			printf(" at %s", intrstr);
		printf("\n");
		return;
	}
	printf(": %s\n", intrstr);

	/* Initialization */
	if (cs4280_init(sc, 1) != 0)
		return;

	mountroothook_establish(cs4280_attachhook, sc);

	/* AC 97 attachement */
	sc->host_if.arg = sc;
	sc->host_if.attach = cs4280_attach_codec;
	sc->host_if.read   = cs4280_read_codec;
	sc->host_if.write  = cs4280_write_codec;
	sc->host_if.reset  = cs4280_reset_codec;

	if (ac97_attach(&sc->host_if) != 0) {
		printf("%s: ac97_attach failed\n", sc->sc_dev.dv_xname);
		return;
	}
}
Пример #11
0
void
ueagle_attach(struct device *parent, struct device *self, void *aux)
{
	struct ueagle_softc *sc = (struct ueagle_softc *)self;
	struct usb_attach_arg *uaa = aux;
	struct ifnet *ifp = &sc->sc_if;
	uint8_t addr[ETHER_ADDR_LEN];

	sc->sc_udev = uaa->device;

	/*
	 * Pre-firmware modems must be flashed and reset first.  They will
	 * automatically detach themselves from the bus and reattach later
	 * with a new product Id.
	 */
	sc->fw = ueagle_lookup(uaa->vendor, uaa->product)->fw;
	if (sc->fw != NULL) {
		if (rootvp == NULL)
			mountroothook_establish(ueagle_attachhook, sc);
		else
			ueagle_attachhook(sc);

		/* processing of pre-firmware modems ends here */
		return;
	}

	if (usbd_set_config_no(sc->sc_udev, UEAGLE_CONFIG_NO, 0) != 0) {
		printf("%s: could not set configuration no\n",
		    sc->sc_dev.dv_xname);
		return;
	}

	if (ueagle_getesi(sc, addr) != 0) {
		printf("%s: could not read end system identifier\n",
		    sc->sc_dev.dv_xname);
		return;
	}

	printf("%s: address: %02x:%02x:%02x:%02x:%02x:%02x\n",
	    sc->sc_dev.dv_xname, addr[0], addr[1], addr[2], addr[3],
	    addr[4], addr[5]);

	usb_init_task(&sc->sc_swap_task, ueagle_loadpage, sc,
	    USB_TASK_TYPE_GENERIC);

	ifp->if_softc = sc;
	ifp->if_flags = IFF_SIMPLEX;
	ifp->if_ioctl = ueagle_ioctl;
	ifp->if_start = ueagle_start;
	IFQ_SET_READY(&ifp->if_snd);
	memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);

	if_attach(ifp);
	atm_ifattach(ifp);

	/* override default MTU value (9180 is too large for us) */
	ifp->if_mtu = UEAGLE_IFMTU;

#if NBPFILTER > 0
	bpfattach(&ifp->if_bpf, ifp, DLT_RAW, 0);
#endif
}
Пример #12
0
void
ulpt_attach(struct device *parent, struct device *self, void *aux)
{
	struct ulpt_softc *sc = (struct ulpt_softc *)self;
	struct usb_attach_arg *uaa = aux;
	struct usbd_device *dev = uaa->device;
	struct usbd_interface *iface = uaa->iface;
	usb_interface_descriptor_t *ifcd = usbd_get_interface_descriptor(iface);
	usb_interface_descriptor_t *id, *iend;
	usb_config_descriptor_t *cdesc;
	usbd_status err;
	usb_endpoint_descriptor_t *ed;
	u_int8_t epcount;
	int i, altno;

	DPRINTFN(10,("ulpt_attach: sc=%p\n", sc));

	//printf("%s: iclass %d/%d\n", sc->sc_dev.dv_xname,
	//    ifcd->bInterfaceClass, ifcd->bInterfaceSubClass);

	/* XXX
	 * Stepping through the alternate settings needs to be abstracted out.
	 */
	cdesc = usbd_get_config_descriptor(dev);
	if (cdesc == NULL) {
		printf("%s: failed to get configuration descriptor\n",
		       sc->sc_dev.dv_xname);
		return;
	}
	iend = (usb_interface_descriptor_t *)
		   ((char *)cdesc + UGETW(cdesc->wTotalLength));
#ifdef DIAGNOSTIC
	if (ifcd < (usb_interface_descriptor_t *)cdesc ||
	    ifcd >= iend)
		panic("ulpt: iface desc out of range");
#endif
	/* Step through all the descriptors looking for bidir mode */
	for (id = ifcd, altno = 0;
	     id < iend;
	     id = (void *)((char *)id + id->bLength)) {
		if (id->bDescriptorType == UDESC_INTERFACE &&
		    id->bInterfaceNumber == ifcd->bInterfaceNumber) {
			if (id->bInterfaceClass == UICLASS_PRINTER &&
			    id->bInterfaceSubClass == UISUBCLASS_PRINTER &&
			    (id->bInterfaceProtocol == UIPROTO_PRINTER_BI /*||
			     id->bInterfaceProtocol == UIPROTO_PRINTER_1284*/))
				goto found;
			altno++;
		}
	}
	id = ifcd;		/* not found, use original */
 found:
	if (id != ifcd) {
		/* Found a new bidir setting */
		DPRINTF(("ulpt_attach: set altno = %d\n", altno));
		err = usbd_set_interface(iface, altno);
		if (err) {
			printf("%s: setting alternate interface failed\n",
			       sc->sc_dev.dv_xname);
			usbd_deactivate(sc->sc_udev);
			return;
		}
	}

	epcount = 0;
	(void)usbd_endpoint_count(iface, &epcount);

	sc->sc_in = -1;
	sc->sc_out = -1;
	for (i = 0; i < epcount; i++) {
		ed = usbd_interface2endpoint_descriptor(iface, i);
		if (ed == NULL) {
			printf("%s: couldn't get ep %d\n",
			    sc->sc_dev.dv_xname, i);
			return;
		}
		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
			sc->sc_in = ed->bEndpointAddress;
		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
			sc->sc_out = ed->bEndpointAddress;
		}
	}
	if (sc->sc_out == -1) {
		printf("%s: could not find bulk out endpoint\n",
		    sc->sc_dev.dv_xname);
		usbd_deactivate(sc->sc_udev);
		return;
	}

	if (usbd_get_quirks(dev)->uq_flags & UQ_BROKEN_BIDIR) {
		/* This device doesn't handle reading properly. */
		sc->sc_in = -1;
	}

	printf("%s: using %s-directional mode\n", sc->sc_dev.dv_xname,
	       sc->sc_in >= 0 ? "bi" : "uni");

	DPRINTFN(10, ("ulpt_attach: bulk=%d\n", sc->sc_out));

	sc->sc_iface = iface;
	sc->sc_ifaceno = id->bInterfaceNumber;
	sc->sc_udev = dev;

	/* maybe the device needs firmware */
	sc->sc_fwdev = ulpt_lookup(uaa->vendor, uaa->product);
	if (sc->sc_fwdev) {
		if (rootvp == NULL)
			mountroothook_establish(ulpt_load_firmware, sc);
		else
			ulpt_load_firmware(sc);
	}

#if 0
/*
 * This code is disabled because for some mysterious reason it causes
 * printing not to work.  But only sometimes, and mostly with
 * UHCI and less often with OHCI.  *sigh*
 */
	{
	usb_config_descriptor_t *cd = usbd_get_config_descriptor(dev);
	usb_device_request_t req;
	int len, alen;

	req.bmRequestType = UT_READ_CLASS_INTERFACE;
	req.bRequest = UR_GET_DEVICE_ID;
	USETW(req.wValue, cd->bConfigurationValue);
	USETW2(req.wIndex, id->bInterfaceNumber, id->bAlternateSetting);
	USETW(req.wLength, DEVINFOSIZE - 1);
	err = usbd_do_request_flags(dev, &req, devinfop, USBD_SHORT_XFER_OK,
		  &alen, USBD_DEFAULT_TIMEOUT);
	if (err) {
		printf("%s: cannot get device id\n", sc->sc_dev.dv_xname);
	} else if (alen <= 2) {
		printf("%s: empty device id, no printer connected?\n",
		       sc->sc_dev.dv_xname);
	} else {
		/* devinfop now contains an IEEE-1284 device ID */
		len = ((devinfop[0] & 0xff) << 8) | (devinfop[1] & 0xff);
		if (len > DEVINFOSIZE - 3)
			len = DEVINFOSIZE - 3;
		devinfo[len] = 0;
		printf("%s: device id <", sc->sc_dev.dv_xname);
		ieee1284_print_id(devinfop+2);
		printf(">\n");
	}
	}
#endif
}