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

📄 hc_isp116x.c

📁 嵌入式USB主控制器ISP1161的驱动编程
💻 C
📖 第 1 页 / 共 4 页
字号:
/*-------------------------------------------------------------------------*//*-------------------------------------------------------------------------* * isp1161 USB HCD for Linux Version 0.9.5 (10/28/2001) *                         Version Tango (05/11/2004) *                         Version Bingo (09/17/2004) * * requires (includes) hc_simple.[hc] simple generic HCD frontend * * Roman Weissgaerber weissg@vienna.at (C) 2001 * * Thanks to Benjamin Herrenschmidt for debugging and the removing of * some bugs. * * Thanks to adsynori, I based my driver on your version : ) * Special thanks to jazzcat, zengyi, haomaomao, sky...  * 				cannot do without you (^V^) * This driver is compatible with Intel Sitsang Evaluation Platform  * with USB HC Controller ISP1161A1, It seems there are still some problem * with ISP1161, maybe you should consider changing your chip if you're  * working with ISP1161. * * See readme for more detailed changelogs : ) * 				fixer: tingwang	 * 					wangting@gmail.com  *-------------------------------------------------------------------------* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * *-------------------------------------------------------------------------*//* V Bingo 09/17/2004 perfect ISOC transfer even under severe system payload *//* V Tango 05/11/2004 ISOC transmission may not stop.(DATA IN) *//* V 0.9.5 10/28/2001 correct toggle on error *//*         inw, outw macros; ISOC support *//* V 0.9  remove some bugs, ISOC still missing *//* V 0.8.1 9/5/2001 mv memcpy of in packet to hc *//* V 0.8 initial release */#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/errno.h>#include <linux/init.h>//#include <linux/smp_lock.h>#include <linux/spinlock.h>#include <linux/list.h>#include <linux/ioport.h>#include <asm/io.h>#include <linux/delay.h>#include <linux/usb.h>#include <linux/stringify.h>#include <asm/system.h>//#include "../core/hcd.h"#include "hcd.h"#include <asm/irq.h>#undef HC_URB_TIMEOUT#define HC_SWITCH_INT#define HC_ENABLE_ISOC#define OHCI_USE_NPS#include "hc_isp116x.h"#include "hc_simple_isp116x.h"//#define DEBUG1static int hc_verbose = 0;#include <linux/time.h>#include <linux/proc_fs.h>#define USE_FAST_ACCESSint actual_len = 0; int is_iso = 0;int global_itl = 0;int global_time = 0;int global_bh_count = 0;int last_i = 0;int force_return_flag = 0;int now_sequence = 0;int itl_reset = 1; 	//this bit is cleared whenever an iso urb finishesint itl_buffer_die = 2;int itl_buffer_count0 = 0;int itl_buffer_count1 = 0;int single_itl = 0;int print_flag = 0;int global_atl_count = 0;int ATLInt_save = 0;int iso_list_map[3] = {-1,-1,-1};int last_HcFmNumber = -1;int last_HcBufferStatus = -1;int miss_flag = 0;int Buffer_History[10];int Buffer_History_p = 0;int ATL_quirk_flag = 0;int ITL0_die_flag = 0;int ITL1_die_flag = 0;int force_return_count = 0;int kernel_panic_count = 0;int last_proc_time_sec = -1;int last_proc_time_usec = -1;int proc_itl_stream = 0;int itl_list_error[5] = {0,0,0,0,0};int work_flag = 0;struct timer_list isp_timer;int timer_switch = 0;int timer_counter = 0;int itl_bandwidth[10];int itl_interval[10];int itl_data_len = 0;int cleanup = 0;int chip_reset = 0;#include "hc_simple_isp116x.c"#include "hc_isp116x_rh.c"#if defined(CONFIG_ARCH_SITSANG)#define HC_DEFAULT_DATA_PORT 0xf4000290#define HC_DEFAULT_CMD_PORT 0xf4000292//#define HC_DEFAULT_WU_PORT 0#define HC_DEFAULT_WU_PORT -1//#define HC_HARDWARE_CONFIG 0//#define HC_HARDWARE_CONFIG (DataBusWidth16 | DownstreamPort15KRSel)#define HC_HARDWARE_CONFIG (DataBusWidth16 | AnalogOCEnable )#else#define HC_DEFAULT_IRQ 74#define HC_DEFAULT_DATA_PORT 0xba00c000#define HC_DEFAULT_CMD_PORT 0xba00c002#define HC_DEFAULT_WU_PORT -1#define HC_HARDWARE_CONFIG (DataBusWidth16 | DownstreamPort15KRSel)#endif#ifndef	SITSANG_USB_HC_IRQ#define SITSANG_USB_HC_IRQ 29#endifstatic int irq = SITSANG_USB_HC_IRQ;static int data_port = HC_DEFAULT_DATA_PORT;static int cmd_port = HC_DEFAULT_CMD_PORT;static int wu_port = HC_DEFAULT_WU_PORT; /* Not used. */MODULE_PARM(hc_verbose,"i");MODULE_PARM_DESC(hc_verbose,"verbose startup messages, default is 1 (yes)");MODULE_PARM(irq,"i");MODULE_PARM_DESC(irq,"IRQ. default " __stringify(HC_DEFAULT_IRQ));MODULE_PARM(data_port,"i");MODULE_PARM_DESC(data_port,"Data port. default " __stringify(HC_DEFAULT_DATA_PORT));MODULE_PARM(cmd_port,"i");MODULE_PARM_DESC(cmd_port,"Command port. default " __stringify(HC_DEFAULT_CMD_PORT));MODULE_PARM(wu_port,"i");MODULE_PARM_DESC(wu_port,"Wakeup port. default " __stringify(HC_DEFAULT_WU_PORT));static int hc_reset (hci_t * );int hc_isp_proc_info (char *, char **, off_t, int, int *, void *);int hc_isp_proc_reset (char *, char **, off_t, int, int *, void *);void hc_renew_chip (unsigned long );static inline void ISP116x_OUTW (int val, int addr){        outw (val, addr);}static inline int ISP116x_INW (int addr){	return inw (addr);}static inline int READ_REG32 (hci_t * hci, int regindex){	hcipriv_t * hp = &hci->hp;	int val16, val;	ISP116x_OUTW (regindex, hp->cmd_port);	ndelay(600);	val16 = ISP116x_INW (hp->data_port);	val = val16 & 0xffff;	ndelay(600);	val16 = ISP116x_INW (hp->data_port);	val += val16 << 16;	return val;}static inline int READ_REG16 (hci_t * hci, int regindex){	hcipriv_t * hp = &hci->hp;	int val = 0;	ISP116x_OUTW (regindex, hp->cmd_port);	ndelay(600);	val = ISP116x_INW (hp->data_port);	ndelay(600);	return val;}static inline void READ_REGn16 (hci_t * hci, int regindex, int length, __u8 * buffer){	hcipriv_t * hp = &hci->hp;	int i;	int val = 0;	ISP116x_OUTW (regindex, hp->cmd_port);	ndelay(600);	for (i = 0; i < length - 1; i += 2) {		val = ISP116x_INW (hp->data_port);		buffer [i] = val;		buffer [i+1] = val >> 8;	}	if (length & 1) {		val = ISP116x_INW (hp->data_port);		buffer [length - 1] = val;	}/*	if (is_iso==1) {		printk (" READ_REGn16: %d :", length);		for (i = 0; i < 16; i++)//		for (i = 0; i < 8; i++)		printk (" %2x", buffer [i]);		printk("\n");	}  */#ifdef DEBUG1	printk (" READ_REGn16: %d :", length);	for (i = 0; i < length; i++)//	for (i = 0; i < 8; i++)		printk (" %2x", buffer [i]);	printk("\n");#endif}static inline void WRITE_REG32 (hci_t * hci, unsigned int value, int regindex){	hcipriv_t * hp = &hci->hp;	ISP116x_OUTW (regindex | 0x80, hp->cmd_port);	ndelay(600);	ISP116x_OUTW (value & 0xffff, hp->data_port);	ndelay(600);	ISP116x_OUTW (value >> 16, hp->data_port);	ndelay(600);}static inline void WRITE_REG16 (hci_t * hci, unsigned int value, int regindex){	hcipriv_t * hp = &hci->hp;	ISP116x_OUTW (regindex | 0x80, hp->cmd_port);	ndelay(600);	ISP116x_OUTW (value, hp->data_port);	ndelay(600);}static inline void WRITE_REG0 (hci_t * hci, int regindex){	hcipriv_t * hp = &hci->hp;	ISP116x_OUTW (regindex | 0x80, hp->cmd_port);	ndelay(600);}static inline void WRITE_REGn16 (hci_t * hci, int regindex, int length, __u8 * buffer){	hcipriv_t * hp = &hci->hp;	int i;	ISP116x_OUTW (regindex | 0x80, hp->cmd_port);	ndelay(600);	for (i = 0; i < length - 1; i += 2) {		ISP116x_OUTW (buffer [i] + (buffer [i+1] << 8), hp->data_port);	}	if (length & 1) {		ISP116x_OUTW (buffer [length - 1], hp->data_port);	}/*	if (is_iso==1) {		printk (" WRITE_REGn16: %d :", length);		for (i = 0; i < length; i++)//		for (i = 0; i < 2; i++)			printk (" %2x", buffer [i]);		printk("\n");	} */}/*-------------------------------------------------------------------------*//* tl functions */static inline void hc_mark_last_trans (hci_t * hci){	hcipriv_t * hp = &hci->hp;	__u8 * ptd = hp->tl;	if (hp->tlp > 0)		*(ptd + hp->tl_last) |= (1 << 3);}static inline void hc_flush_data_cache (hci_t * hci, void * data, int len){}static inline int hc_add_trans (hci_t * hci, int len, void * data,		int toggle, int maxps, int slow, int endpoint, int address, int pid, int format, int type){	hcipriv_t * hp = &hci->hp;	unsigned char last = 0;	__u8 * ptd = hp->tl;		if (hp->units_left < ((len + 8 + 3) & ~0x3)) {		return -1;       	} else {		hp->units_left -= (len + 8 + 3) & ~0x3;	}	ptd += hp->tlp;	hp->tl_last = hp->tlp + 3;       	if (format == 1){        	last = 1;        }	ptd [0] = 0;	ptd [1] = (toggle << 2) | (1 << 3) | (0xf << 4);	ptd [2] = maxps;	ptd [3] = ((maxps >> 8) & 0x3) | (slow << 2) | (last << 3) | (endpoint << 4);	ptd [4] = len;	ptd [5] = ((len >> 8) & 0x3) | (pid << 2);	ptd [6] = address | (format << 7);	ptd [7] = 0;    	if (pid != PID_IN && len) {		if (type==0) {			memcpy (ptd + 8, data, len);		} else {			/* do nothing, because iso packets contains no additional data */			}	}	hp->tlp += ((len + 8 + 3) & ~0x3);	return len;}static inline int hc_parse_trans (hci_t * hci, int * actbytes, void * data,			int * cc, int * toggle, int length){	hcipriv_t * hp = &hci->hp;	int last = 0;	int totbytes;	int pid;	int cp_count;	__u8 *ptd = hp->tl;	*cc = (ptd [1] >> 4) & 0xf;	last = (ptd [3] >> 3) & 0x1;	*actbytes = ((ptd [1] & 0x3) << 8) | ptd [0];	totbytes = ((ptd [5] & 0x3) << 8) | ptd [4];	pid = (ptd [5] >> 2) & 0x3;	if (*actbytes > length)		*actbytes = length;	cp_count = *actbytes;		if (pid == PID_IN && cp_count)		memcpy (data, ptd + 8, cp_count);	*toggle = (ptd [1] >> 2 & 1);	if (*cc > 0 && *cc < 0xE && *cc != 9)		*toggle = !*toggle;	hp->tlp += ((totbytes + 8 + 3) & ~0x3);	return !last;}/*-------------------------------------------------------------------------*/static void hc_start_int (hci_t * hci){#ifdef HC_SWITCH_INT	int mask = OHCI_INTR_MIE | OHCI_INTR_SO | OHCI_INTR_SF;	WRITE_REG32 (hci, mask, HcInterruptEnable);	WRITE_REG32 (hci, mask, HcInterruptStatus);	mask = SOFITLInt | ATLInt | OPR_Reg;	WRITE_REG16 (hci, mask, HcuPInterrupt);	WRITE_REG16 (hci, mask, HcuPInterruptEnable);	WRITE_REG16 (hci, InterruptPinEnable| InterruptPinTrigger| InterruptOutputPolarity| HC_HARDWARE_CONFIG, HcHardwareConfiguration);	//added by wt#endif}static void hc_start_sof_int (hci_t* hci){	int mask = SOFITLInt | ATLInt | OPR_Reg;	WRITE_REG16 (hci, mask, HcuPInterruptEnable);}	static void hc_stop_int (hci_t * hci){#ifdef HC_SWITCH_INT	int mask = OHCI_INTR_MIE | OHCI_INTR_SO;	WRITE_REG32 (hci, mask, HcInterruptEnable);	WRITE_REG32 (hci, mask, HcInterruptStatus);	WRITE_REG16 (hci, 0, HcuPInterrupt); /* maybe need */	WRITE_REG16 (hci, 0, HcuPInterruptEnable);	WRITE_REG16 (hci, HC_HARDWARE_CONFIG, HcHardwareConfiguration);#endif}/*void isp_timeout (unsigned long time_p){	int i;	itl_interval[timer_counter] = (jiffies-time_p);	itl_bandwidth[timer_counter] = itl_data_len;	itl_data_len = 0;	timer_switch = 0;	timer_counter++;	if (timer_counter==10) {		timer_counter = 0;		printk (KERN_DEBUG "itl_data: \n");		for (i=0; i<10; i++) {			printk ("%d\t", itl_bandwidth[i]);		}		printk (KERN_DEBUG "\n");		printk (KERN_DEBUG "itl_interval: \n");		for (i=0; i<10; i++) {

⌨️ 快捷键说明

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