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

📄 adb.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Device driver for the Apple Desktop Bus * and the /dev/adb device on macintoshes. * * Copyright (C) 1996 Paul Mackerras. * * Modified to declare controllers as structures, added * client notification of bus reset and handles PowerBook * sleep, by Benjamin Herrenschmidt. * * To do: * * - /proc/adb to list the devices and infos * - more /dev/adb to allow userland to receive the *   flow of auto-polling datas from a given device. * - move bus probe to a kernel thread */#include <linux/config.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/kernel.h>#include <linux/slab.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/devfs_fs_kernel.h>#include <linux/mm.h>#include <linux/sched.h>#include <linux/smp_lock.h>#include <linux/adb.h>#include <linux/cuda.h>#include <linux/pmu.h>#include <linux/notifier.h>#include <linux/wait.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/completion.h>#include <asm/uaccess.h>#ifdef CONFIG_PPC#include <asm/prom.h>#include <asm/hydra.h>#endifEXPORT_SYMBOL(adb_controller);EXPORT_SYMBOL(adb_client_list);extern struct adb_driver via_macii_driver;extern struct adb_driver via_maciisi_driver;extern struct adb_driver via_cuda_driver;extern struct adb_driver adb_iop_driver;extern struct adb_driver via_pmu_driver;extern struct adb_driver macio_adb_driver;static struct adb_driver *adb_driver_list[] = {#ifdef CONFIG_ADB_MACII	&via_macii_driver,#endif#ifdef CONFIG_ADB_MACIISI	&via_maciisi_driver,#endif#ifdef CONFIG_ADB_CUDA	&via_cuda_driver,#endif#ifdef CONFIG_ADB_IOP	&adb_iop_driver,#endif#ifdef CONFIG_ADB_PMU	&via_pmu_driver,#endif#ifdef CONFIG_ADB_MACIO	&macio_adb_driver,#endif	NULL};struct adb_driver *adb_controller;struct notifier_block *adb_client_list = NULL;static int adb_got_sleep = 0;static int adb_inited = 0;static pid_t adb_probe_task_pid;static int adb_probe_task_flag;static struct completion adb_probe_task_comp;static int sleepy_trackpad;int __adb_probe_sync;#ifdef CONFIG_PMAC_PBOOKstatic int adb_notify_sleep(struct pmu_sleep_notifier *self, int when);static struct pmu_sleep_notifier adb_sleep_notifier = {	adb_notify_sleep,	SLEEP_LEVEL_ADB,};#endifstatic int adb_scan_bus(void);static int do_adb_reset_bus(void);static void adbdev_init(void);static struct adb_handler {	void (*handler)(unsigned char *, int, struct pt_regs *, int);	int original_address;	int handler_id;} adb_handler[16];#if 0static void printADBreply(struct adb_request *req){        int i;        printk("adb reply (%d)", req->reply_len);        for(i = 0; i < req->reply_len; i++)                printk(" %x", req->reply[i]);        printk("\n");}#endifstatic __inline__ void adb_wait_ms(unsigned int ms){	if (current->pid && adb_probe_task_pid &&	  adb_probe_task_pid == current->pid) {		current->state = TASK_UNINTERRUPTIBLE;		schedule_timeout(1 + ms * HZ / 1000);	} else		mdelay(ms);}static int adb_scan_bus(void){	int i, highFree=0, noMovement;	int devmask = 0;	struct adb_request req;		/* assumes adb_handler[] is all zeroes at this point */	for (i = 1; i < 16; i++) {		/* see if there is anything at address i */		adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1,                            (i << 4) | 0xf);		if (req.reply_len > 1)			/* one or more devices at this address */			adb_handler[i].original_address = i;		else if (i > highFree)			highFree = i;	}	/* Note we reset noMovement to 0 each time we move a device */	for (noMovement = 1; noMovement < 2 && highFree > 0; noMovement++) {		for (i = 1; i < 16; i++) {			if (adb_handler[i].original_address == 0)				continue;			/*			 * Send a "talk register 3" command to address i			 * to provoke a collision if there is more than			 * one device at this address.			 */			adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1,				    (i << 4) | 0xf);			/*			 * Move the device(s) which didn't detect a			 * collision to address `highFree'.  Hopefully			 * this only moves one device.			 */			adb_request(&req, NULL, ADBREQ_SYNC, 3,				    (i<< 4) | 0xb, (highFree | 0x60), 0xfe);			/*			 * See if anybody actually moved. This is suggested			 * by HW TechNote 01:			 *			 * http://developer.apple.com/technotes/hw/hw_01.html			 */			adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1,				    (highFree << 4) | 0xf);			if (req.reply_len <= 1) continue;			/*			 * Test whether there are any device(s) left			 * at address i.			 */			adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1,				    (i << 4) | 0xf);			if (req.reply_len > 1) {				/*				 * There are still one or more devices				 * left at address i.  Register the one(s)				 * we moved to `highFree', and find a new				 * value for highFree.				 */				adb_handler[highFree].original_address =					adb_handler[i].original_address;				while (highFree > 0 &&				       adb_handler[highFree].original_address)					highFree--;				if (highFree <= 0)					break;				noMovement = 0;			}			else {				/*				 * No devices left at address i; move the				 * one(s) we moved to `highFree' back to i.				 */				adb_request(&req, NULL, ADBREQ_SYNC, 3,					    (highFree << 4) | 0xb,					    (i | 0x60), 0xfe);			}		}		}	/* Now fill in the handler_id field of the adb_handler entries. */	printk(KERN_DEBUG "adb devices:");	for (i = 1; i < 16; i++) {		if (adb_handler[i].original_address == 0)			continue;		adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1,			    (i << 4) | 0xf);		adb_handler[i].handler_id = req.reply[2];		printk(" [%d]: %d %x", i, adb_handler[i].original_address,		       adb_handler[i].handler_id);		devmask |= 1 << i;	}	printk("\n");	return devmask;}/* * This kernel task handles ADB probing. It dies once probing is * completed. */static intadb_probe_task(void *x){	strcpy(current->comm, "kadbprobe");		spin_lock_irq(&current->sigmask_lock);	sigfillset(&current->blocked);	flush_signals(current);	spin_unlock_irq(&current->sigmask_lock);	printk(KERN_INFO "adb: starting probe task...\n");	do_adb_reset_bus();	printk(KERN_INFO "adb: finished probe task...\n");		adb_probe_task_pid = 0;	clear_bit(0, &adb_probe_task_flag);	return 0;}static void__adb_probe_task(void *data){	adb_probe_task_pid = kernel_thread(adb_probe_task, NULL,		SIGCHLD | CLONE_FS | CLONE_FILES | CLONE_SIGHAND);}intadb_reset_bus(void){	static struct tq_struct tqs = {		routine:	__adb_probe_task,	};	if (__adb_probe_sync) {		do_adb_reset_bus();		return 0;	}			/* We need to get a lock on the probe thread */	while (test_and_set_bit(0, &adb_probe_task_flag))		schedule();	/* Just wait for PID to be 0 just in case (possible race) */	while (adb_probe_task_pid != 0)		schedule();	/* Create probe thread as a child of keventd */	if (current_is_keventd())		__adb_probe_task(NULL);	else		schedule_task(&tqs);	return 0;}int __init adb_init(void){	struct adb_driver *driver;	int i;#ifdef CONFIG_PPC	if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) )		return 0;#endif#ifdef CONFIG_MAC	if (!MACH_IS_MAC)		return 0;#endif	/* xmon may do early-init */	if (adb_inited)		return 0;	adb_inited = 1;			adb_controller = NULL;	i = 0;	while ((driver = adb_driver_list[i++]) != NULL) {		if (!driver->probe()) {			adb_controller = driver;			break;		}	}	if ((adb_controller == NULL) || adb_controller->init()) {		printk(KERN_WARNING "Warning: no ADB interface detected\n");		adb_controller = NULL;	} else {#ifdef CONFIG_PMAC_PBOOK		pmu_register_sleep_notifier(&adb_sleep_notifier);#endif /* CONFIG_PMAC_PBOOK */		if (machine_is_compatible("AAPL,PowerBook1998") ||			machine_is_compatible("PowerBook1,1"))			sleepy_trackpad = 1;		init_completion(&adb_probe_task_comp);		adbdev_init();		adb_reset_bus();	}	return 0;}__initcall(adb_init);#ifdef CONFIG_PMAC_PBOOK/* * notify clients before sleep and reset bus afterwards */intadb_notify_sleep(struct pmu_sleep_notifier *self, int when){	int ret;		switch (when) {	case PBOOK_SLEEP_REQUEST:		adb_got_sleep = 1;		/* We need to get a lock on the probe thread */		while (test_and_set_bit(0, &adb_probe_task_flag))			schedule();		/* Just wait for PID to be 0 just in case (possible race) */		while (adb_probe_task_pid != 0)			schedule();		if (adb_controller->autopoll)			adb_controller->autopoll(0);		ret = notifier_call_chain(&adb_client_list, ADB_MSG_POWERDOWN, NULL);		if (ret & NOTIFY_STOP_MASK)			return PBOOK_SLEEP_REFUSE;		break;	case PBOOK_SLEEP_REJECT:		if (adb_got_sleep) {			adb_got_sleep = 0;			clear_bit(0, &adb_probe_task_flag);			adb_reset_bus();		}		break;			case PBOOK_SLEEP_NOW:		break;	case PBOOK_WAKE:		adb_got_sleep = 0;		clear_bit(0, &adb_probe_task_flag);		adb_reset_bus();		break;	}	return PBOOK_SLEEP_OK;}#endif /* CONFIG_PMAC_PBOOK */static intdo_adb_reset_bus(void){	int ret, nret, devs;	unsigned long flags;		if (adb_controller == NULL)		return -ENXIO;			if (adb_controller->autopoll)		adb_controller->autopoll(0);	nret = notifier_call_chain(&adb_client_list, ADB_MSG_PRE_RESET, NULL);	if (nret & NOTIFY_STOP_MASK) {		if (adb_controller->autopoll)			adb_controller->autopoll(devs);		return -EBUSY;	}	if (sleepy_trackpad) {		/* Let the trackpad settle down */		adb_wait_ms(500);	}		save_flags(flags);	cli();	memset(adb_handler, 0, sizeof(adb_handler));	restore_flags(flags);	/* That one is still a bit synchronous, oh well... */	if (adb_controller->reset_bus)		ret = adb_controller->reset_bus();	else		ret = 0;	if (sleepy_trackpad) {		/* Let the trackpad settle down */		adb_wait_ms(1500);	}

⌨️ 快捷键说明

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