Beispiel #1
0
int
uhci_pci_detach(device_t self)
{
	uhci_softc_t *sc = device_get_softc(self);
	device_t bdev;

	if (sc->sc_bus.bdev) {
		bdev = sc->sc_bus.bdev;
		device_detach(bdev);
		device_delete_child(self, bdev);
	}
	/* during module unload there are lots of children leftover */
	device_delete_children(self);

	/*
	 * disable interrupts that might have been switched on in
	 * uhci_init.
	 */
	if (sc->sc_io_res) {
		USB_BUS_LOCK(&sc->sc_bus);

		/* stop the controller */
		uhci_reset(sc);

		USB_BUS_UNLOCK(&sc->sc_bus);
	}
	pci_disable_busmaster(self);

	if (sc->sc_irq_res && sc->sc_intr_hdl) {
		int err = bus_teardown_intr(self, sc->sc_irq_res, sc->sc_intr_hdl);

		if (err) {
			/* XXX or should we panic? */
			device_printf(self, "Could not tear down irq, %d\n",
			    err);
		}
		sc->sc_intr_hdl = NULL;
	}
	if (sc->sc_irq_res) {
		bus_release_resource(self, SYS_RES_IRQ, 0, sc->sc_irq_res);
		sc->sc_irq_res = NULL;
	}
	if (sc->sc_io_res) {
		bus_release_resource(self, SYS_RES_IOPORT, PCI_UHCI_BASE_REG,
		    sc->sc_io_res);
		sc->sc_io_res = NULL;
	}
	usb_bus_mem_free_all(&sc->sc_bus, &uhci_iterate_hw_softc);

	return (0);
}
Beispiel #2
0
void setup_pci_devs(pci_dt_t *pci_dt)
{
	char *devicepath;
	BOOL do_eth_devprop, do_gfx_devprop, fix_ehci, fix_legoff, fix_uhci, fix_usb, do_enable_hpet;
	pci_dt_t *current = pci_dt;

	do_eth_devprop = do_gfx_devprop = fix_ehci = fix_legoff = fix_uhci = fix_usb = do_enable_hpet = false;

	getBoolForKey("EthernetBuiltIn", &do_eth_devprop, &bootInfo->bootConfig);
	getBoolForKey("GraphicsEnabler", &do_gfx_devprop, &bootInfo->bootConfig);
	if (getBoolForKey("USBBusFix", &fix_usb, &bootInfo->bootConfig) && fix_usb)
		fix_ehci = fix_uhci = true;
	else
	{
		getBoolForKey("EHCIacquire", &fix_ehci, &bootInfo->bootConfig);
		getBoolForKey("UHCIreset", &fix_uhci, &bootInfo->bootConfig);
	}
	getBoolForKey("USBLegacyOff", &fix_legoff, &bootInfo->bootConfig);
	getBoolForKey("ForceHPET", &do_enable_hpet, &bootInfo->bootConfig);

	while (current)
	{
		devicepath = get_pci_dev_path(current);

		switch (current->class_id)
		{
			case PCI_CLASS_NETWORK_ETHERNET: 
				if (do_eth_devprop)
					set_eth_builtin(current);
				break;
				
			case PCI_CLASS_DISPLAY_VGA:
				if (do_gfx_devprop)
					switch (current->vendor_id)
					{
						case PCI_VENDOR_ID_ATI:
							verbose("ATI VGA Controller [%04x:%04x] :: %s \n", 
							current->vendor_id, current->device_id, devicepath);
							setup_ati_devprop(current); 
							break;
					
						case PCI_VENDOR_ID_INTEL: 
							/* message to be removed once support for these cards is added */
							verbose("Intel VGA Controller [%04x:%04x] :: %s (currently NOT SUPPORTED)\n", 
								current->vendor_id, current->device_id, devicepath);
							break;
					
						case PCI_VENDOR_ID_NVIDIA: 
							setup_nvidia_devprop(current);
							break;
					}
				break;

			case PCI_CLASS_SERIAL_USB:
				switch (pci_config_read8(current->dev.addr, PCI_CLASS_PROG))
				{
					/* EHCI */
					case 0x20:
				    	if (fix_ehci)
							ehci_acquire(current);
						if (fix_legoff)
							legacy_off(current);
						break;

					/* UHCI */
					case 0x00:
				    	if (fix_uhci)
							uhci_reset(current);
						break;
				}
				break;

			case PCI_CLASS_BRIDGE_ISA:
				if (do_enable_hpet)
					force_enable_hpet(current);
				break;
		}
		
		setup_pci_devs(current->children);
		current = current->next;
	}
}
Beispiel #3
0
hci_t *
uhci_init (pcidev_t addr)
{
	int i;
	u16 reg16;

	hci_t *controller = new_controller ();

	if (!controller)
		fatal("Could not create USB controller instance.\n");

	controller->instance = malloc (sizeof (uhci_t));
	if(!controller->instance)
		fatal("Not enough memory creating USB controller instance.\n");

	controller->type = UHCI;

	controller->start = uhci_start;
	controller->stop = uhci_stop;
	controller->reset = uhci_reset;
	controller->init = uhci_reinit;
	controller->shutdown = uhci_shutdown;
	controller->bulk = uhci_bulk;
	controller->control = uhci_control;
	controller->set_address = generic_set_address;
	controller->finish_device_config = NULL;
	controller->destroy_device = NULL;
	controller->create_intr_queue = uhci_create_intr_queue;
	controller->destroy_intr_queue = uhci_destroy_intr_queue;
	controller->poll_intr_queue = uhci_poll_intr_queue;
	for (i = 0; i < 128; i++) {
		controller->devices[i] = 0;
	}
	init_device_entry (controller, 0);
	UHCI_INST (controller)->roothub = controller->devices[0];

	controller->bus_address = addr;
	controller->reg_base = pci_read_config32 (controller->bus_address, 0x20) & ~1;	/* ~1 clears the register type indicator that is set to 1 for IO space */

	/* kill legacy support handler */
	uhci_stop (controller);
	mdelay (1);
	uhci_reg_write16 (controller, USBSTS, 0x3f);
	reg16 = pci_read_config16(controller->bus_address, 0xc0);
	reg16 &= 0xdf80;
	pci_write_config16 (controller->bus_address, 0xc0, reg16);

	UHCI_INST (controller)->framelistptr = memalign (0x1000, 1024 * sizeof (flistp_t));	/* 4kb aligned to 4kb */
	if (! UHCI_INST (controller)->framelistptr)
		fatal("Not enough memory for USB frame list pointer.\n");

	memset (UHCI_INST (controller)->framelistptr, 0,
		1024 * sizeof (flistp_t));

	/* According to the *BSD UHCI code, this one is needed on some
	   PIIX chips, because otherwise they misbehave. It must be
	   added to the last chain.

	   FIXME: this leaks, if the driver should ever be reinited
	          for some reason. Not a problem now.
	   */
	td_t *antiberserk = memalign(16, sizeof(td_t));
	if (!antiberserk)
		fatal("Not enough memory for chipset workaround.\n");
	memset(antiberserk, 0, sizeof(td_t));

	UHCI_INST (controller)->qh_prei = memalign (16, sizeof (qh_t));
	UHCI_INST (controller)->qh_intr = memalign (16, sizeof (qh_t));
	UHCI_INST (controller)->qh_data = memalign (16, sizeof (qh_t));
	UHCI_INST (controller)->qh_last = memalign (16, sizeof (qh_t));

	if (! UHCI_INST (controller)->qh_prei ||
	    ! UHCI_INST (controller)->qh_intr ||
	    ! UHCI_INST (controller)->qh_data ||
	    ! UHCI_INST (controller)->qh_last)
		fatal("Not enough memory for USB controller queues.\n");

	UHCI_INST (controller)->qh_prei->headlinkptr =
		virt_to_phys (UHCI_INST (controller)->qh_intr) | FLISTP_QH;
	UHCI_INST (controller)->qh_prei->elementlinkptr = 0 | FLISTP_TERMINATE;

	UHCI_INST (controller)->qh_intr->headlinkptr =
		virt_to_phys (UHCI_INST (controller)->qh_data) | FLISTP_QH;
	UHCI_INST (controller)->qh_intr->elementlinkptr = 0 | FLISTP_TERMINATE;

	UHCI_INST (controller)->qh_data->headlinkptr =
		virt_to_phys (UHCI_INST (controller)->qh_last) | FLISTP_QH;
	UHCI_INST (controller)->qh_data->elementlinkptr = 0 | FLISTP_TERMINATE;

	UHCI_INST (controller)->qh_last->headlinkptr = virt_to_phys (UHCI_INST (controller)->qh_data) | FLISTP_TERMINATE;
	UHCI_INST (controller)->qh_last->elementlinkptr = virt_to_phys (antiberserk) | FLISTP_TERMINATE;

	for (i = 0; i < 1024; i++) {
		UHCI_INST (controller)->framelistptr[i] =
			virt_to_phys (UHCI_INST (controller)->qh_prei) | FLISTP_QH;
	}
	controller->devices[0]->controller = controller;
	controller->devices[0]->init = uhci_rh_init;
	controller->devices[0]->init (controller->devices[0]);
	uhci_reset (controller);
	uhci_reinit (controller);
	return controller;
}