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

📄 pcikbd.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 3 页
字号:
}void pcikbd_leds(unsigned char leds){	if (!pcikbd_iobase)		return;	if (!send_data(KBD_CMD_SET_LEDS) || !send_data(leds))		send_data(KBD_CMD_ENABLE);}static unsigned char parse_kbd_rate(struct kbd_repeat *r){	static struct r2v {		int rate;		unsigned char val;	} kbd_rates[]={	{ 5,  0x14 },			{ 7,  0x10 },			{ 10, 0x0c },			{ 15, 0x08 },			{ 20, 0x04 },			{ 25, 0x02 },			{ 30, 0x00 } };	static struct d2v {		int delay;		unsigned char val;	} kbd_delays[]={ { 250,  0 },			 { 500,  1 },			 { 750,  2 },			 { 1000, 3 } };	int rate = 0, delay = 0;	if (r != NULL) {		int i, new_rate = 30, new_delay = 250;		if (r->rate <= 0)			r->rate = kbdrate.rate;		if (r->delay <= 0)			r->delay = kbdrate.delay;		for (i = 0; i < sizeof(kbd_rates) / sizeof(struct r2v); i++) {			if (kbd_rates[i].rate == r->rate) {				new_rate = kbd_rates[i].rate;				rate = kbd_rates[i].val;				break;			}		}		for (i=0; i < sizeof(kbd_delays) / sizeof(struct d2v); i++) {			if (kbd_delays[i].delay == r->delay) {				new_delay = kbd_delays[i].delay;				delay = kbd_delays[i].val;				break;			}		}		r->rate = new_rate;		r->delay = new_delay;	}	return (delay << 5) | rate;}static int write_kbd_rate(unsigned char r){	if (!send_data(KBD_CMD_SET_RATE) || !send_data(r)) {		/* re-enable kbd if any errors */		send_data(KBD_CMD_ENABLE);		return 0;	}	return 1;}static int pcikbd_rate(struct kbd_repeat *rep){	unsigned char r;	struct kbd_repeat old_rep;	if (rep == NULL)		return -EINVAL;	r = parse_kbd_rate(rep);	memcpy(&old_rep, &kbdrate, sizeof(struct kbd_repeat));	if (write_kbd_rate(r)) {		memcpy(&kbdrate,rep,sizeof(struct kbd_repeat));		memcpy(rep,&old_rep,sizeof(struct kbd_repeat));		return 0;	}	return -EIO;}static int pcikbd_wait_for_input(void){	int status, data;	unsigned long timeout = 1000;	do {		mdelay(1);		status = pcikbd_inb(pcikbd_iobase + KBD_STATUS_REG);		if (!(status & KBD_STAT_OBF))			continue;		data = pcikbd_inb(pcikbd_iobase + KBD_DATA_REG);		if (status & (KBD_STAT_GTO | KBD_STAT_PERR))			continue;		return (data & 0xff);	} while (--timeout > 0);	return -1;}static void pcikbd_write(int address, int data){	int status;	do {		status = pcikbd_inb(pcikbd_iobase + KBD_STATUS_REG);	} while (status & KBD_STAT_IBF);	pcikbd_outb(data, pcikbd_iobase + address);}#ifdef __sparc_v9__static unsigned long pcibeep_iobase = 0;/* Timer routine to turn off the beep after the interval expires. */static void pcikbd_kd_nosound(unsigned long __unused){	if (pcibeep_iobase & 0x2UL)		outb(0, pcibeep_iobase);	else		outl(0, pcibeep_iobase);}/* * Initiate a keyboard beep. If the frequency is zero, then we stop * the beep. Any other frequency will start a monotone beep. The beep * will be stopped by a timer after "ticks" jiffies. If ticks is 0, * then we do not start a timer. */static void pcikbd_kd_mksound(unsigned int hz, unsigned int ticks){	unsigned long flags;	static struct timer_list sound_timer = { function: pcikbd_kd_nosound };	save_flags(flags); cli();	del_timer(&sound_timer);	if (hz) {		if (pcibeep_iobase & 0x2UL)			outb(1, pcibeep_iobase);		else			outl(1, pcibeep_iobase);		if (ticks) {			sound_timer.expires = jiffies + ticks;			add_timer(&sound_timer);		}	} else {		if (pcibeep_iobase & 0x2UL)			outb(0, pcibeep_iobase);		else			outl(0, pcibeep_iobase);	}	restore_flags(flags);}#if defined(CONFIG_USB) && defined(CONFIG_SPARC64)static void isa_kd_nosound(unsigned long __unused){	/* disable counter 2 */	outb(inb(pcibeep_iobase + 0x61)&0xFC, pcibeep_iobase + 0x61);	return;}static void isa_kd_mksound(unsigned int hz, unsigned int ticks){	static struct timer_list sound_timer = { function: isa_kd_nosound };	unsigned int count = 0;	unsigned long flags;	if (hz > 20 && hz < 32767)		count = 1193180 / hz;		save_flags(flags);	cli();	del_timer(&sound_timer);	if (count) {		/* enable counter 2 */		outb(inb(pcibeep_iobase + 0x61)|3, pcibeep_iobase + 0x61);		/* set command for counter 2, 2 byte write */		outb(0xB6, pcibeep_iobase + 0x43);		/* select desired HZ */		outb(count & 0xff, pcibeep_iobase + 0x42);		outb((count >> 8) & 0xff, pcibeep_iobase + 0x42);		if (ticks) {			sound_timer.expires = jiffies+ticks;			add_timer(&sound_timer);		}	} else		isa_kd_nosound(0);	restore_flags(flags);	return;}#endif#endifstatic void nop_kd_mksound(unsigned int hz, unsigned int ticks){}extern void (*kd_mksound)(unsigned int hz, unsigned int ticks);static char * __init do_pcikbd_init_hw(void){	while(pcikbd_wait_for_input() != -1)		;	pcikbd_write(KBD_CNTL_REG, KBD_CCMD_SELF_TEST);	if(pcikbd_wait_for_input() != 0x55)		return "Keyboard failed self test";	pcikbd_write(KBD_CNTL_REG, KBD_CCMD_KBD_TEST);	if(pcikbd_wait_for_input() != 0x00)		return "Keyboard interface failed self test";	pcikbd_write(KBD_CNTL_REG, KBD_CCMD_KBD_ENABLE);	pcikbd_write(KBD_DATA_REG, KBD_CMD_RESET);	if(pcikbd_wait_for_input() != KBD_REPLY_ACK)		return "Keyboard reset failed, no ACK";	if(pcikbd_wait_for_input() != KBD_REPLY_POR)		return "Keyboard reset failed, no ACK";	pcikbd_write(KBD_DATA_REG, KBD_CMD_DISABLE);	if(pcikbd_wait_for_input() != KBD_REPLY_ACK)		return "Disable keyboard: no ACK";	pcikbd_write(KBD_CNTL_REG, KBD_CCMD_WRITE_MODE);	pcikbd_write(KBD_DATA_REG,		     (KBD_MODE_KBD_INT | KBD_MODE_SYS |		      KBD_MODE_DISABLE_MOUSE | KBD_MODE_KCC));	pcikbd_write(KBD_DATA_REG, KBD_CMD_ENABLE);	if(pcikbd_wait_for_input() != KBD_REPLY_ACK)		return "Enable keyboard: no ACK";	write_kbd_rate(parse_kbd_rate(&kbdrate));	return NULL; /* success */}void __init pcikbd_init_hw(void){	struct linux_ebus *ebus;	struct linux_ebus_device *edev;	struct linux_ebus_child *child;	char *msg;	if (pcikbd_mrcoffee) {		if ((pcikbd_iobase = (unsigned long) ioremap(0x71300060, 8)) == 0) {			prom_printf("pcikbd_init_hw: cannot map\n");			return;		}		pcikbd_irq = 13 | 0x20;		if (request_irq(pcikbd_irq, &pcikbd_interrupt,				SA_SHIRQ, "keyboard", (void *)pcikbd_iobase)) {			printk("8042: cannot register IRQ %x\n", pcikbd_irq);			return;		}		printk("8042(kbd): iobase[%x] irq[%x]\n",		    (unsigned)pcikbd_iobase, pcikbd_irq);	} else {		for_each_ebus(ebus) {			for_each_ebusdev(edev, ebus) {				if(!strcmp(edev->prom_name, "8042")) {					for_each_edevchild(edev, child) {                                                if (strcmp(child->prom_name, PCI_KB_NAME1) == 0 ||						    strcmp(child->prom_name, PCI_KB_NAME2) == 0)							goto found;					}				}			}		}#ifdef CONFIG_USB		/* We are being called for the sake of USB keyboard		 * state initialization.  So we should check for beeper		 * device in this case.		 */		edev = 0;		for_each_ebus(ebus) {			for_each_ebusdev(edev, ebus) {				if (!strcmp(edev->prom_name, "beep")) {					pcibeep_iobase = edev->resource[0].start;					kd_mksound = pcikbd_kd_mksound;					printk("8042(speaker): iobase[%016lx]\n", pcibeep_iobase);					return;				}			}		}#ifdef CONFIG_SPARC64		/* Maybe we have one inside the ALI southbridge? */		{			struct isa_bridge *isa_br;			struct isa_device *isa_dev;			for_each_isa(isa_br) {				for_each_isadev(isa_dev, isa_br) {					/* This is a hack, the 'dma' device node has					 * the base of the I/O port space for that PBM					 * as it's resource, so we use that. -DaveM					 */					if (!strcmp(isa_dev->prom_name, "dma")) {						pcibeep_iobase = isa_dev->resource.start;						kd_mksound = isa_kd_mksound;						printk("isa(speaker): iobase[%016lx:%016lx]\n",						       pcibeep_iobase + 0x42,						       pcibeep_iobase + 0x61);						return;					}				}			}		}#endif		/* No beeper found, ok complain. */#endif		printk("pcikbd_init_hw: no 8042 found\n");		return;found:		pcikbd_iobase = child->resource[0].start;		pcikbd_irq = child->irqs[0];		if (request_irq(pcikbd_irq, &pcikbd_interrupt,				SA_SHIRQ, "keyboard", (void *)pcikbd_iobase)) {			printk("8042: cannot register IRQ %s\n",			       __irq_itoa(pcikbd_irq));			return;		}		printk("8042(kbd) at 0x%lx (irq %s)\n", pcikbd_iobase,		       __irq_itoa(pcikbd_irq));	}	kd_mksound = nop_kd_mksound;	kbd_rate = pcikbd_rate;#ifdef __sparc_v9__	edev = 0;	for_each_ebus(ebus) {		for_each_ebusdev(edev, ebus) {			if(!strcmp(edev->prom_name, "beeper"))				goto ebus_done;		}	}ebus_done:	/*	 * XXX: my 3.1.3 PROM does not give me the beeper node for the audio	 *      auxio register, though I know it is there... (ecd)	 *	 * JavaStations appear not to have beeper. --zaitcev	 */	if (!edev)		pcibeep_iobase = (pcikbd_iobase & ~(0xffffff)) | 0x722000;	else		pcibeep_iobase = edev->resource[0].start;	kd_mksound = pcikbd_kd_mksound;	printk("8042(speaker): iobase[%016lx]%s\n", pcibeep_iobase,	       edev ? "" : " (forced)");	prom_keyboard = pcikbd_enter_prom;#endif	disable_irq(pcikbd_irq);	msg = do_pcikbd_init_hw();	enable_irq(pcikbd_irq);	if(msg)		printk("8042: keyboard init failure [%s]\n", msg);}/* * Here begins the Mouse Driver. */static unsigned long pcimouse_iobase = 0;static unsigned int pcimouse_irq;#define AUX_BUF_SIZE	2048struct aux_queue {	unsigned long head;	unsigned long tail;	wait_queue_head_t proc_list;	struct fasync_struct *fasync;	unsigned char buf[AUX_BUF_SIZE];};static struct aux_queue *queue;static int aux_count = 0;static int aux_present = 0;#define pcimouse_inb(x)     inb(x)#define pcimouse_outb(v,x)  outb(v,x)/* *	Shared subroutines */static unsigned int get_from_queue(void){	unsigned int result;	unsigned long flags;	spin_lock_irqsave(&pcikbd_lock, flags);	result = queue->buf[queue->tail];	queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);	spin_unlock_irqrestore(&pcikbd_lock, flags);	return result;}static inline int queue_empty(void){	return queue->head == queue->tail;}static int aux_fasync(int fd, struct file *filp, int on){	int retval;	retval = fasync_helper(fd, filp, on, &queue->fasync);	if (retval < 0)		return retval;	return 0;}/* *	PS/2 Aux Device */#define AUX_INTS_OFF	(KBD_MODE_KCC | KBD_MODE_DISABLE_MOUSE | \			 KBD_MODE_SYS | KBD_MODE_KBD_INT)#define AUX_INTS_ON	(KBD_MODE_KCC | KBD_MODE_SYS | \			 KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT)#define MAX_RETRIES	60		/* some aux operations take long time*//* *	Status polling */static int poll_aux_status(void){	int retries = 0;	while ((pcimouse_inb(pcimouse_iobase + KBD_STATUS_REG) &		(KBD_STAT_IBF | KBD_STAT_OBF)) && retries < MAX_RETRIES) { 		if ((pcimouse_inb(pcimouse_iobase + KBD_STATUS_REG) & AUX_STAT_OBF)		    == AUX_STAT_OBF)			pcimouse_inb(pcimouse_iobase + KBD_DATA_REG);		mdelay(5);		retries++;	}	return (retries < MAX_RETRIES);}/* * Write to aux device */static void aux_write_dev(int val)

⌨️ 快捷键说明

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