| /* | 
 |  * Device driver for the IIsi-style ADB on some Mac LC and II-class machines | 
 |  * | 
 |  * Based on via-cuda.c and via-macii.c, as well as the original | 
 |  * adb-bus.c, which in turn is somewhat influenced by (but uses no | 
 |  * code from) the NetBSD HWDIRECT ADB code.  Original IIsi driver work | 
 |  * was done by Robert Thompson and integrated into the old style | 
 |  * driver by Michael Schmitz. | 
 |  * | 
 |  * Original sources (c) Alan Cox, Paul Mackerras, and others. | 
 |  * | 
 |  * Rewritten for Unified ADB by David Huggins-Daines <dhd@debian.org> | 
 |  *  | 
 |  * 7/13/2000- extensive changes by Andrew McPherson <andrew@macduff.dhs.org> | 
 |  * Works about 30% of the time now. | 
 |  */ | 
 |  | 
 | #include <linux/types.h> | 
 | #include <linux/errno.h> | 
 | #include <linux/kernel.h> | 
 | #include <linux/sched.h> | 
 | #include <linux/adb.h> | 
 | #include <linux/cuda.h> | 
 | #include <linux/delay.h> | 
 | #include <linux/interrupt.h> | 
 | #include <asm/macintosh.h> | 
 | #include <asm/macints.h> | 
 | #include <asm/machw.h> | 
 | #include <asm/mac_via.h> | 
 |  | 
 | static volatile unsigned char *via; | 
 |  | 
 | /* VIA registers - spaced 0x200 bytes apart - only the ones we actually use */ | 
 | #define RS		0x200		/* skip between registers */ | 
 | #define B		0		/* B-side data */ | 
 | #define A		RS		/* A-side data */ | 
 | #define DIRB		(2*RS)		/* B-side direction (1=output) */ | 
 | #define DIRA		(3*RS)		/* A-side direction (1=output) */ | 
 | #define SR		(10*RS)		/* Shift register */ | 
 | #define ACR		(11*RS)		/* Auxiliary control register */ | 
 | #define IFR		(13*RS)		/* Interrupt flag register */ | 
 | #define IER		(14*RS)		/* Interrupt enable register */ | 
 |  | 
 | /* Bits in B data register: all active low */ | 
 | #define TREQ		0x08		/* Transfer request (input) */ | 
 | #define TACK		0x10		/* Transfer acknowledge (output) */ | 
 | #define TIP		0x20		/* Transfer in progress (output) */ | 
 | #define ST_MASK		0x30		/* mask for selecting ADB state bits */ | 
 |  | 
 | /* Bits in ACR */ | 
 | #define SR_CTRL		0x1c		/* Shift register control bits */ | 
 | #define SR_EXT		0x0c		/* Shift on external clock */ | 
 | #define SR_OUT		0x10		/* Shift out if 1 */ | 
 |  | 
 | /* Bits in IFR and IER */ | 
 | #define IER_SET		0x80		/* set bits in IER */ | 
 | #define IER_CLR		0		/* clear bits in IER */ | 
 | #define SR_INT		0x04		/* Shift register full/empty */ | 
 | #define SR_DATA		0x08		/* Shift register data */ | 
 | #define SR_CLOCK	0x10		/* Shift register clock */ | 
 |  | 
 | #define ADB_DELAY 150 | 
 |  | 
 | #undef DEBUG_MACIISI_ADB | 
 |  | 
 | static struct adb_request* current_req = NULL; | 
 | static struct adb_request* last_req = NULL; | 
 | static unsigned char maciisi_rbuf[16]; | 
 | static unsigned char *reply_ptr = NULL; | 
 | static int data_index; | 
 | static int reading_reply; | 
 | static int reply_len; | 
 | static int tmp; | 
 | static int need_sync; | 
 |  | 
 | static enum maciisi_state { | 
 |     idle, | 
 |     sending, | 
 |     reading, | 
 | } maciisi_state; | 
 |  | 
 | static int maciisi_probe(void); | 
 | static int maciisi_init(void); | 
 | static int maciisi_send_request(struct adb_request* req, int sync); | 
 | static void maciisi_sync(struct adb_request *req); | 
 | static int maciisi_write(struct adb_request* req); | 
 | static irqreturn_t maciisi_interrupt(int irq, void* arg, struct pt_regs* regs); | 
 | static void maciisi_input(unsigned char *buf, int nb, struct pt_regs *regs); | 
 | static int maciisi_init_via(void); | 
 | static void maciisi_poll(void); | 
 | static int maciisi_start(void); | 
 |  | 
 | struct adb_driver via_maciisi_driver = { | 
 | 	"Mac IIsi", | 
 | 	maciisi_probe, | 
 | 	maciisi_init, | 
 | 	maciisi_send_request, | 
 | 	NULL, /* maciisi_adb_autopoll, */ | 
 | 	maciisi_poll, | 
 | 	NULL /* maciisi_reset_adb_bus */ | 
 | }; | 
 |  | 
 | static int | 
 | maciisi_probe(void) | 
 | { | 
 | 	if (macintosh_config->adb_type != MAC_ADB_IISI) | 
 | 		return -ENODEV; | 
 |  | 
 | 	via = via1; | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int | 
 | maciisi_init(void) | 
 | { | 
 | 	int err; | 
 |  | 
 | 	if (via == NULL) | 
 | 		return -ENODEV; | 
 |  | 
 | 	if ((err = maciisi_init_via())) { | 
 | 		printk(KERN_ERR "maciisi_init: maciisi_init_via() failed, code %d\n", err); | 
 | 		via = NULL; | 
 | 		return err; | 
 | 	} | 
 |  | 
 | 	if (request_irq(IRQ_MAC_ADB, maciisi_interrupt, IRQ_FLG_LOCK | IRQ_FLG_FAST,  | 
 | 			"ADB", maciisi_interrupt)) { | 
 | 		printk(KERN_ERR "maciisi_init: can't get irq %d\n", IRQ_MAC_ADB); | 
 | 		return -EAGAIN; | 
 | 	} | 
 |  | 
 | 	printk("adb: Mac IIsi driver v0.2 for Unified ADB.\n"); | 
 | 	return 0; | 
 | } | 
 |  | 
 | /* Flush data from the ADB controller */ | 
 | static void | 
 | maciisi_stfu(void) | 
 | { | 
 | 	int status = via[B] & (TIP|TREQ); | 
 |  | 
 | 	if (status & TREQ) { | 
 | #ifdef DEBUG_MACIISI_ADB | 
 | 		printk (KERN_DEBUG "maciisi_stfu called with TREQ high!\n"); | 
 | #endif | 
 | 		return; | 
 | 	} | 
 | 	 | 
 | 	udelay(ADB_DELAY); | 
 | 	via[ACR] &= ~SR_OUT; | 
 | 	via[IER] = IER_CLR | SR_INT; | 
 |  | 
 | 	udelay(ADB_DELAY); | 
 |  | 
 | 	status = via[B] & (TIP|TREQ); | 
 |  | 
 | 	if (!(status & TREQ)) | 
 | 	{ | 
 | 		via[B] |= TIP; | 
 |  | 
 | 		while(1) | 
 | 		{ | 
 | 			int poll_timeout = ADB_DELAY * 5; | 
 | 			/* Poll for SR interrupt */ | 
 | 			while (!(via[IFR] & SR_INT) && poll_timeout-- > 0) | 
 | 				status = via[B] & (TIP|TREQ); | 
 |  | 
 | 			tmp = via[SR]; /* Clear shift register */ | 
 | #ifdef DEBUG_MACIISI_ADB | 
 | 			printk(KERN_DEBUG "maciisi_stfu: status %x timeout %d data %x\n", | 
 | 			       status, poll_timeout, tmp); | 
 | #endif	 | 
 | 			if(via[B] & TREQ) | 
 | 				break; | 
 | 	 | 
 | 			/* ACK on-off */ | 
 | 			via[B] |= TACK; | 
 | 			udelay(ADB_DELAY); | 
 | 			via[B] &= ~TACK; | 
 | 		} | 
 |  | 
 | 		/* end frame */ | 
 | 		via[B] &= ~TIP; | 
 | 		udelay(ADB_DELAY); | 
 | 	} | 
 |  | 
 | 	via[IER] = IER_SET | SR_INT;	 | 
 | } | 
 |  | 
 | /* All specifically VIA-related initialization goes here */ | 
 | static int | 
 | maciisi_init_via(void) | 
 | { | 
 | 	int	i; | 
 | 	 | 
 | 	/* Set the lines up. We want TREQ as input TACK|TIP as output */ | 
 | 	via[DIRB] = (via[DIRB] | TACK | TIP) & ~TREQ; | 
 | 	/* Shift register on input */ | 
 | 	via[ACR]  = (via[ACR] & ~SR_CTRL) | SR_EXT; | 
 | #ifdef DEBUG_MACIISI_ADB | 
 | 	printk(KERN_DEBUG "maciisi_init_via: initial status %x\n", via[B] & (TIP|TREQ)); | 
 | #endif | 
 | 	/* Wipe any pending data and int */ | 
 | 	tmp = via[SR]; | 
 | 	/* Enable keyboard interrupts */ | 
 | 	via[IER] = IER_SET | SR_INT; | 
 | 	/* Set initial state: idle */ | 
 | 	via[B] &= ~(TACK|TIP); | 
 | 	/* Clear interrupt bit */ | 
 | 	via[IFR] = SR_INT; | 
 |  | 
 | 	for(i = 0; i < 60; i++) { | 
 | 		udelay(ADB_DELAY); | 
 | 		maciisi_stfu(); | 
 | 		udelay(ADB_DELAY); | 
 | 		if(via[B] & TREQ) | 
 | 			break; | 
 | 	} | 
 | 	if (i == 60) | 
 | 		printk(KERN_ERR "maciisi_init_via: bus jam?\n"); | 
 |  | 
 | 	maciisi_state = idle; | 
 | 	need_sync = 0; | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | /* Send a request, possibly waiting for a reply */ | 
 | static int | 
 | maciisi_send_request(struct adb_request* req, int sync) | 
 | { | 
 | 	int i; | 
 |  | 
 | #ifdef DEBUG_MACIISI_ADB | 
 | 	static int dump_packet = 0; | 
 | #endif | 
 |  | 
 | 	if (via == NULL) { | 
 | 		req->complete = 1; | 
 | 		return -ENXIO; | 
 | 	} | 
 |  | 
 | #ifdef DEBUG_MACIISI_ADB | 
 | 	if (dump_packet) { | 
 | 		printk(KERN_DEBUG "maciisi_send_request:"); | 
 | 		for (i = 0; i < req->nbytes; i++) { | 
 | 			printk(" %.2x", req->data[i]); | 
 | 		} | 
 | 		printk(" sync %d\n", sync); | 
 | 	} | 
 | #endif | 
 |  | 
 | 	req->reply_expected = 1; | 
 | 	 | 
 | 	i = maciisi_write(req); | 
 | 	if (i) | 
 | 	{ | 
 | 		/* Normally, if a packet requires syncing, that happens at the end of | 
 | 		 * maciisi_send_request. But if the transfer fails, it will be restarted | 
 | 		 * by maciisi_interrupt(). We use need_sync to tell maciisi_interrupt | 
 | 		 * when to sync a packet that it sends out. | 
 | 		 *  | 
 | 		 * Suggestions on a better way to do this are welcome. | 
 | 		 */ | 
 | 		if(i == -EBUSY && sync) | 
 | 			need_sync = 1; | 
 | 		else | 
 | 			need_sync = 0; | 
 | 		return i; | 
 | 	} | 
 | 	if(sync) | 
 | 		maciisi_sync(req); | 
 | 	 | 
 | 	return 0; | 
 | } | 
 |  | 
 | /* Poll the ADB chip until the request completes */ | 
 | static void maciisi_sync(struct adb_request *req) | 
 | { | 
 | 	int count = 0;  | 
 |  | 
 | #ifdef DEBUG_MACIISI_ADB | 
 | 	printk(KERN_DEBUG "maciisi_sync called\n"); | 
 | #endif | 
 |  | 
 | 	/* If for some reason the ADB chip shuts up on us, we want to avoid an endless loop. */ | 
 | 	while (!req->complete && count++ < 50) { | 
 | 		maciisi_poll(); | 
 | 	} | 
 | 	/* This could be BAD... when the ADB controller doesn't respond | 
 | 	 * for this long, it's probably not coming back :-( */ | 
 | 	if(count >= 50) /* Hopefully shouldn't happen */ | 
 | 		printk(KERN_ERR "maciisi_send_request: poll timed out!\n"); | 
 | } | 
 |  | 
 | int | 
 | maciisi_request(struct adb_request *req, void (*done)(struct adb_request *), | 
 | 	    int nbytes, ...) | 
 | { | 
 | 	va_list list; | 
 | 	int i; | 
 |  | 
 | 	req->nbytes = nbytes; | 
 | 	req->done = done; | 
 | 	req->reply_expected = 0; | 
 | 	va_start(list, nbytes); | 
 | 	for (i = 0; i < nbytes; i++) | 
 | 		req->data[i++] = va_arg(list, int); | 
 | 	va_end(list); | 
 |  | 
 | 	return maciisi_send_request(req, 1); | 
 | } | 
 |  | 
 | /* Enqueue a request, and run the queue if possible */ | 
 | static int | 
 | maciisi_write(struct adb_request* req) | 
 | { | 
 | 	unsigned long flags; | 
 | 	int i; | 
 |  | 
 | 	/* We will accept CUDA packets - the VIA sends them to us, so | 
 |            it figures that we should be able to send them to it */ | 
 | 	if (req->nbytes < 2 || req->data[0] > CUDA_PACKET) { | 
 | 		printk(KERN_ERR "maciisi_write: packet too small or not an ADB or CUDA packet\n"); | 
 | 		req->complete = 1; | 
 | 		return -EINVAL; | 
 | 	} | 
 | 	req->next = NULL; | 
 | 	req->sent = 0; | 
 | 	req->complete = 0; | 
 | 	req->reply_len = 0; | 
 | 	 | 
 | 	local_irq_save(flags); | 
 |  | 
 | 	if (current_req) { | 
 | 		last_req->next = req; | 
 | 		last_req = req; | 
 | 	} else { | 
 | 		current_req = req; | 
 | 		last_req = req; | 
 | 	} | 
 | 	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 int | 
 | maciisi_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; | 
 | } | 
 |  | 
 | void | 
 | maciisi_poll(void) | 
 | { | 
 | 	unsigned long flags; | 
 |  | 
 | 	local_irq_save(flags); | 
 | 	if (via[IFR] & SR_INT) { | 
 | 		maciisi_interrupt(0, NULL, 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_t | 
 | maciisi_interrupt(int irq, void* arg, struct pt_regs* regs) | 
 | { | 
 | 	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, regs); | 
 | 		} | 
 | 		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 void | 
 | maciisi_input(unsigned char *buf, int nb, struct pt_regs *regs) | 
 | { | 
 | #ifdef DEBUG_MACIISI_ADB | 
 |     int i; | 
 | #endif | 
 |  | 
 |     switch (buf[0]) { | 
 |     case ADB_PACKET: | 
 | 	    adb_input(buf+2, nb-2, regs, 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; | 
 |     } | 
 | } |