⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb_ohci.c

📁 arm920t内核linux操作系统U-BOOT引导程序中usb相关部分的程序
💻 C
📖 第 1 页 / 共 4 页
字号:
	/* device pulled? Shortcut the action. */	if (devgone == dev) {		dev->status = USB_ST_CRC_ERR;		return 0;	}#ifdef DEBUG	urb->actual_length = 0;	pkt_print(urb, dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe));#else	wait_ms(1);#endif	if (!maxsize) {		err("submit_common_message: pipesize for pipe %lx is zero",			pipe);		return -1;	}	if (sohci_submit_job(urb, setup) < 0) {		err("sohci_submit_job failed");		return -1;	}#if 0	wait_ms(10);	/* ohci_dump_status(&gohci); */#endif	/* allow more time for a BULK device to react - some are slow */#define BULK_TO	 5000	/* timeout in milliseconds */	if (usb_pipetype (pipe) == PIPE_BULK)		timeout = BULK_TO;	else		timeout = 100;	/* wait for it to complete */	for (;;) {		/* check whether the controller is done */		stat = hc_interrupt();		if (stat < 0) {			stat = USB_ST_CRC_ERR;			break;		}		/* NOTE: since we are not interrupt driven in U-Boot and always		 * handle only one URB at a time, we cannot assume the		 * transaction finished on the first successful return from		 * hc_interrupt().. unless the flag for current URB is set,		 * meaning that all TD's to/from device got actually		 * transferred and processed. If the current URB is not		 * finished we need to re-iterate this loop so as		 * hc_interrupt() gets called again as there needs to be some		 * more TD's to process still */		if ((stat >= 0) && (stat != 0xff) && (urb->finished)) {			/* 0xff is returned for an SF-interrupt */			break;		}		if (--timeout) {			wait_ms(1);			if (!urb->finished)				dbg("\%");		} else {			err("CTL:TIMEOUT ");			dbg("submit_common_msg: TO status %x\n", stat);			urb->finished = 1;			stat = USB_ST_CRC_ERR;			break;		}	}	dev->status = stat;	dev->act_len = transfer_len;#ifdef DEBUG	pkt_print(urb, dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", usb_pipein(pipe));#else	wait_ms(1);#endif	/* free TDs in urb_priv */	if (usb_pipetype (pipe) != PIPE_INTERRUPT)		urb_free_priv (urb);	return 0;}/* submit routines called from usb.c */int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,		int transfer_len){	info("submit_bulk_msg");	return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, 0);}int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,		int transfer_len, struct devrequest *setup){	int maxsize = usb_maxpacket(dev, pipe);	info("submit_control_msg");#ifdef DEBUG	pkt_print(NULL, dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe));#else	wait_ms(1);#endif	if (!maxsize) {		err("submit_control_message: pipesize for pipe %lx is zero",			pipe);		return -1;	}	if (((pipe >> 8) & 0x7f) == gohci.rh.devnum) {		gohci.rh.dev = dev;		/* root hub - redirect */		return ohci_submit_rh_msg(dev, pipe, buffer, transfer_len,			setup);	}	return submit_common_msg(dev, pipe, buffer, transfer_len, setup, 0);}int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,		int transfer_len, int interval){	info("submit_int_msg");	return submit_common_msg(dev, pipe, buffer, transfer_len, NULL,			interval);}/*-------------------------------------------------------------------------* * HC functions *-------------------------------------------------------------------------*//* reset the HC and BUS */static int hc_reset (ohci_t *ohci){	int timeout = 30;	int smm_timeout = 50; /* 0,5 sec */	dbg("%s\n", __FUNCTION__);	if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */		writel (OHCI_OCR, &ohci->regs->cmdstatus); /* request ownership */		info("USB HC TakeOver from SMM");		while (readl (&ohci->regs->control) & OHCI_CTRL_IR) {			wait_ms (10);			if (--smm_timeout == 0) {				err("USB HC TakeOver failed!");				return -1;			}		}	}	/* Disable HC interrupts */	writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);	dbg("USB HC reset_hc usb-%s: ctrl = 0x%X ;\n",		ohci->slot_name,		readl(&ohci->regs->control));	/* Reset USB (needed by some controllers) */	ohci->hc_control = 0;	writel (ohci->hc_control, &ohci->regs->control);	/* HC Reset requires max 10 us delay */	writel (OHCI_HCR,  &ohci->regs->cmdstatus);	while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {		if (--timeout == 0) {			err("USB HC reset timed out!");			return -1;		}		udelay (1);	}	return 0;}/*-------------------------------------------------------------------------*//* Start an OHCI controller, set the BUS operational * enable interrupts * connect the virtual root hub */static int hc_start (ohci_t * ohci){	__u32 mask;	unsigned int fminterval;	ohci->disabled = 1;	/* Tell the controller where the control and bulk lists are	 * The lists are empty now. */	writel (0, &ohci->regs->ed_controlhead);	writel (0, &ohci->regs->ed_bulkhead);	writel ((__u32)ohci->hcca, &ohci->regs->hcca); /* a reset clears this */	fminterval = 0x2edf;	writel ((fminterval * 9) / 10, &ohci->regs->periodicstart);	fminterval |= ((((fminterval - 210) * 6) / 7) << 16);	writel (fminterval, &ohci->regs->fminterval);	writel (0x628, &ohci->regs->lsthresh);	/* start controller operations */	ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;	ohci->disabled = 0;	writel (ohci->hc_control, &ohci->regs->control);	/* disable all interrupts */	mask = (OHCI_INTR_SO | OHCI_INTR_WDH | OHCI_INTR_SF | OHCI_INTR_RD |			OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC |			OHCI_INTR_OC | OHCI_INTR_MIE);	writel (mask, &ohci->regs->intrdisable);	/* clear all interrupts */	mask &= ~OHCI_INTR_MIE;	writel (mask, &ohci->regs->intrstatus);	/* Choose the interrupts we care about now  - but w/o MIE */	mask = OHCI_INTR_RHSC | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO;	writel (mask, &ohci->regs->intrenable);#ifdef	OHCI_USE_NPS	/* required for AMD-756 and some Mac platforms */	writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM,		&ohci->regs->roothub.a);	writel (RH_HS_LPSC, &ohci->regs->roothub.status);#endif	/* OHCI_USE_NPS */#define mdelay(n) ({unsigned long msec=(n); while (msec--) udelay(1000);})	/* POTPGT delay is bits 24-31, in 2 ms units. */	mdelay ((roothub_a (ohci) >> 23) & 0x1fe);	/* connect the virtual root hub */	ohci->rh.devnum = 0;	return 0;}/*-------------------------------------------------------------------------*//* Poll USB interrupt. */void usb_event_poll(void){	hc_interrupt();}/* an interrupt happens */static int hc_interrupt (void){	ohci_t *ohci = &gohci;	struct ohci_regs *regs = ohci->regs;	int ints;	int stat = -1;	if ((ohci->hcca->done_head != 0) &&	    !(m32_swap (ohci->hcca->done_head) & 0x01)) {		ints =  OHCI_INTR_WDH;	} else if ((ints = readl (&regs->intrstatus)) == ~(u32)0) {		ohci->disabled++;		err ("%s device removed!", ohci->slot_name);		return -1;	} else if ((ints &= readl (&regs->intrenable)) == 0) {		dbg("hc_interrupt: returning..\n");		return 0xff;	}	/* dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); */	if (ints & OHCI_INTR_RHSC) {		got_rhsc = 1;		stat = 0xff;	}	if (ints & OHCI_INTR_UE) {		ohci->disabled++;		err ("OHCI Unrecoverable Error, controller usb-%s disabled",			ohci->slot_name);		/* e.g. due to PCI Master/Target Abort */#ifdef	DEBUG		ohci_dump (ohci, 1);#else	wait_ms(1);#endif		/* FIXME: be optimistic, hope that bug won't repeat often. */		/* Make some non-interrupt context restart the controller. */		/* Count and limit the retries though; either hardware or */		/* software errors can go forever... */		hc_reset (ohci);		return -1;	}	if (ints & OHCI_INTR_WDH) {		wait_ms(1);		writel (OHCI_INTR_WDH, &regs->intrdisable);		(void)readl (&regs->intrdisable); /* flush */		stat = dl_done_list (&gohci, dl_reverse_done_list (&gohci));		writel (OHCI_INTR_WDH, &regs->intrenable);		(void)readl (&regs->intrdisable); /* flush */	}	if (ints & OHCI_INTR_SO) {		dbg("USB Schedule overrun\n");		writel (OHCI_INTR_SO, &regs->intrenable);		stat = -1;	}	/* FIXME:  this assumes SOF (1/ms) interrupts don't get lost... */	if (ints & OHCI_INTR_SF) {		unsigned int frame = m16_swap (ohci->hcca->frame_no) & 1;		wait_ms(1);		writel (OHCI_INTR_SF, &regs->intrdisable);		if (ohci->ed_rm_list[frame] != NULL)			writel (OHCI_INTR_SF, &regs->intrenable);		stat = 0xff;	}	writel (ints, &regs->intrstatus);	return stat;}/*-------------------------------------------------------------------------*//*-------------------------------------------------------------------------*//* De-allocate all resources.. */static void hc_release_ohci (ohci_t *ohci){	dbg ("USB HC release ohci usb-%s", ohci->slot_name);	if (!ohci->disabled)		hc_reset (ohci);}/*-------------------------------------------------------------------------*//* * low level initalisation routine, called from usb.c */static char ohci_inited = 0;int usb_lowlevel_init(void){#ifdef CONFIG_PCI_OHCI	pci_dev_t pdev;#endif#ifdef CFG_USB_OHCI_CPU_INIT	/* cpu dependant init */	if(usb_cpu_init())		return -1;#endif#ifdef CFG_USB_OHCI_BOARD_INIT	/*  board dependant init */	if(usb_board_init())		return -1;#endif	memset (&gohci, 0, sizeof (ohci_t));	/* align the storage */	if ((__u32)&ghcca[0] & 0xff) {		err("HCCA not aligned!!");		return -1;	}	phcca = &ghcca[0];	info("aligned ghcca %p", phcca);	memset(&ohci_dev, 0, sizeof(struct ohci_device));	if ((__u32)&ohci_dev.ed[0] & 0x7) {		err("EDs not aligned!!");		return -1;	}	memset(gtd, 0, sizeof(td_t) * (NUM_TD + 1));	if ((__u32)gtd & 0x7) {		err("TDs not aligned!!");		return -1;	}	ptd = gtd;	gohci.hcca = phcca;	memset (phcca, 0, sizeof (struct ohci_hcca));	gohci.disabled = 1;	gohci.sleeping = 0;	gohci.irq = -1;#ifdef CONFIG_PCI_OHCI	pdev = pci_find_devices(ohci_pci_ids, 0);	if (pdev != -1) {		u16 vid, did;		u32 base;		pci_read_config_word(pdev, PCI_VENDOR_ID, &vid);		pci_read_config_word(pdev, PCI_DEVICE_ID, &did);		printf("OHCI pci controller (%04x, %04x) found @(%d:%d:%d)\n",				vid, did, (pdev >> 16) & 0xff,				(pdev >> 11) & 0x1f, (pdev >> 8) & 0x7);		pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &base);		printf("OHCI regs address 0x%08x\n", base);		gohci.regs = (struct ohci_regs *)base;	} else		return -1;#else	gohci.regs = (struct ohci_regs *)CFG_USB_OHCI_REGS_BASE;#endif	gohci.flags = 0;	gohci.slot_name = CFG_USB_OHCI_SLOT_NAME;	if (hc_reset (&gohci) < 0) {		hc_release_ohci (&gohci);		err ("can't reset usb-%s", gohci.slot_name);#ifdef CFG_USB_OHCI_BOARD_INIT		/* board dependant cleanup */		usb_board_init_fail();#endif#ifdef CFG_USB_OHCI_CPU_INIT		/* cpu dependant cleanup */		usb_cpu_init_fail();#endif		return -1;	}	/* FIXME this is a second HC reset; why?? */	/* writel(gohci.hc_control = OHCI_USB_RESET, &gohci.regs->control);	   wait_ms(10); */	if (hc_start (&gohci) < 0) {		err ("can't start usb-%s", gohci.slot_name);		hc_release_ohci (&gohci);		/* Initialization failed */#ifdef CFG_USB_OHCI_BOARD_INIT		/* board dependant cleanup */		usb_board_stop();#endif#ifdef CFG_USB_OHCI_CPU_INIT		/* cpu dependant cleanup */		usb_cpu_stop();#endif		return -1;	}#ifdef	DEBUG	ohci_dump (&gohci, 1);#else	wait_ms(1);#endif	ohci_inited = 1;	return 0;}int usb_lowlevel_stop(void){	/* this gets called really early - before the controller has */	/* even been initialized! */	if (!ohci_inited)		return 0;	/* TODO release any interrupts, etc. */	/* call hc_release_ohci() here ? */	hc_reset (&gohci);#ifdef CFG_USB_OHCI_BOARD_INIT	/* board dependant cleanup */	if(usb_board_stop())		return -1;#endif#ifdef CFG_USB_OHCI_CPU_INIT	/* cpu dependant cleanup */	if(usb_cpu_stop())		return -1;#endif	return 0;}#endif /* CONFIG_USB_OHCI_NEW */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -