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

📄 ohci-sl811-regs.h

📁 优龙2410linux2.6.8内核源代码
💻 H
字号:
/* * SL811HS OHCI HCD (Host Controller Driver) for USB. * * linux/drivers/usb/host/ohci-sl811-regs.h * * Copyright (C) 2004 by Lothar Wassmann <LW at KARO-electronics.de> * * This file is subject to the terms and conditions of the GNU General Public * License.  See the file "COPYING" in the main directory of this archive * for more details. * * * Macros for OHCI register access to facilitate OHCI emulation * on non-OHCI compliant hardware * */#include "ohci-sl811.h"#define hcd_to_sl811_dev(hcd)	((struct hc_sl811_dev *)dev_get_drvdata(hcd->self.controller))#define ohci_to_sl811_dev(ohci)	((struct hc_sl811_dev *)dev_get_drvdata(ohci->hcd.self.controller))#define hc_sl811_dev_to_hcd(dev) ((struct usb_hcd *)dev_get_drvdata(&dev->dev))/* * OHCI emulation */static void sl811_reset_hc(struct usb_hcd *hcd, int cold);static int hc_sl811_detect_device(struct usb_hcd *hcd);#define HcControl		(regs->control)#define HcCmdStatus		(regs->cmdstatus)#define HcFmRemaining		(regs->fmremaining)#define HcFmNumber		(regs->fmnumber)#define HcFmInterval		(regs->fminterval)#define HcPeriodicStart		(regs->periodicstart)#define HcLsThreshold		(regs->lsthresh)#define HcRhStatus		(regs->roothub.status)#define HcRhPortStatus		(regs->roothub.portstatus)#define HcIntrEnable		(regs->intrenable)#define HcIntrStatus		(regs->intrstatus)#define HcControlHeadED		(regs->ed_controlhead)#define HcBulkHeadED		(regs->ed_bulkhead)#define HcDoneHead		(regs->donehead)#define HcControlCurrentED	(regs->ed_controlcurrent)#define HcBulkCurrentED		(regs->ed_bulkcurrent)#define HcPeriodCurrentED	(regs->ed_periodcurrent)#define HCCADoneHead		(hcca->done_head)#define HCCAFrameNumber		(hcca->frame_no)#define HCCAInterruptTable	(hcca->int_table)static void sl811_trigger_bh(struct hc_sl811_dev *dev, dev_state_t req){	if (dev->dev_state & DEV_TRIGGERED) {		dev->dev_state |= req;	} else {		dev->dev_state |= req;		tasklet_schedule(&dev->usb_reset_bh);	}}static void ohci_sl811_update_intrstatus(struct ohci_hcd *ohci, u32 set){	struct usb_hcd *hcd = ohci_to_hcd(ohci);	struct hc_sl811_dev *dev = hcd_to_sl811_dev(hcd);	struct ohci_regs *regs = ohci->regs;	unsigned long flags;	u32 stat;	u32 chg;	local_irq_save(flags);	stat = ohci->regs->intrstatus;	chg = set & ~stat;	if (chg) {		HcIntrStatus |= set;		ohci_vdbg(ohci, "%s: HcIntrStatus changed from %08x to %08x (%08x)\n",			  __FUNCTION__, stat, HcIntrStatus, set);		if (HcIntrEnable & set) {			WARN_ON(!in_interrupt());			sl811_trigger_bh(dev, DEV_OHCI_IRQ);		}	}	local_irq_restore(flags);}static void ohci_sl811_update_portstatus(struct ohci_hcd *ohci, int port, u32 set, u32 clr){	unsigned long flags;	u32 stat;	u32 new;	u32 chg;	WARN_ON(!ohci->regs);	if (!ohci->regs) {		return;	}	if (port < 0 || port >= MAX_ROOT_PORTS) {		printk("%s: Invalid port number %d\n", __FUNCTION__, port);		return;	}	local_irq_save(flags);	stat = ohci->regs->roothub.portstatus[port];	new = ((stat & 0xffff) | set) & ~clr;	chg = (stat ^ new) & 0xffff;	ohci_vdbg(ohci, "%s: old: %08x new: %08x chg: %04x\n", __FUNCTION__, stat, new, chg);	if (chg) {		u32 int_status = OHCI_INTR_RHSC;		chg |= stat >> 16;		ohci_vdbg(ohci, "%s: Changed port_status from %08x to: %08x\n", __FUNCTION__,			ohci->regs->roothub.portstatus[port], new | (chg << 16));		ohci->regs->roothub.portstatus[port] = new | (chg << 16);		if ((chg & RH_PS_CCS) && (ohci->regs->control & RH_HS_DRWE)) {			int_status |= OHCI_INTR_RD;		}		ohci_sl811_update_intrstatus(ohci, int_status);	} else {		ohci_vdbg(ohci, "%s: Leaving portstatus unchanged: %08x\n", __FUNCTION__,			ohci->regs->roothub.portstatus[port]);	}	local_irq_restore(flags);}/* * Software API */#define ohci_read_reg(hc,n)						\({									\	u32 *reg = &(hc)->regs->n;					\	u32 val;							\									\	val = *reg;							\	val;								\})#define ohci_write_reg(hc,n,v)						\{									\	u32 *reg = &ohci->regs->n;					\									\	*reg = v;							\}#define ohci_read_roothub_reg(hc,n)					\	ohci_read_reg(hc,roothub.n)#define ohci_write_roothub_reg(hc,n,v)						\({										\	u32 *reg = &ohci->regs->roothub.n;					\										\	*reg = v;								\})#define	ohci_read_intrstatus(hc)	ohci_read_reg(hc, intrstatus)#define	ohci_read_intrenable(hc)	ohci_read_reg(hc, intrenable)#define ohci_read_intrdisable		ohci_read_intrenable#define ohci_read_control(hc)		ohci_read_reg(hc, control)#define ohci_read_cmdstatus(hc)		ohci_read_reg(hc, cmdstatus)#define ohci_read_roothub_a(hc)		ohci_read_roothub_reg(hc, a)#define ohci_read_roothub_b(hc)		ohci_read_roothub_reg(hc, b)#define ohci_read_roothub_status(hc)	ohci_read_roothub_reg(hc, status)#define ohci_write_roothub_a(hc,v)	ohci_write_roothub_reg(hc,a,v)#define ohci_write_roothub_b(hc,v)	ohci_write_roothub_reg(hc,b,v)#define ohci_write_controlhead(hc,v)	ohci_write_reg(hc, ed_controlhead, v)#define ohci_write_controlcurrent(hc,v)	ohci_write_reg(hc, ed_controlcurrent, v)#define ohci_write_bulkhead(hc,v)	ohci_write_reg(hc, ed_bulkhead, v)#define ohci_write_bulkcurrent(hc,v)	ohci_write_reg(hc, ed_bulkcurrent, v)#define ohci_write_periodcurrent(hc,v)	ohci_write_reg(hc, ed_periodcurrent, v)static void _ohci_write_control(struct ohci_regs *regs, struct usb_hcd *hcd, u32 ctrl){	unsigned long flags;	struct hc_sl811_dev *dev = hcd_to_sl811_dev(hcd);	struct ohci_hcd *ohci = hcd_to_ohci(hcd);	int old_state;	int new_state = ctrl & OHCI_CTRL_HCFS;	u32 chg;	u32 old;	local_irq_save(flags);	old_state = regs->control & OHCI_CTRL_HCFS;	old = regs->control;	chg = old ^ ctrl;	regs->control = ctrl;	local_irq_restore(flags);	if (old_state != new_state) {		ohci_dbg(ohci, "%s: Changing state from %08x to %08x\n", __FUNCTION__, old_state, new_state);		switch (new_state) {		case OHCI_USB_RESET:			ohci_dbg(ohci, "%s: Going to USB_RESET state: %12u\n", __FUNCTION__, OSCR);			sl811_reset_hc(hcd, 0);			break;		case OHCI_USB_RESUME:			ohci_dbg(ohci, "%s: Going to USB_RESUME state: %12u\n", __FUNCTION__, OSCR);			if (old_state == OHCI_USB_SUSPEND) {				ohci_dbg(ohci, "%s: Deactivating SUSPEND mode\n", __FUNCTION__);				hc_sl811_set_mask(dev, SL11H_CTLREG1, SL11H_CTL1MASK_SOFENA);			}			break;		case OHCI_USB_SUSPEND:			ohci_dbg(ohci, "%s: Going to USB_SUSPEND state: %12u\n", __FUNCTION__, OSCR);			if (old_state == OHCI_USB_OPER) {				ohci_dbg(ohci, "%s: Activating SUSPEND mode\n", __FUNCTION__);				hc_sl811_clr_mask(dev, SL11H_CTLREG1, SL11H_CTL1MASK_SOFENA);				local_irq_save(flags);				__hc_sl811_clr_mask(dev, SL11H_INTENBLREG, SL11H_INTMASK_SOFINTR);				del_timer(&dev->int_timer);				local_irq_restore(flags);			}			break;		case OHCI_USB_OPER:			ohci_dbg(ohci, "%s: Going to USB_OPERATIONAL state: %12u\n", __FUNCTION__, OSCR);			switch (old_state) {			case OHCI_USB_RESET:				ohci_dbg(ohci, "%s: Leaving USB_RESET state: %12u\n", __FUNCTION__, OSCR);				break;			case OHCI_USB_RESUME:				ohci_dbg(ohci, "%s: Disabling USB Resume Interrupt\n", __FUNCTION__);				hc_sl811_clr_mask(dev, SL11H_CTLREG1, SL11H_CTL1MASK_SUSPEND);				hc_sl811_clr_mask(dev, SL11H_INTENBLREG, SL11H_INTMASK_RESUME);				ohci_dbg(ohci, "%s: int_mask=%02x, int_stat=%02x\n", __FUNCTION__,					hc_sl811_read_reg(dev, SL11H_INTENBLREG),					hc_sl811_read_reg(dev, SL11H_INTSTATREG));				break;			case OHCI_USB_SUSPEND:				ohci_dbg(ohci, "%s: Enabling USB Resume Interrupt\n", __FUNCTION__);				local_irq_save(flags);				__hc_sl811_set_mask(dev, SL11H_INTENBLREG, SL11H_INTMASK_RESUME);				__hc_sl811_set_mask(dev, SL11H_CTLREG1, SL11H_CTL1MASK_SUSPEND);				local_irq_restore(flags);				break;			}			break;		}	}}static void ohci_write_control(struct ohci_hcd *ohci, u32 ctrl){	_ohci_write_control(ohci->regs, ohci_to_hcd(ohci), ctrl);}static void _ohci_write_cmdstatus(struct ohci_regs *regs, struct usb_hcd *hcd, u32 cmd){	unsigned long flags;	u32 chg;	if (cmd & OHCI_HCR) {		sl811_reset_hc(hcd, 0);		cmd &= ~OHCI_HCR;	}	local_irq_save(flags);	chg = cmd ^ regs->cmdstatus;	regs->cmdstatus = cmd;	local_irq_restore(flags);}static void ohci_write_cmdstatus(struct ohci_hcd *ohci, u32 cmd){	_ohci_write_cmdstatus(ohci->regs, ohci_to_hcd(ohci), cmd);}static void ohci_write_roothub_status(struct ohci_hcd *ohci, u32 mask){	//struct usb_hcd *hcd = ohci_to_hcd(ohci);	//struct hc_sl811_dev *dev = hcd_to_sl811_dev(hcd);	unsigned long flags;	u32 *reg = &ohci->regs->roothub.status;	u32 status = 0;	local_irq_save(flags);	if (mask & RH_HS_LPS) {		// Power control not supported on SL811	}	if (mask & RH_HS_DRWE) {		status |= RH_HS_DRWE;	}	if (mask & RH_HS_CRWE) {		status &= ~RH_HS_DRWE;	}	if (mask & RH_HS_LPSC) {		// Power control not supported on SL811		status &= ~RH_HS_LPSC;	}	if (mask & RH_HS_OCIC) {		status &= ~RH_HS_OCIC;	}	if (*reg != status) {		ohci_sl811_update_intrstatus(ohci, OHCI_INTR_RHSC);	}	*reg = status;	local_irq_restore(flags);}static u32 ohci_read_roothub_portstatus(struct ohci_hcd *ohci, int port){	struct ohci_roothub_regs *rh_regs = &ohci->regs->roothub;	u32 status = RH_PS_PPS;	static u32 old_status = -1;	if (port < 0 || port >= MAX_ROOT_PORTS) {		ohci_err(ohci, "%s: Invalid port number %d\n", __FUNCTION__, port);		return -1;	}	status |= rh_regs->portstatus[port];	if (old_status != status) {		ohci_vdbg(ohci, "%s: Read %08x from portstatus[%d]\n", __FUNCTION__, status, port);		old_status = status;	}	return status;}static void ohci_write_roothub_portstatus(struct ohci_hcd *ohci, int port, u32 mask){	unsigned long flags;	struct ohci_roothub_regs *rh_regs = &ohci->regs->roothub;	u32 status;	if (port < 0 || port >= MAX_ROOT_PORTS) {		printk("%s: Invalid port number %d\n", __FUNCTION__, port);		return;	}#ifdef DEBUG	status = rh_regs->portstatus[port];	ohci_vdbg(ohci, "%s: Writing %08x to portstatus[%d]: %08x\n", __FUNCTION__, mask, port, status);#endif	local_irq_save(flags);	status = rh_regs->portstatus[port];	if (mask & RH_PS_PESC) {		status &= ~RH_PS_PESC;	}	if (mask & RH_PS_PSSC) {		status &= ~RH_PS_PSSC;	}	if (mask & RH_PS_OCIC) {		status &= ~RH_PS_OCIC;	}	if (mask & RH_PS_PRSC) {		status &= ~RH_PS_PRSC;	}	if (mask & RH_PS_CSC) {		status &= ~RH_PS_CSC;	}	if (status & RH_PS_CCS) {		if (mask & RH_PS_CCS) {			// clear PES, if device is removable			if (rh_regs->b & (1 << port)) {				status &= ~RH_PS_PES;			}		}		if (mask & RH_PS_PES) {			status |= RH_PS_PES;		}		if (mask & RH_PS_PSS) {			status |= RH_PS_PSS;		}		if (mask & RH_PS_POCI) {			status &= ~RH_PS_PSS;		}		if (mask & RH_PS_PRS) {			status |= RH_PS_PRS;		}		if (mask & RH_PS_PPS) {			// PPS enabled: set PPS		}		if (mask & RH_PS_LSDA) {			// PPS enabled: clear PPS		}	} else {		if (mask & (RH_PS_PRS | RH_PS_PES | RH_PS_PSS)) {			status |= RH_PS_CSC;		}	}	if (status != rh_regs->portstatus[port]) {		ohci_vdbg(ohci, "%s: status of port %d changed from %08x to %08x\n", __FUNCTION__,			port, rh_regs->portstatus[port], status);	}	rh_regs->portstatus[port] = status;	if (status & RH_PS_PRS) {		ohci_vdbg(ohci, "%s: Performing USB Port reset\n", __FUNCTION__);		hc_sl811_usb_reset(ohci_to_hcd(ohci), -1);	}	local_irq_restore(flags);}static void ohci_write_intrstatus(struct ohci_hcd *ohci, u32 ohci_mask){	unsigned long flags;	ohci_vdbg(ohci, "%s: Acknowledging Interrupts: %08x\n", __FUNCTION__, ohci_mask);	local_irq_save(flags);	ohci->regs->intrstatus &= ~ohci_mask;	local_irq_restore(flags);}static void ohci_write_intrenable(struct ohci_hcd *ohci, u32 ohci_mask){	unsigned long flags;	ohci_vdbg(ohci, "%s: Enabling OHCI Interrupts: %08x\n", __FUNCTION__, ohci_mask);	local_irq_save(flags);	ohci->regs->intrenable |= ohci_mask;	local_irq_restore(flags);}static void ohci_write_intrdisable(struct ohci_hcd *ohci, u32 ohci_mask){	unsigned long flags;	ohci_vdbg(ohci, "%s: Disabling OHCI Interrupts: %08x\n", __FUNCTION__, ohci_mask);	local_irq_save(flags);	ohci->regs->intrenable &= ~ohci_mask;	local_irq_restore(flags);}

⌨️ 快捷键说明

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