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

📄 via-macii.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		 *	won't be called again from send_request!		 *	(need to re-check other cases ...)		 */		/*		 * if the interrupt handler set the need_poll		 * flag, it's hopefully a SRQ poll or re-Talk		 * so we try to send here anyway		 */		if (!need_poll) {			if (console_loglevel == 10)				printk("macii_start: device busy - retry %p state %d status %x!\n", 					req, macii_state,					(uint) via[B] & (ST_MASK|TREQ));			retry_req = req;			/* set ADB status here ? */			restore_flags(flags);			return;		} else {			need_poll = 0;		}	}	/*	 * Another retry pending? (sanity check)	 */	if (retry_req) {		retry_req = NULL;	}	/* Now send it. Be careful though, that first byte of the request */	/* is actually ADB_PACKET; the real data begins at index 1!	  */	/* store command byte */	command_byte = req->data[1];	/* Output mode */	via[ACR] |= SR_OUT;	/* Load data */	via[SR] = req->data[1];	/* set ADB state to 'command' */	via[B] = (via[B] & ~ST_MASK) | ST_CMD;	macii_state = sent_first_byte;	data_index = 2;	restore_flags(flags);}/* * The notorious ADB interrupt handler - does all of the protocol handling,  * except for starting new send operations. Relies heavily on the ADB  * controller sending and receiving data, thereby generating SR interrupts * for us. This means there has to be always activity on the ADB bus, otherwise * the whole process dies and has to be re-kicked by sending TALK requests ... * CUDA-based Macs seem to solve this with the autopoll option, for MacII-type * ADB the problem isn't solved yet (retransmit of the latest active TALK seems * a good choice; either on timeout or on a timer interrupt). * * The basic ADB state machine was left unchanged from the original MacII code * by Alan Cox, which was based on the CUDA driver for PowerMac.  * The syntax of the ADB status lines seems to be totally different on MacII,  * though. MacII uses the states Command -> Even -> Odd -> Even ->...-> Idle for * sending, and Idle -> Even -> Odd -> Even ->...-> Idle for receiving. Start  * and end of a receive packet are signaled by asserting /IRQ on the interrupt * line. Timeouts are signaled by a sequence of 4 0xFF, with /IRQ asserted on  * every other byte. SRQ is probably signaled by 3 or more 0xFF tacked on the  * end of a packet. (Thanks to Guido Koerber for eavesdropping on the ADB  * protocol with a logic analyzer!!) * * Note: As of 21/10/97, the MacII ADB part works including timeout detection * and retransmit (Talk to the last active device). */void macii_interrupt(int irq, void *arg, struct pt_regs *regs){	int x, adbdir;	unsigned long flags;	struct adb_request *req;	last_status = status;	/* prevent races due to SCSI enabling ints */	save_flags(flags); cli();	if (driver_running) {		restore_flags(flags);		return;	}	driver_running = 1;		status = via[B] & (ST_MASK|TREQ);	adbdir = via[ACR] & SR_OUT;	switch (macii_state) {		case idle:			x = via[SR];			first_byte = x;			/* set ADB state = even for first data byte */			via[B] = (via[B] & ~ST_MASK) | ST_EVEN;			reply_buf[0] = first_byte; /* was command_byte?? */			reply_ptr = reply_buf + 1;			reply_len = 1;			prefix_len = 1;			reading_reply = 0;			macii_state = reading;			break;		case awaiting_reply:			/* handshake etc. for II ?? */			x = via[SR];			first_byte = x;			/* set ADB state = even for first data byte */			via[B] = (via[B] & ~ST_MASK) | ST_EVEN;			current_req->reply[0] = first_byte;			reply_ptr = current_req->reply + 1;			reply_len = 1;			prefix_len = 1;			reading_reply = 1;			macii_state = reading;						break;		case sent_first_byte:			req = current_req;			/* maybe we're already done (Talk, or Poll)? */			if (data_index >= req->nbytes) {				/* reset to shift in */				/* If it's a Listen command and we're done, someone's doing weird stuff. */				if (((command_byte & 0x0C) == 0x08)				    && (console_loglevel == 10))					printk("macii_interrupt: listen command with no data: %x!\n", 						command_byte);				/* reset to shift in */				via[ACR] &= ~SR_OUT;				x = via[SR];				/* set ADB state idle - might get SRQ */				via[B] = (via[B] & ~ST_MASK) | ST_IDLE;				req->sent = 1;				if (req->reply_expected) {					macii_state = awaiting_reply;				} else {					req->complete = 1;					current_req = req->next;					if (req->done) (*req->done)(req);					macii_state = idle;					if (current_req || retry_req)						macii_start();					else						macii_retransmit((command_byte & 0xF0) >> 4);				}			} else {				/* SR already set to shift out; send byte */				via[SR] = current_req->data[data_index++];				/* set state to ST_EVEN (first byte was: ST_CMD) */				via[B] = (via[B] & ~ST_MASK) | ST_EVEN;				macii_state = sending;			}			break;		case sending:			req = current_req;			if (data_index >= req->nbytes) {				/* reset to shift in */				via[ACR] &= ~SR_OUT;				x = via[SR];				/* set ADB state idle - might get SRQ */				via[B] = (via[B] & ~ST_MASK) | ST_IDLE;				req->sent = 1;				if (req->reply_expected) {					macii_state = awaiting_reply;				} else {					req->complete = 1;					current_req = req->next;					if (req->done) (*req->done)(req);					macii_state = idle;					if (current_req || retry_req)						macii_start();					else						macii_retransmit((command_byte & 0xF0) >> 4);				}			} else {				via[SR] = req->data[data_index++];				/* invert state bits, toggle ODD/EVEN */				via[B] ^= ST_MASK;			}			break;		case reading:			/* timeout / SRQ handling for II hw */			if( (first_byte == 0xFF && (reply_len-prefix_len)==2 			     && memcmp(reply_ptr-2,"\xFF\xFF",2)==0) || 			    ((reply_len-prefix_len)==3 			     && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0))			{				/*				 * possible timeout (in fact, most probably a 				 * timeout, since SRQ can't be signaled without				 * transfer on the bus).				 * The last three bytes seen were FF, together 				 * with the starting byte (in case we started				 * on 'idle' or 'awaiting_reply') this probably				 * makes four. So this is mostl likely #5!				 * The timeout signal is a pattern 1 0 1 0 0..				 * on /INT, meaning we missed it :-(				 */				x = via[SR];				if (x != 0xFF) printk("macii_interrupt: mistaken timeout/SRQ!\n");				if ((status & TREQ) == (last_status & TREQ)) {					/* Not a timeout. Unsolicited SRQ? weird. */					/* Terminate the SRQ packet and poll */					need_poll = 1;				}				/* There's no packet to get, so reply is blank */				via[B] ^= ST_MASK;				reply_ptr -= (reply_len-prefix_len);				reply_len = prefix_len;				macii_state = read_done;				break;			} /* end timeout / SRQ handling for II hw. */			if((reply_len-prefix_len)>3				&& memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0)			{				/* SRQ tacked on data packet */				/* Terminate the packet (SRQ never ends) */				x = via[SR];				macii_state = read_done;				reply_len -= 3;				reply_ptr -= 3;				need_poll = 1;				/* need to continue; next byte not seen else */			} else {				/* Sanity check */				if (reply_len > 15) reply_len = 0;				/* read byte */				x = via[SR];				*reply_ptr = x;				reply_ptr++;				reply_len++;			}			/* The usual handshake ... */			/*			 * NetBSD hints that the next to last byte 			 * is sent with IRQ !! 			 * Guido found out it's the last one (0x0),			 * but IRQ should be asserted already.			 * Problem with timeout detection: First			 * transition to /IRQ might be second 			 * byte of timeout packet! 			 * Timeouts are signaled by 4x FF.			 */			if (!(status & TREQ) && (x == 0x00)) { /* != 0xFF */				/* invert state bits, toggle ODD/EVEN */				via[B] ^= ST_MASK;				/* adjust packet length */				reply_len--;				reply_ptr--;				macii_state = read_done;			} else {				/* not caught: ST_CMD */				/* required for re-entry 'reading'! */				if ((status & ST_MASK) == ST_IDLE) {					/* (in)sanity check - set even */					via[B] = (via[B] & ~ST_MASK) | ST_EVEN;				} else {					/* invert state bits */					via[B] ^= ST_MASK;				}			}			break;		case read_done:			x = via[SR];			if (reading_reply) {				req = current_req;				req->reply_len = reply_ptr - req->reply;				req->complete = 1;				current_req = req->next;				if (req->done) (*req->done)(req);			} else {				adb_input(reply_buf, reply_ptr - reply_buf,					  regs, 0);			}			/*			 * remember this device ID; it's the latest we got a 			 * reply from!			 */			last_reply = command_byte;			last_active = (command_byte & 0xF0) >> 4;			/* SRQ seen before, initiate poll now */			if (need_poll) {				macii_state = idle;				macii_queue_poll();				need_poll = 0;				break;			}			/* /IRQ seen, so the ADB controller has data for us */			if (!(status & TREQ)) {				/* set ADB state to idle */				via[B] = (via[B] & ~ST_MASK) | ST_IDLE;				macii_state = reading;				reply_buf[0] = command_byte;				reply_ptr = reply_buf + 1;				reply_len = 1;				prefix_len = 1;				reading_reply = 0;			} else {				/* no IRQ, send next packet or wait */				macii_state = idle;				if (current_req)					macii_start();				else					macii_retransmit(last_active);			}			break;		default:		break;	}	/* reset mutex and interrupts */	driver_running = 0;	restore_flags(flags);}

⌨️ 快捷键说明

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