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

📄 via-cuda.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Device driver for the via-cuda on Apple Powermacs. * * The VIA (versatile interface adapter) interfaces to the CUDA, * a 6805 microprocessor core which controls the ADB (Apple Desktop * Bus) which connects to the keyboard and mouse.  The CUDA also * controls system power and the RTC (real time clock) chip. * * Copyright (C) 1996 Paul Mackerras. */#include <stdarg.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/adb.h>#include <linux/cuda.h>#include <linux/spinlock.h>#include <linux/interrupt.h>#ifdef CONFIG_PPC#include <asm/prom.h>#include <asm/machdep.h>#else#include <asm/macintosh.h>#include <asm/macints.h>#include <asm/machw.h>#include <asm/mac_via.h>#endif#include <asm/io.h>#include <asm/system.h>#include <linux/init.h>static volatile unsigned char __iomem *via;static DEFINE_SPINLOCK(cuda_lock);/* 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) *//* 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 */static enum cuda_state {    idle,    sent_first_byte,    sending,    reading,    read_done,    awaiting_reply} cuda_state;static struct adb_request *current_req;static struct adb_request *last_req;static unsigned char cuda_rbuf[16];static unsigned char *reply_ptr;static int reading_reply;static int data_index;static int cuda_irq;#ifdef CONFIG_PPCstatic struct device_node *vias;#endifstatic int cuda_fully_inited;#ifdef CONFIG_ADBstatic int cuda_probe(void);static int cuda_init(void);static int cuda_send_request(struct adb_request *req, int sync);static int cuda_adb_autopoll(int devs);static int cuda_reset_adb_bus(void);#endif /* CONFIG_ADB */static int cuda_init_via(void);static void cuda_start(void);static irqreturn_t cuda_interrupt(int irq, void *arg);static void cuda_input(unsigned char *buf, int nb);void cuda_poll(void);static int cuda_write(struct adb_request *req);int cuda_request(struct adb_request *req,		 void (*done)(struct adb_request *), int nbytes, ...);#ifdef CONFIG_ADBstruct adb_driver via_cuda_driver = {	"CUDA",	cuda_probe,	cuda_init,	cuda_send_request,	cuda_adb_autopoll,	cuda_poll,	cuda_reset_adb_bus};#endif /* CONFIG_ADB */#ifdef CONFIG_PPCint __init find_via_cuda(void){    struct adb_request req;    phys_addr_t taddr;    const u32 *reg;    int err;    if (vias != 0)	return 1;    vias = of_find_node_by_name(NULL, "via-cuda");    if (vias == 0)	return 0;    reg = of_get_property(vias, "reg", NULL);    if (reg == NULL) {	    printk(KERN_ERR "via-cuda: No \"reg\" property !\n");	    goto fail;    }    taddr = of_translate_address(vias, reg);    if (taddr == 0) {	    printk(KERN_ERR "via-cuda: Can't translate address !\n");	    goto fail;    }    via = ioremap(taddr, 0x2000);    if (via == NULL) {	    printk(KERN_ERR "via-cuda: Can't map address !\n");	    goto fail;    }    cuda_state = idle;    sys_ctrler = SYS_CTRLER_CUDA;    err = cuda_init_via();    if (err) {	printk(KERN_ERR "cuda_init_via() failed\n");	via = NULL;	return 0;    }    /* Clear and enable interrupts, but only on PPC. On 68K it's done  */    /* for us by the main VIA driver in arch/m68k/mac/via.c        */    out_8(&via[IFR], 0x7f);	/* clear interrupts by writing 1s */    out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */    /* enable autopoll */    cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1);    while (!req.complete)	cuda_poll();    return 1; fail:    of_node_put(vias);    vias = NULL;    return 0;}#endif /* CONFIG_PPC */static int __init via_cuda_start(void){    if (via == NULL)	return -ENODEV;#ifdef CONFIG_MAC    cuda_irq = IRQ_MAC_ADB;#else /* CONFIG_MAC */    cuda_irq = irq_of_parse_and_map(vias, 0);    if (cuda_irq == NO_IRQ) {	printk(KERN_ERR "via-cuda: can't map interrupts for %s\n",	       vias->full_name);	return -ENODEV;    }#endif /* CONFIG_MAC */    if (request_irq(cuda_irq, cuda_interrupt, 0, "ADB", cuda_interrupt)) {	printk(KERN_ERR "via-cuda: can't request irq %d\n", cuda_irq);	return -EAGAIN;    }    printk("Macintosh CUDA driver v0.5 for Unified ADB.\n");    cuda_fully_inited = 1;    return 0;}device_initcall(via_cuda_start);#ifdef CONFIG_ADBstatic intcuda_probe(void){#ifdef CONFIG_PPC    if (sys_ctrler != SYS_CTRLER_CUDA)	return -ENODEV;#else    if (macintosh_config->adb_type != MAC_ADB_CUDA)	return -ENODEV;    via = via1;#endif    return 0;}static int __initcuda_init(void){#ifdef CONFIG_PPC    if (via == NULL)	return -ENODEV;    return 0;#else     int err = cuda_init_via();    if (err) {	printk(KERN_ERR "cuda_init_via() failed\n");	return -ENODEV;    }    out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */    return via_cuda_start();#endif}#endif /* CONFIG_ADB */#define WAIT_FOR(cond, what)					\    do {                                                        \    	int x;							\	for (x = 1000; !(cond); --x) {				\	    if (x == 0) {					\		printk("Timeout waiting for " what "\n");	\		return -ENXIO;					\	    }							\	    udelay(100);					\	}							\    } while (0)static intcuda_init_via(void){    out_8(&via[DIRB], (in_8(&via[DIRB]) | TACK | TIP) & ~TREQ);	/* TACK & TIP out */    out_8(&via[B], in_8(&via[B]) | TACK | TIP);			/* negate them */    out_8(&via[ACR] ,(in_8(&via[ACR]) & ~SR_CTRL) | SR_EXT);	/* SR data in */    (void)in_8(&via[SR]);						/* clear any left-over data */#ifdef CONFIG_PPC    out_8(&via[IER], 0x7f);					/* disable interrupts from VIA */    (void)in_8(&via[IER]);#else    out_8(&via[IER], SR_INT);					/* disable SR interrupt from VIA */#endif    /* delay 4ms and then clear any pending interrupt */    mdelay(4);    (void)in_8(&via[SR]);    out_8(&via[IFR], SR_INT);    /* sync with the CUDA - assert TACK without TIP */    out_8(&via[B], in_8(&via[B]) & ~TACK);    /* wait for the CUDA to assert TREQ in response */    WAIT_FOR((in_8(&via[B]) & TREQ) == 0, "CUDA response to sync");    /* wait for the interrupt and then clear it */    WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (2)");    (void)in_8(&via[SR]);    out_8(&via[IFR], SR_INT);    /* finish the sync by negating TACK */    out_8(&via[B], in_8(&via[B]) | TACK);    /* wait for the CUDA to negate TREQ and the corresponding interrupt */    WAIT_FOR(in_8(&via[B]) & TREQ, "CUDA response to sync (3)");    WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (4)");    (void)in_8(&via[SR]);    out_8(&via[IFR], SR_INT);    out_8(&via[B], in_8(&via[B]) | TIP);	/* should be unnecessary */    return 0;}#ifdef CONFIG_ADB/* Send an ADB command */static intcuda_send_request(struct adb_request *req, int sync){    int i;    if ((via == NULL) || !cuda_fully_inited) {	req->complete = 1;	return -ENXIO;    }      req->reply_expected = 1;    i = cuda_write(req);    if (i)	return i;

⌨️ 快捷键说明

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