Пример #1
0
static void
uhci_reset (hci_t *controller)
{
	/* reset */
	uhci_reg_write16 (controller, USBCMD, 4);
	mdelay (50);
	uhci_reg_write16 (controller, USBCMD, 0);
	mdelay (10);
	uhci_reg_write16 (controller, USBCMD, 2);
	while ((uhci_reg_read16 (controller, USBCMD) & 2) != 0)
		mdelay (1);

	uhci_reg_write32 (controller, FLBASEADD,
			  (u32) virt_to_phys (UHCI_INST (controller)->
					      framelistptr));
	//debug ("framelist at %p\n",UHCI_INST(controller)->framelistptr);

	/* disable irqs */
	uhci_reg_write16 (controller, USBINTR, 0);

	/* reset framelist index */
	uhci_reg_write16 (controller, FRNUM, 0);

	uhci_reg_mask16 (controller, USBCMD, ~0, 0xc0);	// max packets, configure flag

	uhci_start (controller);
}
Пример #2
0
/* disable root hub */
static void
uhci_rh_disable_port (usbdev_t *dev, int port)
{
	hci_t *controller = dev->controller;
	if (port == 1)
		port = PORTSC1;
	else if (port == 2)
		port = PORTSC2;
	else {
		usb_debug("Invalid port %d\n", port);
		return;
	}
	uhci_reg_write16(controller, port,
			 uhci_reg_read16(controller, port) & ~4);
	u16 value;
	/* wait for controller to disable port */
	/* TOTEST: how long to wait? 100ms for now */
	int timeout = 200; /* time out after 200 * 500us == 100ms */
	do {
		value = uhci_reg_read16 (controller, port);
		udelay(500); timeout--;
	} while (((value & (1 << 2)) != 0) && timeout);
	if (!timeout)
		usb_debug("Warning: uhci_rh: port disabling timed out.\n");
}
Пример #3
0
static void
uhci_rh_scanport (usbdev_t *dev, int port)
{
	int portsc, offset;
	if (port == 1) {
		portsc = PORTSC1;
		offset = 0;
	} else if (port == 2) {
		portsc = PORTSC2;
		offset = 1;
	} else {
		usb_debug("Invalid port %d\n", port);
		return;
	}
	int devno = RH_INST (dev)->port[offset];
	if ((dev->controller->devices[devno] != 0) && (devno != -1)) {
		usb_detach_device(dev->controller, devno);
		RH_INST (dev)->port[offset] = -1;
	}
	uhci_reg_write16(dev->controller, portsc,
			 uhci_reg_read16(dev->controller, portsc) | (1 << 3) | (1 << 2));	// clear port state change, enable port

	mdelay(100); // wait for signal to stabilize

	if ((uhci_reg_read16 (dev->controller, portsc) & 1) != 0) {
		// device attached

		uhci_rh_disable_port (dev, port);
		uhci_rh_enable_port (dev, port);

		int speed = ((uhci_reg_read16 (dev->controller, portsc) >> 8) & 1);

		RH_INST (dev)->port[offset] = usb_attach_device(dev->controller, dev->address, portsc, speed);
	}
Пример #4
0
static void
uhci_reset (hci_t *controller)
{
	/* reset */
	uhci_reg_write16 (controller, USBCMD, 4); /* Global Reset */
	mdelay (50); /* uhci spec 2.1.1: at least 10ms */
	uhci_reg_write16 (controller, USBCMD, 0);
	mdelay (10);
	uhci_reg_write16 (controller, USBCMD, 2); /* Host Controller Reset */
	/* wait for controller to finish reset */
	/* TOTEST: how long to wait? 100ms for now */
	int timeout = 200; /* time out after 200 * 500us == 100ms */
	while (((uhci_reg_read16 (controller, USBCMD) & 2) != 0) && timeout--)
		udelay (500);
	if (timeout < 0)
		usb_debug ("Warning: uhci: host controller reset timed out.\n");
}
Пример #5
0
static void
uhci_reinit (hci_t *controller)
{
	uhci_reg_write32 (controller, FLBASEADD,
			  (u32) virt_to_phys (UHCI_INST (controller)->
					      framelistptr));
	//usb_debug ("framelist at %p\n",UHCI_INST(controller)->framelistptr);

	/* disable irqs */
	uhci_reg_write16 (controller, USBINTR, 0);

	/* reset framelist index */
	uhci_reg_write16 (controller, FRNUM, 0);

	uhci_reg_write16(controller, USBCMD,
			 uhci_reg_read16(controller, USBCMD) | 0xc0);	// max packets, configure flag

	uhci_start (controller);
}
Пример #6
0
static void
uhci_rh_enable_port (usbdev_t *dev, int port)
{
	u16 value;
	hci_t *controller = dev->controller;
	if (port == 1)
		port = PORTSC1;
	else if (port == 2)
		port = PORTSC2;
	else {
		usb_debug("Invalid port %d\n", port);
		return;
	}

	uhci_reg_write16(controller, port,
			 uhci_reg_read16(controller, port) & ~(1 << 12));	/* wakeup */

	uhci_reg_write16(controller, port,
			 uhci_reg_read16(controller, port) | 1 << 9);	/* reset */
	mdelay (30);		// >10ms
	uhci_reg_write16(controller, port,
			 uhci_reg_read16(controller, port) & ~(1 << 9));
	mdelay (1);		// >5.3us per spec, <3ms because some devices make trouble

	uhci_reg_write16(controller, port,
			 uhci_reg_read16(controller, port) | 1 << 2);	/* enable */
	/* wait for controller to enable port */
	/* TOTEST: how long to wait? 100ms for now */
	int timeout = 200; /* time out after 200 * 500us == 100ms */
	do {
		value = uhci_reg_read16 (controller, port);
		udelay(500); timeout--;
	} while (((value & (1 << 2)) == 0) && (value & 0x01) && timeout);
	if (!timeout)
		usb_debug("Warning: uhci_rh: port enabling timed out.\n");
}
Пример #7
0
static td_t *
wait_for_completed_qh (hci_t *controller, qh_t *qh)
{
	int timeout = 1000;	/* max 30 ms. */
	void *current = GET_TD (qh->elementlinkptr);
	while (((qh->elementlinkptr & FLISTP_TERMINATE) == 0) && (timeout-- > 0)) {
		if (current != GET_TD (qh->elementlinkptr)) {
			current = GET_TD (qh->elementlinkptr);
			timeout = 1000;
		}
		uhci_reg_write16(controller, USBSTS,
				 uhci_reg_read16(controller, USBSTS) | 0);	// clear resettable registers
		udelay (30);
	}
	return (GET_TD (qh->elementlinkptr) ==
		0) ? 0 : GET_TD (phys_to_virt (qh->elementlinkptr));
}
Пример #8
0
static void
uhci_shutdown (hci_t *controller)
{
	if (controller == 0)
		return;
	detach_controller (controller);
	UHCI_INST (controller)->roothub->destroy (UHCI_INST (controller)->
						  roothub);
	uhci_reg_write16(controller, USBCMD,
			 uhci_reg_read16(controller, USBCMD) & 0);	// stop work
	free (UHCI_INST (controller)->framelistptr);
	free (UHCI_INST (controller)->qh_prei);
	free (UHCI_INST (controller)->qh_intr);
	free (UHCI_INST (controller)->qh_data);
	free (UHCI_INST (controller)->qh_last);
	free (UHCI_INST (controller));
	free (controller);
}
Пример #9
0
static void
uhci_stop (hci_t *controller)
{
	uhci_reg_write16(controller, USBCMD,
			 uhci_reg_read16(controller, USBCMD) & ~1);	// stop work on schedule
}
Пример #10
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;
}
Пример #11
0
void
uhci_reg_mask16 (hci_t *ctrl, usbreg reg, u16 andmask, u16 ormask)
{
	uhci_reg_write16 (ctrl, reg,
			  (uhci_reg_read16 (ctrl, reg) & andmask) | ormask);
}