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

📄 via-maciisi.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	if (maciisi_state == idle)	{		i = maciisi_start();		if(i != 0)		{			local_irq_restore(flags);			return i;		}	}	else	{#ifdef DEBUG_MACIISI_ADB		printk(KERN_DEBUG "maciisi_write: would start, but state is %d\n", maciisi_state);#endif		local_irq_restore(flags);		return -EBUSY;	}	local_irq_restore(flags);	return 0;}static intmaciisi_start(void){	struct adb_request* req;	int status;#ifdef DEBUG_MACIISI_ADB	status = via[B] & (TIP | TREQ);	printk(KERN_DEBUG "maciisi_start called, state=%d, status=%x, ifr=%x\n", maciisi_state, status, via[IFR]);#endif	if (maciisi_state != idle) {		/* shouldn't happen */		printk(KERN_ERR "maciisi_start: maciisi_start called when driver busy!\n");		return -EBUSY;	}	req = current_req;	if (req == NULL)		return -EINVAL;	status = via[B] & (TIP|TREQ);	if (!(status & TREQ)) {#ifdef DEBUG_MACIISI_ADB		printk(KERN_DEBUG "maciisi_start: bus busy - aborting\n");#endif		return -EBUSY;	}	/* Okay, send */#ifdef DEBUG_MACIISI_ADB	printk(KERN_DEBUG "maciisi_start: sending\n");#endif	/* Set state to active */	via[B] |= TIP;	/* ACK off */	via[B] &= ~TACK;	/* Delay */	udelay(ADB_DELAY);	/* Shift out and send */	via[ACR] |= SR_OUT;	via[SR] = req->data[0];	data_index = 1;	/* ACK on */	via[B] |= TACK;	maciisi_state = sending;	return 0;}voidmaciisi_poll(void){	unsigned long flags;	local_irq_save(flags);	if (via[IFR] & SR_INT) {		maciisi_interrupt(0, NULL);	}	else /* avoid calling this function too quickly in a loop */		udelay(ADB_DELAY);	local_irq_restore(flags);}/* Shift register interrupt - this is *supposed* to mean that the   register is either full or empty. In practice, I have no idea what   it means :( */static irqreturn_tmaciisi_interrupt(int irq, void* arg){	int status;	struct adb_request *req;#ifdef DEBUG_MACIISI_ADB	static int dump_reply = 0;#endif	int i;	unsigned long flags;	local_irq_save(flags);	status = via[B] & (TIP|TREQ);#ifdef DEBUG_MACIISI_ADB	printk(KERN_DEBUG "state %d status %x ifr %x\n", maciisi_state, status, via[IFR]);#endif	if (!(via[IFR] & SR_INT)) {		/* Shouldn't happen, we hope */		printk(KERN_ERR "maciisi_interrupt: called without interrupt flag set\n");		local_irq_restore(flags);		return IRQ_NONE;	}	/* Clear the interrupt */	/* via[IFR] = SR_INT; */ switch_start:	switch (maciisi_state) {	case idle:		if (status & TIP)			printk(KERN_ERR "maciisi_interrupt: state is idle but TIP asserted!\n");		if(!reading_reply)			udelay(ADB_DELAY);		/* Shift in */		via[ACR] &= ~SR_OUT; 		/* Signal start of frame */		via[B] |= TIP;		/* Clear the interrupt (throw this value on the floor, it's useless) */		tmp = via[SR];		/* ACK adb chip, high-low */		via[B] |= TACK;		udelay(ADB_DELAY);		via[B] &= ~TACK;		reply_len = 0;		maciisi_state = reading;		if (reading_reply) {			reply_ptr = current_req->reply;		} else {			reply_ptr = maciisi_rbuf;		}		break;	case sending:		/* via[SR]; */		/* Set ACK off */		via[B] &= ~TACK;		req = current_req;		if (!(status & TREQ)) {			/* collision */			printk(KERN_ERR "maciisi_interrupt: send collision\n");			/* Set idle and input */			via[ACR] &= ~SR_OUT;			tmp = via[SR];			via[B] &= ~TIP;			/* Must re-send */			reading_reply = 0;			reply_len = 0;			maciisi_state = idle;			udelay(ADB_DELAY);			/* process this now, because the IFR has been cleared */			goto switch_start;		}		udelay(ADB_DELAY);		if (data_index >= req->nbytes) {			/* Sent the whole packet, put the bus back in idle state */			/* Shift in, we are about to read a reply (hopefully) */			via[ACR] &= ~SR_OUT;			tmp = via[SR];			/* End of frame */			via[B] &= ~TIP;			req->sent = 1;			maciisi_state = idle;			if (req->reply_expected) {				/* Note: only set this once we've                                   successfully sent the packet */				reading_reply = 1;			} else {				current_req = req->next;				if (req->done)					(*req->done)(req);				/* Do any queued requests now */				i = maciisi_start();				if(i == 0 && need_sync) {					/* Packet needs to be synced */					maciisi_sync(current_req);				}				if(i != -EBUSY)					need_sync = 0;			}		} else {			/* Sending more stuff */			/* Shift out */			via[ACR] |= SR_OUT;			/* Write */			via[SR] = req->data[data_index++];			/* Signal 'byte ready' */			via[B] |= TACK;		}		break;	case reading:		/* Shift in */		/* via[ACR] &= ~SR_OUT; */ /* Not in 2.2 */		if (reply_len++ > 16) {			printk(KERN_ERR "maciisi_interrupt: reply too long, aborting read\n");			via[B] |= TACK;			udelay(ADB_DELAY);			via[B] &= ~(TACK|TIP);			maciisi_state = idle;			i = maciisi_start();			if(i == 0 && need_sync) {				/* Packet needs to be synced */				maciisi_sync(current_req);			}			if(i != -EBUSY)				need_sync = 0;			break;		}		/* Read data */		*reply_ptr++ = via[SR];		status = via[B] & (TIP|TREQ);		/* ACK on/off */		via[B] |= TACK;		udelay(ADB_DELAY);		via[B] &= ~TACK;			if (!(status & TREQ))			break; /* more stuff to deal with */				/* end of frame */		via[B] &= ~TIP;		tmp = via[SR]; /* That's what happens in 2.2 */		udelay(ADB_DELAY); /* Give controller time to recover */		/* end of packet, deal with it */		if (reading_reply) {			req = current_req;			req->reply_len = reply_ptr - req->reply;			if (req->data[0] == ADB_PACKET) {				/* Have to adjust the reply from ADB commands */				if (req->reply_len <= 2 || (req->reply[1] & 2) != 0) {					/* the 0x2 bit indicates no response */					req->reply_len = 0;				} else {					/* leave just the command and result bytes in the reply */					req->reply_len -= 2;					memmove(req->reply, req->reply + 2, req->reply_len);				}			}#ifdef DEBUG_MACIISI_ADB			if (dump_reply) {				int i;				printk(KERN_DEBUG "maciisi_interrupt: reply is ");				for (i = 0; i < req->reply_len; ++i)					printk(" %.2x", req->reply[i]);				printk("\n");			}#endif			req->complete = 1;			current_req = req->next;			if (req->done)				(*req->done)(req);			/* Obviously, we got it */			reading_reply = 0;		} else {			maciisi_input(maciisi_rbuf, reply_ptr - maciisi_rbuf);		}		maciisi_state = idle;		status = via[B] & (TIP|TREQ);		if (!(status & TREQ)) {			/* Timeout?! More likely, another packet coming in already */#ifdef DEBUG_MACIISI_ADB			printk(KERN_DEBUG "extra data after packet: status %x ifr %x\n",			       status, via[IFR]);#endif#if 0			udelay(ADB_DELAY);			via[B] |= TIP;			maciisi_state = reading;			reading_reply = 0;			reply_ptr = maciisi_rbuf;#else			/* Process the packet now */			reading_reply = 0;			goto switch_start;#endif			/* We used to do this... but the controller might actually have data for us */			/* maciisi_stfu(); */		}		else {			/* Do any queued requests now if possible */			i = maciisi_start();			if(i == 0 && need_sync) {				/* Packet needs to be synced */				maciisi_sync(current_req);			}			if(i != -EBUSY)				need_sync = 0;		}		break;	default:		printk("maciisi_interrupt: unknown maciisi_state %d?\n", maciisi_state);	}	local_irq_restore(flags);	return IRQ_HANDLED;}static voidmaciisi_input(unsigned char *buf, int nb){#ifdef DEBUG_MACIISI_ADB    int i;#endif    switch (buf[0]) {    case ADB_PACKET:	    adb_input(buf+2, nb-2, buf[1] & 0x40);	    break;    default:#ifdef DEBUG_MACIISI_ADB	    printk(KERN_DEBUG "data from IIsi ADB (%d bytes):", nb);	    for (i = 0; i < nb; ++i)		    printk(" %.2x", buf[i]);	    printk("\n");#endif	    break;    }}

⌨️ 快捷键说明

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