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

📄 sl11.c

📁 Linux2.4.20针对三星公司的s3c2440内核基础上的一些设备驱动代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * sl11_bi/udc.c * * Copyright (c) 2000, 2001, 2002 Lineo * * By:  *      Stuart Lynne <sl@lineo.com>,  *      Tom Rushworth <tbr@lineo.com>,  *      Bruce Balden <balden@lineo.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., 675 Mass Ave, Cambridge, MA 02139, USA. * *//*****************************************************************************/#include <linux/config.h>#include <linux/module.h>#include "../usbd-export.h"#include "../usbd-build.h"#include "../usbd-module.h"MODULE_AUTHOR ("sl@lineo.com, tbr@lineo.com");MODULE_DESCRIPTION ("USB Device SL11 Bus Interface");USBD_MODULE_INFO ("sl11_bi 0.1-alpha");#include <linux/kernel.h>#include <linux/slab.h>#include <linux/interrupt.h>#include <linux/pci.h>#include <linux/init.h>#include <asm/atomic.h>#include <asm/io.h>#include <linux/netdevice.h>#include <asm/irq.h>#include <asm/system.h>#include <asm/types.h>#include <asm/uaccess.h>#include <asm/io.h>#include <linux/delay.h>#include "../usbd.h"#include "../usbd-func.h"#include "../usbd-bus.h"#include "../usbd-inline.h"#include "usbd-bi.h"#include "sl11.h"#include "sl11-info.h"#define MIN(a,b) ((a) < (b) ? (a) : (b))#define MAX(a,b) ((a) > (b) ? (a) : (b))/* * ep_address - endpoint buffer addresses * * 0-3  epNa * 4-7  epNb */static unsigned char ep_address[UDC_MAX_ENDPOINTS * 2] = {	EP_S_BUF, EP_S_BUF, EP_S_BUF, EP_S_BUF,	EP_S_BUF, EP_S_BUF, EP_S_BUF, EP_S_BUF};/* * ep_register - endpoint register addresses * * 0-3  epNa * 4-7  epNb */static unsigned char ep_register[UDC_MAX_ENDPOINTS * 2] = {	EP0_Control, EP1_Control, EP2_Control, EP3_Control,	EP0_Control + 8, EP1_Control + 8, EP2_Control + 8, EP3_Control + 8};static struct usb_device_instance *udc_device;	// required for the interrupt handler/* * ep_sequence - current sequence number for each endpoint */static unsigned char ep_sequence[UDC_MAX_ENDPOINTS] = {	0, 0, 0, 0};/* * ep_next - next ping pong buffer */static unsigned char ep_next[UDC_MAX_ENDPOINTS] = {	0, 0, 0, 0};/* * ep_int_mask - interrupt status register endpoint bit masks */static unsigned char ep_int_mask[UDC_MAX_ENDPOINTS] = {	INT_EP0_DONE, INT_EP1_DONE, INT_EP2_DONE, INT_EP3_DONE};/* * ep_endpoints - map physical endpoints to logical endpoints */static struct usb_endpoint_instance *ep_endpoints[UDC_MAX_ENDPOINTS];// static struct urb ep0_urb;static struct urb *ep0_urb;static unsigned char usb_address;static int udc_saw_sof;static int udc_suspended;static int udc_addressed;static struct tq_struct sl11_tq;extern unsigned int udc_interrupts;unsigned int udc_ticks;/* ********************************************************************************************* */#ifdef CONFIG_X86/** * sl11write_byte - write a byte to the sl11 * @a: sl11 address * @b: byte to write */static __inline__ void sl11write_byte (unsigned char a, unsigned char b){	outb (a, UDC_ADDR);	outb (b, UDC_ADDR + 1);}static __inline__ void _sl11write_byte (unsigned char a, unsigned char b){	printk (KERN_DEBUG "sl11write_byte: Reg: %02x Val: %02x\n", a, b);	outb (a, UDC_ADDR);	outb (b, UDC_ADDR + 1);}/** * sl11write_buffer - write a buffer to the sl11 using auto-increment mode * @a: sl11 address * @b: pointer to buffer to write * @size: number of bytes to write */static __inline__ void sl11write_buffer (unsigned char a, unsigned char *b, unsigned char size){	outb (a, UDC_ADDR);	while (size--) {		outb (*b++, UDC_ADDR + 1);	}}/** * sl11read_byte - read a byte from the sl11 and return * @a: sl11 address */static __inline__ unsigned char sl11read_byte (unsigned char a){	outb (a, UDC_ADDR);	return inb (UDC_ADDR + 1);}/** * sl11read_buffer - fill a buffer from the sl11 using auto-increment mode * @a: sl11 address * @b: pointer to buffer to fill * @size: number of bytes to read */static __inline__ void sl11read_buffer (unsigned char a, unsigned char *b, unsigned char size){	outb (a, UDC_ADDR);	while (size--) {		*b++ = inb (UDC_ADDR + 1);	}}/** * sl11clear - clear sl11 memory * @a: sl11 address * @size: bytes to clear */static void sl11clear (unsigned char a, unsigned char size){	outb (a, UDC_ADDR);	while (size--) {		outb (0, UDC_ADDR + 1);	}}#else#abort SL11 memory mapped IO not implemented#endif/* ********************************************************************************************* *//** * sl11write_epn - write a byte to a sl11 endpoint register * @a: endpoint  * @b: endpoint register * @d: byte to write */static __inline__ void sl11write_epn (unsigned char ep, unsigned char b, unsigned char c){	sl11write_byte (ep_register[ep] + b, c);}static __inline__ void _sl11write_epn (unsigned char ep, unsigned char b, unsigned char c){	printk (KERN_DEBUG "sl11write_epn: Reg: %02x Val: %02x\n", ep_register[ep] + b, c);	_sl11write_byte (ep_register[ep] + b, c);}/** * sl11read_epn - read a byte from a sl11 endpoint register * @a: endpoint  * @b: endpoint register * @d: byte to write */__inline__ unsigned char sl11read_epn (unsigned char ep, unsigned char b){	return sl11read_byte (ep_register[ep] + b);}/* ********************************************************************************************* *//** * sl11_dump */static void sl11_dump (unsigned char a, unsigned char size){	int i;	for (i = 0; i < size; i++) {		if ((i % 8) == 0) {			printk ("\n[%02x]: ", a + i);		}		printk ("%02x ", sl11read_byte (a + i));	}	printk ("\n");}static void sl11_dump_epn (unsigned char ep, char *m){	printk ("ep[%d]: Ctl:%02x Adr:%02x Xfr:%02x Sts:%02x Cnt:%02x Seq:%d%s", ep,		sl11read_epn (ep, EPN_Control),		sl11read_epn (ep, EPN_Address),		sl11read_epn (ep, EPN_XferLen),		sl11read_epn (ep, EPN_Status),		sl11read_epn (ep, EPN_Counter), ep_sequence[ep & 0x3], m);}/** * sl11_probe - initialize * * 0. Issue a reset to CtrlReg * * 1. After reset we typically see: * *          IntStatus       0x40 or 0x60 *          DATASet         0x10  * * 2. We test that IntStatus can be changed to 0x00 by writing 0xff to it. * * 3. If successful clear all chip memory. * **/static int sl11_probe (void){	sl11_dump (0, 64);	printk (KERN_DEBUG "sl11_probe: start\n");	// reset	sl11write_byte (CtrlReg, CTRL_USB_RESET);	udelay (100);		// XXX may not be needed	sl11write_byte (CtrlReg, 0);	sl11_dump (0, 64);	printk (KERN_DEBUG "sl11_probe: RESET\n");	/*	 * XXX	 *	 * If device is present DATASet&CDS_RESERVED will be true.	 *	 * After reset we will see IntStatus & INT_USB_RESET if cable is plugged in.	 *	 */	if (((sl11read_byte (IntStatus) & INT_USB_RESET) != INT_USB_RESET)	    || ((sl11read_byte (DATASet) & 0x10) != 0x10)) {		sl11_dump (0, 64);		printk (KERN_DEBUG "sl11_probe: cannot see " UDC_NAME ", failed initial probe\n");		//udc_regs();		//return -EINVAL;	}	// reset interrupt status	sl11write_byte (IntStatus, 0xff);	if ((sl11read_byte (IntStatus) != 0x00)) {		sl11_dump (0, 64);		printk (KERN_DEBUG "sl11_probe: cannot see " UDC_NAME			", failed interrupt status reset\n");		udc_regs ();		return -EINVAL;	}	// success!	// clear all memory	sl11clear (0, 255);	printk (KERN_DEBUG "sl11_probe: found and setup\n");	//sl11_dump(0, 64);	//udc_regs();	return 0;}/* ********************************************************************************************* *//** * sl11send_data - send packet via endpoint * @ep: logical endpoint number * @bp: pointer to data * @size: bytes to write */static void __inline__ sl11send_data (unsigned char ep, unsigned char *bp, unsigned char size){	// copy data from buffer to chip	if (bp && size) {		sl11write_buffer (ep_address[ep], bp, size);	}	sl11write_epn (ep, EPN_XferLen, size);	// arm	sl11write_epn (ep, EPN_Control,		       EPN_CTRL_ARM | EPN_CTRL_ENABLE | EPN_CTRL_DIRECTION_IN |		       (ep_sequence[ep] ? EPN_CTRL_SEQUENCE : 0)	    );}/** * s111send_done * @ep */static void __inline__ sl11send_done (unsigned ep){	// disarm	sl11write_epn (ep, EPN_Control, EPN_CTRL_ENABLE | EPN_CTRL_DIRECTION_IN);	// flip sequence	ep_sequence[ep] = (~ep_sequence[ep]) & 0x1;}/* ********************************************************************************************* *//** * s111read_init * @ep: endpoint */static void sl11read_init (unsigned char ep, unsigned char size){	// setup packet size	sl11write_epn (ep, EPN_XferLen, size);	// arm	sl11write_epn (ep, EPN_Control, EPN_CTRL_ARM | EPN_CTRL_ENABLE | EPN_CTRL_DIRECTION_OUT);}/** * sl11read_done * @ep: endpoint */static void sl11read_done (unsigned char ep, unsigned char *bp, unsigned char size){	// disarm	sl11write_epn (ep, EPN_Control, EPN_CTRL_ENABLE | EPN_CTRL_DIRECTION_OUT);	// copy data from chip to buffer	sl11read_buffer (ep_address[ep], bp, size);}/* ********************************************************************************************* *//** * sl11_out - process rcv interrupt * * Queue received data. */static void __inline__ sl11_out (unsigned int ep, struct usb_endpoint_instance *endpoint){	int len;	int cnt;	int error = 0;	int adr;	int i;	unsigned char status;	unsigned char ctl;	unsigned int cep;	// loop alternating between A-B register sets looking for ACK in packet status	//	for (i = 0; i < 8; i++) {		cep = ep + (ep_next[ep] ? 4 : 0);		ep_next[ep] = ~ep_next[ep] & 0x1;		status = sl11read_epn (cep, EPN_Status);		//printk(KERN_DEBUG"[%d] out[%d]: seq: %d next: %d sts: %02x\n", udc_interrupts, ep, ep_sequence[ep], ep_next[ep], status);		if (!(status & EPN_PSTS_ACK)) {			continue;	//return;		}		// check packet status bits for errors		ctl = sl11read_epn (cep, EPN_Control);		len = sl11read_epn (cep, EPN_XferLen);		cnt = sl11read_epn (cep, EPN_Counter);		adr = sl11read_epn (cep, EPN_Address);		//printk(KERN_DEBUG"[%d] out[%d]: sts: %02x len: %d cnt: %d adr: %02x seq: %02x bytes: %0d\n", 		//        udc_interrupts, cep, status, len, cnt, adr, ep_sequence[ep], len - cnt);		//sl11_dump_epn(ep, " ");		//sl11_dump_epn(ep + 4, "\n");		len -= cnt;		if (status &		    (EPN_PSTS_ERROR | EPN_PSTS_TIMEOUT | EPN_PSTS_SETUP | EPN_PSTS_OVERFLOW)) {			printk (KERN_DEBUG "sl11_out[%d]: ERROR\n", cep);			error = 1;

⌨️ 快捷键说明

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