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

📄 via-macii.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Device driver for the via ADB on (many) Mac II-class machines * * Based on the original ADB keyboard handler Copyright (c) 1997 Alan Cox * Also derived from code Copyright (C) 1996 Paul Mackerras. * * With various updates provided over the years by Michael Schmitz, * Guideo Koerber and others. * * Rewrite for Unified ADB by Joshua M. Thompson (funaho@jurai.org) * * 1999-08-02 (jmt) - Initial rewrite for Unified ADB. */ #include <stdarg.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/sched.h>#include <linux/adb.h>#include <asm/macintosh.h>#include <asm/macints.h>#include <asm/machw.h>#include <asm/mac_via.h>#include <asm/io.h>#include <asm/system.h>#include <asm/init.h>static volatile unsigned char *via;/* VIA registers - spaced 0x200 bytes apart */#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 T1CL		(4*RS)		/* Timer 1 ctr/latch (low 8 bits) */#define T1CH		(5*RS)		/* Timer 1 counter (high 8 bits) */#define T1LL		(6*RS)		/* Timer 1 latch (low 8 bits) */#define T1LH		(7*RS)		/* Timer 1 latch (high 8 bits) */#define T2CL		(8*RS)		/* Timer 2 ctr/latch (low 8 bits) */#define T2CH		(9*RS)		/* Timer 2 counter (high 8 bits) */#define SR		(10*RS)		/* Shift register */#define ACR		(11*RS)		/* Auxiliary control register */#define PCR		(12*RS)		/* Peripheral control register */#define IFR		(13*RS)		/* Interrupt flag register */#define IER		(14*RS)		/* Interrupt enable register */#define ANH		(15*RS)		/* A-side data, no handshake *//* 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 *//* ADB transaction states according to GMHW */#define ST_CMD		0x00		/* ADB state: command byte */#define ST_EVEN		0x10		/* ADB state: even data byte */#define ST_ODD		0x20		/* ADB state: odd data byte */#define ST_IDLE		0x30		/* ADB state: idle, nothing to send */static int  macii_init_via(void);static void macii_start(void);static void macii_interrupt(int irq, void *arg, struct pt_regs *regs);static void macii_retransmit(int);static void macii_queue_poll(void);static int macii_probe(void);static int macii_init(void);static int macii_send_request(struct adb_request *req, int sync);static int macii_write(struct adb_request *req);static int macii_autopoll(int devs);static void macii_poll(void);static int macii_reset_bus(void);struct adb_driver via_macii_driver = {	"Mac II",	macii_probe,	macii_init,	macii_send_request,	macii_autopoll,	macii_poll,	macii_reset_bus};static enum macii_state {	idle,	sent_first_byte,	sending,	reading,	read_done,	awaiting_reply} macii_state;static int need_poll    = 0;static int command_byte = 0;static int last_reply   = 0;static int last_active  = 0;static struct adb_request *current_req;static struct adb_request *last_req;static struct adb_request *retry_req;static unsigned char reply_buf[16];static unsigned char *reply_ptr;static int reply_len;static int reading_reply;static int data_index;static int first_byte;static int prefix_len;static int status = ST_IDLE|TREQ;static int last_status;static int driver_running = 0;/* debug level 10 required for ADB logging (should be && debug_adb, ideally) *//* Check for MacII style ADB */static int macii_probe(void){	if (macintosh_config->adb_type != MAC_ADB_II) return -ENODEV;	via = via1;	printk("adb: Mac II ADB Driver v0.4 for Unified ADB\n");	return 0;}/* Initialize the driver */int macii_init(void){	unsigned long flags;	int err;		save_flags(flags);	cli();		err = macii_init_via();	if (err) return err;	err = request_irq(IRQ_MAC_ADB, macii_interrupt, IRQ_FLG_LOCK, "ADB",		    macii_interrupt);	if (err) return err;	macii_state = idle;	restore_flags(flags);		return 0;}/* initialize the hardware */	static int macii_init_via(void){	unsigned char x;	/* Set the lines up. We want TREQ as input TACK|TIP as output */	via[DIRB] = (via[DIRB] | TACK | TIP) & ~TREQ;	/* Set up state: idle */	via[B] |= ST_IDLE;	last_status = via[B] & (ST_MASK|TREQ);	/* Shift register on input */	via[ACR] = (via[ACR] & ~SR_CTRL) | SR_EXT;	/* Wipe any pending data and int */	x = via[SR];	return 0;}/* Send an ADB poll (Talk Register 0 command, tagged on the front of the request queue) */static void macii_queue_poll(void){	static int device = 0;	static int in_poll=0;	static struct adb_request req;	unsigned long flags;	if (in_poll) printk("macii_queue_poll: double poll!\n");	in_poll++;	if (++device > 15) device = 1;	adb_request(&req, NULL, ADBREQ_REPLY|ADBREQ_NOSEND, 1,		    ADB_READREG(device, 0));	save_flags(flags);	cli();	req.next = current_req;	current_req = &req;	restore_flags(flags);	macii_start();	in_poll--;}/* Send an ADB retransmit (Talk, appended to the request queue) */static void macii_retransmit(int device){	static int in_retransmit = 0;	static struct adb_request rt;	unsigned long flags;	if (in_retransmit) printk("macii_retransmit: double retransmit!\n");	in_retransmit++;	adb_request(&rt, NULL, ADBREQ_REPLY|ADBREQ_NOSEND, 1,		    ADB_READREG(device, 0));	save_flags(flags);	cli();	if (current_req != NULL) {		last_req->next = &rt;		last_req = &rt;	} else {		current_req = &rt;		last_req = &rt;	}	if (macii_state == idle) macii_start();	restore_flags(flags);	in_retransmit--;}/* Send an ADB request; if sync, poll out the reply 'till it's done */static int macii_send_request(struct adb_request *req, int sync){	int i;	i = macii_write(req);	if (i) return i;	if (sync) {		while (!req->complete) macii_poll();	}	return 0;}/* Send an ADB request */static int macii_write(struct adb_request *req){	unsigned long flags;	if (req->nbytes < 2 || req->data[0] != ADB_PACKET) {		req->complete = 1;		return -EINVAL;	}	req->next = 0;	req->sent = 0;	req->complete = 0;	req->reply_len = 0;	save_flags(flags); cli();	if (current_req != NULL) {		last_req->next = req;		last_req = req;	} else {		current_req = req;		last_req = req;		if (macii_state == idle) macii_start();	}	restore_flags(flags);	return 0;}/* Start auto-polling */static int macii_autopoll(int devs){	/* Just ping a random default address */	if (!(current_req || retry_req))		macii_retransmit( (last_active < 16 && last_active > 0) ? last_active : 3);	return 0;}/* Prod the chip without interrupts */static void macii_poll(void){	unsigned long flags;	save_flags(flags); cli();	if (via[IFR] & SR_INT) macii_interrupt(0, 0, 0);	restore_flags(flags);}/* Reset the bus */static int macii_reset_bus(void){	static struct adb_request req;		/* Command = 0, Address = ignored */	adb_request(&req, NULL, 0, 1, ADB_BUSRESET);	return 0;}/* Start sending ADB packet */static void macii_start(void){	unsigned long flags;	struct adb_request *req;	req = current_req;	if (!req) return;	/* assert macii_state == idle */	if (macii_state != idle) {		printk("macii_start: called while driver busy (%p %x %x)!\n",			req, macii_state, (uint) via1[B] & (ST_MASK|TREQ));		return;	}	save_flags(flags); cli();		/* 	 * IRQ signaled ?? (means ADB controller wants to send, or might 	 * be end of packet if we were reading)	 */	if ((via[B] & TREQ) == 0) {		/*		 *	FIXME - we need to restart this on a timer		 *	or a collision at boot hangs us.		 *	Never set macii_state to idle here, or macii_start 

⌨️ 快捷键说明

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