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

📄 sl11.c

📁 Linux2.4.20针对三星公司的s3c2440内核基础上的一些设备驱动代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		}		if (((status & EPN_PSTS_SEQUENCE) && ep_sequence[ep]) ||		    (!(status & EPN_PSTS_SEQUENCE) && !ep_sequence[ep])) {			ep_sequence[ep] = (~ep_sequence[ep]) & 0x1;		} else {			// sequence error			printk (KERN_DEBUG "sl11_out[%d]: SEQ\n", cep);			error = 1;		}		if (endpoint->rcv_urb && len) {			sl11read_buffer (adr,					 endpoint->rcv_urb->buffer +					 endpoint->rcv_urb->actual_length, len);		}		// re-arm		sl11write_epn (cep, EPN_Status, 0);		sl11write_epn (cep, EPN_Counter, 0);		sl11write_epn (cep, EPN_XferLen, endpoint->rcv_packetSize);		//sl11_dump_epn(ep, "\n");		sl11write_epn (cep, EPN_Control, ctl | EPN_CTRL_ARM);		if (endpoint->endpoint_address) {			//printk(KERN_DEBUG"sl11_out: receive len: %d\n", len);			usbd_rcv_complete_irq (endpoint, len, 0);		} else {			printk (KERN_DEBUG "sl11_out: cannot receive no endpoint address len: %d\n",				len);		}	}}/* ********************************************************************************************* *//** * sl11_start - start transmit * @ep: */static void __inline__ sl11_start (unsigned int ep, struct usb_endpoint_instance *endpoint,				   int restart){	//printk(KERN_DEBUG"sl11_start: tx_urb: %p sent: %d\n", endpoint->tx_urb, endpoint->sent);	if (endpoint->tx_urb) {		struct urb *urb = endpoint->tx_urb;		//printk(KERN_DEBUG"sl11_start: length: %d\n", endpoint->tx_urb->actual_length);		if ((urb->actual_length - endpoint->sent) > 0) {			endpoint->last =			    MIN (urb->actual_length - endpoint->sent, endpoint->tx_packetSize);			sl11send_data (ep, urb->buffer + endpoint->sent, endpoint->last);		} else {			// XXX ZLP			endpoint->last = 0;			sl11send_data (ep, urb->buffer + endpoint->sent, 0);		}	}}/** * sl11_in - process tx interrupt * @ep: * @endpoint: * * Determine status of last data sent, queue new data. */static __inline__ void sl11_in (unsigned int ep, struct usb_endpoint_instance *endpoint){	int restart = 0;	unsigned char status;	restart = 0;	//printk(KERN_DEBUG"in[%d]: seq: %d next: %d\n", ep, ep_sequence[ep], ep_next[ep]);	// check packet status bits for errors	status = sl11read_epn (ep, EPN_Status);	if (status & (EPN_PSTS_ERROR | EPN_PSTS_TIMEOUT | EPN_PSTS_SETUP | EPN_PSTS_OVERFLOW)) {		printk (KERN_DEBUG "sl11_in[%d]: ERROR status: %0x\n", ep, status);		restart = 1;	} else {		// flip sequence		ep_sequence[ep] = (~ep_sequence[ep]) & 0x1;	}	usbd_tx_complete_irq (endpoint, restart);	sl11_start (ep, endpoint, restart);}/* ********************************************************************************************* */static void sl11_ep0_setaddress (struct usb_endpoint_instance *endpoint){	//printk(KERN_DEBUG"sl11_ep0: finished set address: %d\n", usb_address);	sl11write_byte (USBAdd, usb_address);	udc_addressed = usb_address;	usb_address = 0;	// send ack	sl11write_epn (0, EPN_XferLen, endpoint->rcv_packetSize);	sl11write_epn (0, EPN_Control, EPN_CTRL_ENABLE | EPN_CTRL_ARM);	printk ("\n");	sl11_dump_epn (0, "\n");}static void sl11_ep0_ending (struct usb_endpoint_instance *endpoint){	//ep_sequence[0] = ~ep_sequence[0];	if (endpoint->tx_urb) {		//printk(KERN_DEBUG"sl11_ep0: continue IN actual: %d sent: %d last: %d seq: %d\n", 		//        endpoint->tx_urb->actual_length, endpoint->sent, endpoint->last, ep_sequence[0]);		sl11_in (0, endpoint);	}	if (endpoint->tx_urb) {		//printk(KERN_DEBUG"sl11_ep0: still sending\n");		return;	}	//printk(KERN_DEBUG"sl11_ep0: finished sending\n");	// send ack	sl11write_epn (0, EPN_XferLen, endpoint->rcv_packetSize);	sl11write_epn (0, EPN_Control, EPN_CTRL_ENABLE | EPN_CTRL_ARM);}static void sl11_ep0_receiving (struct usb_endpoint_instance *endpoint){	// XXX check sequence	//ep_sequence[ep] = ~ep_sequence[ep];	// are we trying to read data?	if (endpoint->rcv_urb) {		// ok, handle incoming data		sl11_out (0, endpoint);		// more to send?		if (endpoint->rcv_urb) {			return;		}		// send ack		sl11write_epn (0, EPN_XferLen, 0);		sl11write_epn (0, EPN_Control, EPN_CTRL_ENABLE | EPN_CTRL_ARM);		return;	}	//printk(KERN_DEBUG"sl11_ep0: received ACK\n");	sl11write_epn (0, EPN_XferLen, endpoint->rcv_packetSize);	sl11write_epn (0, EPN_Control, EPN_CTRL_ENABLE | EPN_CTRL_ARM);	// stall if we where not waiting for data	//udc_stall_ep(0);}/** * sl11_ep0 - process an endpoint 0 interrupt * * Read and process a setup packet */static void sl11_ep0 (struct usb_endpoint_instance *endpoint){	unsigned char control;	unsigned char status;	unsigned char *cp;	//sl11_dump_epn(0, "\n");	// delayed set address, cannot set until we have received IN	if (usb_address) {		sl11_ep0_setaddress (endpoint);		return;	}	// are we sending a reply	control = sl11read_epn (0, EPN_Control);	if (control & EPN_CTRL_DIRECTION_IN) {		sl11_ep0_ending (endpoint);		return;	}	status = sl11read_epn (0, EPN_Status);	// is the host sending data?	if (!(status & EPN_PSTS_SETUP)) {		sl11_ep0_receiving (endpoint);		return;	}	// check if host changed it's mind	if (endpoint->tx_urb) {		endpoint->tx_urb = NULL;		endpoint->last = endpoint->sent = 0;		printk (KERN_DEBUG "sl11_ep0: host cancelled tx\n");	}	if (endpoint->rcv_urb) {		endpoint->rcv_urb = NULL;		ep0_urb->actual_length = 0;		printk (KERN_DEBUG "sl11_ep0: host cancelled rcv\n");	}	// read setup packet	//len = sl11read_epn(0, EPN_XferLen);	//printk(KERN_DEBUG"sl11_ep0: reading setup\n");	sl11read_buffer (ep_address[0], (unsigned char *) &ep0_urb->device_request, 8);	//sl11_dump(0, 255);	cp = (unsigned char *) &ep0_urb->device_request;	//printk(KERN_DEBUG"setup: %02x %02x %02x %02x %02x %02x %02x %02x\n",	//        cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);	// process setup packet	if (usbd_recv_setup (ep0_urb)) {		printk (KERN_DEBUG "sl11_ep0: setup failed\n");		//sl11write_epn(0, )		//udc_stall_ep(0);		return;	}	//sl11write_epn(0, EPN_XferLen, 0);	//sl11write_epn(0, EPN_Control, EPN_CTRL_SEQUENCE | EPN_CTRL_DIRECTION_IN | EPN_CTRL_ENABLE | EPN_CTRL_ARM);	//return; // XXX	// check data direction	if ((ep0_urb->device_request.bmRequestType & USB_REQ_DIRECTION_MASK) == USB_REQ_HOST2DEVICE) {		// should we setup to receive data		if (le16_to_cpu (ep0_urb->device_request.wLength)) {			//printk(KERN_DEBUG"sl11_ep0: read data %d\n",le16_to_cpu(ep0_urb->device_request.wLength));			endpoint->rcv_urb = ep0_urb;			endpoint->rcv_urb->actual_length = 0;			sl11_out (0, endpoint);			return;		}		//printk(KERN_DEBUG"sl11_ep0: send ack %d\n",le16_to_cpu(ep0_urb->device_request.wLength));		// should be finished, send ack		sl11write_epn (0, EPN_XferLen, 0);		sl11write_epn (0, EPN_Control,			       EPN_CTRL_SEQUENCE | EPN_CTRL_DIRECTION_IN | EPN_CTRL_ENABLE |			       EPN_CTRL_ARM);		return;	}	// we should be sending data back	//printk(KERN_DEBUG"sl11_ep0: send data: %d\n", le16_to_cpu(ep0_urb->device_request.wLength));	// verify that we have non-zero request length	if (!le16_to_cpu (ep0_urb->device_request.wLength)) {		udc_stall_ep (0);		return;	}	// verify that we have non-zero length response	if (!ep0_urb->actual_length) {		udc_stall_ep (0);		return;	}	// start sending	//printk(KERN_DEBUG"sl11_ep0: start sending\n");	endpoint->tx_urb = ep0_urb;	endpoint->sent = 0;	endpoint->last = 0;	ep_sequence[0] = 1;	sl11_start (0, endpoint, 0);}/* ********************************************************************************************* *//** * sl11_int_hndlr - interrupt handler * */static void sl11_int_hndlr (int irq, void *dev_id, struct pt_regs *regs){	int i;	unsigned char status;	int ep;	udc_interrupts++;	// loop while interrupt status register is non-zero	for (i = 0; (i < 10) && (status = sl11read_byte (IntStatus)); i++) {		//if ((status & ~INT_SOF_RECEIVED)) {		//    printk(KERN_DEBUG"[%d] %02x\n", udc_interrupts, status);		//}		// Common interrupts - Endpoint done		for (ep = 1; ep < UDC_MAX_ENDPOINTS; ep++) {			struct usb_endpoint_instance *endpoint;			if ((status & ep_int_mask[ep]) && (endpoint = ep_endpoints[ep])) {				// transmit on other than endpoint zero				if (endpoint->endpoint_address & IN) {					endpoint->tx_interrupts++;					sl11_in (ep, endpoint);				}				// receive on other than endpoint zero				else {					endpoint->rcv_interrupts++;					sl11_out (ep, endpoint);				}			}		}		// uncommon interrupts		if (status & (INT_USB_RESET | INT_EP0_DONE | INT_DMA_DONE | INT_SOF_RECEIVED)) {			// Reset			if (status & INT_USB_RESET) {				printk (KERN_DEBUG "sl11_int_hndlr: RESET: %02x\n", status);				udc_suspended = 0;				usbd_device_event (udc_device, DEVICE_RESET, 0);			}			// endpoint zero			if ((status & INT_EP0_DONE)) {				struct usb_endpoint_instance *endpoint;				endpoint = ep_endpoints[0];				endpoint->ep0_interrupts++;				sl11_ep0 (endpoint);			}			// DMA done			if (status & INT_DMA_DONE) {				printk (KERN_DEBUG "sl11_int_hndlr: DMA: %02x\n", status);			}			// SOF frame			if (status & INT_SOF_RECEIVED) {				udc_saw_sof = 1;				if (udc_suspended) {					udc_suspended = 0;					usbd_device_event (udc_device, DEVICE_BUS_ACTIVITY, 0);					printk (KERN_DEBUG "sl11_tick: RESUMED\n");				}			}		}		// clear all available status bits		sl11write_byte (IntStatus, status);	}}/* ********************************************************************************************* *//** * sl11_tick - clock timer task  * @data: * * Run from global clock tick to check if we are suspended. */static void sl11_tick (void *data){	udc_ticks++;	// is driver active	if (data) {		// if not suspended check if we should suspend		if (udc_addressed && !udc_suspended) {			int saw_sof = *((int *) data);			if (!saw_sof) {				// XXX				//				usbd_device_event (udc_device, DEVICE_BUS_INACTIVE, 0);				udc_suspended = 1;				printk (KERN_DEBUG "sl11_tick: SUSPENDED\n");			}			*(int *) data = 0;		}		// re-queue task		queue_task (&sl11_tq, &tq_timer);	} else {		printk (KERN_DEBUG "sl11_tick: not restarting\n");	}}/* ********************************************************************************************* *//* * Start of public functions. *//** * udc_start_in_irq - start transmit * @eendpoint: endpoint instance * * Called by bus interface driver to see if we need to start a data transmission. */void udc_start_in_irq (struct usb_endpoint_instance *endpoint){	sl11_start (endpoint->endpoint_address & 0xf, endpoint, 0);}/** * udc_stall_ep - stall endpoint * @ep: physical endpoint * * Stall the endpoint. */void udc_stall_ep (unsigned int ep){	unsigned char status;	if (ep < UDC_MAX_ENDPOINTS) {		status = sl11read_epn (ep, EPN_Control);		sl11write_epn (ep, EPN_Control, status | EPN_CTRL_SENDSTALL);		udelay (10);	// XXX		sl11write_epn (ep, EPN_Control, status);	}}/** * udc_reset_ep - reset endpoint * @ep: physical endpoint * reset the endpoint. * * returns : 0 if ok, -1 otherwise */void udc_reset_ep (unsigned int ep){	if (ep < UDC_MAX_ENDPOINTS) {		ep_sequence[ep] = 0;	}	printk (KERN_DEBUG "udc_reset_ep[%d]:\n", ep);	if (!ep) {		if (udc_addressed) {			printk (KERN_DEBUG "udc_reset_ep[%d]: reseting address\n", ep);			usb_address = 0;			udc_addressed = 0;			sl11write_byte (USBAdd, 0);			// reset UDC			sl11write_byte (CtrlReg, CTRL_USB_RESET);			udelay (100);	// XXX may not be needed			sl11write_byte (CtrlReg, 0);			// enable UDC			sl11write_byte (CtrlReg, CTRL_USB_ENABLE);		}		// arm EP0		sl11write_epn (0, EPN_Control,			       EPN_CTRL_ARM | EPN_CTRL_ENABLE | EPN_CTRL_DIRECTION_OUT);		sl11_dump_epn (ep + 0, " ");		sl11_dump_epn (ep + 4, "\n");

⌨️ 快捷键说明

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