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

📄 sunkbd.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 3 页
字号:
}static void do_lock(unsigned char value, char up_flag){	if (up_flag || rep)		return;	chg_vc_kbd_lock(kbd, value);}/* * The leds display either (i) the status of NumLock, CapsLock, ScrollLock, * or (ii) whatever pattern of lights people want to show using KDSETLED, * or (iii) specified bits of specified words in kernel memory. */static unsigned char ledstate = 0xff; /* undefined */static unsigned char ledioctl;unsigned char sun_getledstate(void) {    return ledstate;}void sun_setledstate(struct kbd_struct *kbd, unsigned int led) {    if (!(led & ~7)) {	ledioctl = led;	kbd->ledmode = LED_SHOW_IOCTL;    } else	kbd->ledmode = LED_SHOW_FLAGS;    set_leds();}static struct ledptr {    unsigned int *addr;    unsigned int mask;    unsigned char valid:1;} ledptrs[3];void register_leds(int console, unsigned int led,		   unsigned int *addr, unsigned int mask) {    struct kbd_struct *kbd = kbd_table + console;    if (led < 3) {	ledptrs[led].addr = addr;	ledptrs[led].mask = mask;	ledptrs[led].valid = 1;	kbd->ledmode = LED_SHOW_MEM;    } else	kbd->ledmode = LED_SHOW_FLAGS;}static inline unsigned char getleds(void){    struct kbd_struct *kbd = kbd_table + fg_console;    unsigned char leds;    if (kbd->ledmode == LED_SHOW_IOCTL)      return ledioctl;    leds = kbd->ledflagstate;    if (kbd->ledmode == LED_SHOW_MEM) {	if (ledptrs[0].valid) {	    if (*ledptrs[0].addr & ledptrs[0].mask)	      leds |= 1;	    else	      leds &= ~1;	}	if (ledptrs[1].valid) {	    if (*ledptrs[1].addr & ledptrs[1].mask)	      leds |= 2;	    else	      leds &= ~2;	}	if (ledptrs[2].valid) {	    if (*ledptrs[2].addr & ledptrs[2].mask)	      leds |= 4;	    else	      leds &= ~4;	}    }    return leds;}/* * This routine is the bottom half of the keyboard interrupt * routine, and runs with all interrupts enabled. It does * console changing, led setting and copy_to_cooked, which can * take a reasonably long time. * * Aside from timing (which isn't really that important for * keyboard interrupts as they happen often), using the software * interrupt routines for this thing allows us to easily mask * this when we don't want any of the above to happen. Not yet * used, but this allows for easy and efficient race-condition * prevention later on. */static unsigned char sunkbd_ledstate = 0xff; /* undefined */void sun_kbd_bh(unsigned long dummy){	unsigned long flags;	unsigned char leds, kbd_leds;	spin_lock_irqsave(&sunkbd_lock, flags);	leds = getleds();	kbd_leds = vcleds_to_sunkbd(leds);	if (kbd_leds != sunkbd_ledstate) {		ledstate = leds;		sunkbd_ledstate = kbd_leds;		send_cmd(SKBDCMD_SETLED);		send_cmd(kbd_leds);	}	spin_unlock_irqrestore(&sunkbd_lock, flags);}/* Support for keyboard "beeps". */ /* Timer routine to turn off the beep after the interval expires. */static void sunkbd_kd_nosound(unsigned long __unused){	unsigned long flags;	spin_lock_irqsave(&sunkbd_lock, flags);	send_cmd(SKBDCMD_BELLOFF);	spin_unlock_irqrestore(&sunkbd_lock, flags);}/* * 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 sunkbd_kd_mksound(unsigned int hz, unsigned int ticks){	unsigned long flags;	static struct timer_list sound_timer = { function: sunkbd_kd_nosound };	spin_lock_irqsave(&sunkbd_lock, flags);	del_timer(&sound_timer);	if (hz) {		send_cmd(SKBDCMD_BELLON);		if (ticks) {			sound_timer.expires = jiffies + ticks;			add_timer(&sound_timer);		}	} else		send_cmd(SKBDCMD_BELLOFF);	spin_unlock_irqrestore(&sunkbd_lock, flags);}extern void (*kd_mksound)(unsigned int hz, unsigned int ticks);int __init sun_kbd_init(void){	int i, opt_node;	struct kbd_struct kbd0;	extern struct tty_driver console_driver;	kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS;	kbd0.ledmode = LED_SHOW_FLAGS;	kbd0.lockstate = KBD_DEFLOCK;	kbd0.slockstate = 0;	kbd0.modeflags = KBD_DEFMODE;	kbd0.kbdmode = VC_XLATE; 	for (i = 0 ; i < MAX_NR_CONSOLES ; i++)		kbd_table[i] = kbd0;	ttytab = console_driver.table;	kd_mksound = sunkbd_kd_mksound;	/* XXX Check keyboard-click? property in 'options' PROM node XXX */	if(sparc_cpu_model != sun4) {		opt_node = prom_getchild(prom_root_node);		opt_node = prom_searchsiblings(opt_node, "options");		i = prom_getintdefault(opt_node, "keyboard-click?", -1);		if(i != -1)			sunkbd_clickp = 1;		else			sunkbd_clickp = 0;	} else {		sunkbd_clickp = 0;	}	keyboard_tasklet.func = sun_kbd_bh;	tasklet_enable(&keyboard_tasklet);	tasklet_schedule(&keyboard_tasklet);	return 0;}/* /dev/kbd support */#define KBD_QSIZE 32static Firm_event kbd_queue [KBD_QSIZE];static int kbd_head, kbd_tail;static spinlock_t kbd_queue_lock = SPIN_LOCK_UNLOCKED;char kbd_opened;static int kbd_active = 0;static DECLARE_WAIT_QUEUE_HEAD(kbd_wait);static struct fasync_struct *kb_fasync;voidpush_kbd (int scan){	unsigned long flags;	int next;	if (scan == KBD_IDLE)		return;	spin_lock_irqsave(&kbd_queue_lock, flags);	next = (kbd_head + 1) % KBD_QSIZE;	if (next != kbd_tail){		kbd_queue [kbd_head].id = scan & KBD_KEYMASK;		kbd_queue [kbd_head].value=scan & KBD_UP ? VKEY_UP : VKEY_DOWN;		kbd_queue [kbd_head].time = xtime;		kbd_head = next;	}	spin_unlock_irqrestore(&kbd_queue_lock, flags);	kill_fasync (&kb_fasync, SIGIO, POLL_IN);	wake_up_interruptible (&kbd_wait);}static ssize_tkbd_read (struct file *f, char *buffer, size_t count, loff_t *ppos){	DECLARE_WAITQUEUE(wait, current);	unsigned long flags;	char *end, *p;	/* Return EWOULDBLOCK, because this is what the X server expects */	if (kbd_head == kbd_tail){		if (f->f_flags & O_NONBLOCK)			return -EWOULDBLOCK;		add_wait_queue (&kbd_wait, &wait);repeat:		set_current_state(TASK_INTERRUPTIBLE);		if (kbd_head == kbd_tail && !signal_pending(current)) {			schedule();			goto repeat;		}		current->state = TASK_RUNNING;		remove_wait_queue (&kbd_wait, &wait);	}	/* There is data in the keyboard, fill the user buffer */	end = buffer+count;	p = buffer;	spin_lock_irqsave(&kbd_queue_lock, flags);	for (; p < end && kbd_head != kbd_tail;){		Firm_event this_event = kbd_queue[kbd_tail];		kbd_tail = (kbd_tail + 1) % KBD_QSIZE;		spin_unlock_irqrestore(&kbd_queue_lock, flags);#ifdef CONFIG_SPARC32_COMPAT		if (current->thread.flags & SPARC_FLAG_32BIT) {			if (copy_to_user((Firm_event *)p, &this_event,					 sizeof(Firm_event)-sizeof(struct timeval)))				return -EFAULT;			p += sizeof(Firm_event)-sizeof(struct timeval);			if (__put_user(this_event.time.tv_sec, (u32 *)p))				return -EFAULT;			p += sizeof(u32);			if (__put_user(this_event.time.tv_usec, (u32 *)p))				return -EFAULT;			p += sizeof(u32);		} else#endif		{			if (copy_to_user((Firm_event *)p, &this_event, 					 sizeof(Firm_event)))				return -EFAULT;			p += sizeof (Firm_event);		}#ifdef KBD_DEBUG		printk ("[%s]", this_event.value == VKEY_UP ? "UP" : "DOWN");#endif		spin_lock_irqsave(&kbd_queue_lock, flags);	}	spin_unlock_irqrestore(&kbd_queue_lock, flags);	return p-buffer;}/* Needed by X */static int kbd_fasync (int fd, struct file *filp, int on){	int retval;	retval = fasync_helper (fd, filp, on, &kb_fasync);	if (retval < 0)		return retval;	return 0;}static unsigned int kbd_poll (struct file *f, poll_table *wait){	poll_wait(f, &kbd_wait, wait);	if (kbd_head != kbd_tail)		return POLLIN | POLLRDNORM;	return 0;}static intkbd_ioctl (struct inode *i, struct file *f, unsigned int cmd, unsigned long arg){	unsigned char c;	unsigned char leds = 0;	int value;	switch (cmd){	case KIOCTYPE:		  /* return keyboard type */		if (put_user(sunkbd_type, (int *) arg))			return -EFAULT;		break;	case KIOCGTRANS:		if (put_user(TR_UNTRANS_EVENT, (int *) arg))			return -EFAULT;		break;	case KIOCTRANS:		if (get_user(value, (int *) arg))			return -EFAULT;		if (value != TR_UNTRANS_EVENT)			return -EINVAL;		break;	case KIOCLAYOUT:		if (put_user(sunkbd_layout, (int *) arg))			return -EFAULT;		break;	case KIOCSDIRECT:#ifndef CODING_NEW_DRIVER		if (get_user(value, (int *) arg))			return -EFAULT;		if(value)			kbd_redirected = fg_console + 1;		else			kbd_redirected = 0;		kbd_table [fg_console].kbdmode = kbd_redirected ? VC_RAW : VC_XLATE;#endif		break;	case KIOCCMD:		if (get_user(value, (int *) arg))			return -EFAULT;		c = (unsigned char) value;		switch (c) {			case SKBDCMD_CLICK:			case SKBDCMD_NOCLICK:				spin_lock_irq(&sunkbd_lock);				send_cmd(c);				spin_unlock_irq(&sunkbd_lock);				return 0;			case SKBDCMD_BELLON:				kd_mksound(1,0);				return 0;			case SKBDCMD_BELLOFF:				kd_mksound(0,0);				return 0;			default:				return -EINVAL;		}	case KIOCSLED:		if (get_user(c, (unsigned char *) arg))			return -EFAULT;		if (c & LED_SCRLCK) leds |= (1 << VC_SCROLLOCK);		if (c & LED_NLOCK) leds |= (1 << VC_NUMLOCK);		if (c & LED_CLOCK) leds |= (1 << VC_CAPSLOCK);		compose_led_on = !!(c & LED_CMPOSE);		sun_setledstate(kbd_table + fg_console, leds);		break;	case KIOCGLED:		if (put_user(vcleds_to_sunkbd(getleds()), (unsigned char *) arg))			return -EFAULT;		break;	case KIOCGRATE:	{		struct kbd_rate rate;		rate.delay = kbd_delay_ticks;		if (kbd_rate_ticks)			rate.rate = HZ / kbd_rate_ticks;		else			rate.rate = 0;		if (copy_to_user((struct kbd_rate *)arg, &rate,				 sizeof(struct kbd_rate)))			return -EFAULT;		return 0;	}	case KIOCSRATE:	{		struct kbd_rate rate;		if (verify_area(VERIFY_READ, (void *)arg,				sizeof(struct kbd_rate)))			return -EFAULT;		copy_from_user(&rate, (struct kbd_rate *)arg,			       sizeof(struct kbd_rate));		if (rate.rate > 50)			return -EINVAL;		if (rate.rate == 0)			kbd_rate_ticks = 0;		else			kbd_rate_ticks = HZ / rate.rate;		kbd_delay_ticks = rate.delay;		return 0;	}	case FIONREAD:		/* return number of bytes in kbd queue */	{		int count;				count = kbd_head - kbd_tail;		if (put_user((count < 0) ? KBD_QSIZE - count : count, (int *) arg))			return -EFAULT;		return 0;	}	default:		printk ("Unknown Keyboard ioctl: %8.8x\n", cmd);		return -EINVAL;	}	return 0;}static intkbd_open (struct inode *i, struct file *f){	kbd_active++;	if (kbd_opened)		return 0;	kbd_opened = fg_console + 1;	spin_lock_irq(&kbd_queue_lock);	kbd_head = kbd_tail = 0;	spin_unlock_irq(&kbd_queue_lock);	return 0;}static intkbd_close (struct inode *i, struct file *f){	lock_kernel();	if (!--kbd_active) {		if (kbd_redirected)			kbd_table [kbd_redirected-1].kbdmode = VC_XLATE;		kbd_redirected = 0;		kbd_opened = 0;		kbd_fasync (-1, f, 0);	}	unlock_kernel();	return 0;}static struct file_operations kbd_fops ={	read:		kbd_read,	poll:		kbd_poll,	ioctl:		kbd_ioctl,	open:		kbd_open,	release:	kbd_close,	fasync:		kbd_fasync,};void __init keyboard_zsinit(void (*put_char)(unsigned char)){	int timeout = 0;	kbd_put_char = put_char;	if (!kbd_put_char)		panic("keyboard_zsinit: no put_char parameter");	/* Test out the leds */	sunkbd_type = 255;	sunkbd_layout = 0;	send_cmd(SKBDCMD_RESET);	send_cmd(SKBDCMD_RESET);	while((sunkbd_type==255) && timeout++ < 25000) {		udelay(100);		barrier();	}	if(timeout>=25000) {		printk("keyboard: not present\n");		return;	}	if(sunkbd_type != SUNKBD_TYPE4) {		printk("Sun TYPE %d keyboard detected ", sunkbd_type);	} else {		timeout=0;		while((sunkbd_layout==0) && timeout++ < 10000) {			udelay(100);			barrier();		}		printk("Sun TYPE %d keyboard detected ",		       ((sunkbd_layout & SUNKBD_LOUT_TYP5_MASK) ? 5 : 4));	}	if(sunkbd_type == SUNKBD_TYPE2)		sunkbd_clickp = 0;	spin_lock_irq(&sunkbd_lock);	if(sunkbd_clickp) {		send_cmd(SKBDCMD_CLICK);		printk("with keyclick\n");	} else {		send_cmd(SKBDCMD_NOCLICK);		printk("without keyclick\n");	}	/* Dork with led lights, then turn them all off */	send_cmd(SKBDCMD_SETLED); send_cmd(0xf); /* All on */	send_cmd(SKBDCMD_SETLED); send_cmd(0x0); /* All off */	spin_unlock_irq(&sunkbd_lock);	/* Register the /dev/kbd interface */	devfs_register (NULL, "kbd", DEVFS_FL_DEFAULT,			KBD_MAJOR, 0,			S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH,			&kbd_fops, NULL);	if (devfs_register_chrdev (KBD_MAJOR, "kbd", &kbd_fops)){		printk ("Could not register /dev/kbd device\n");		return;	}	return;}

⌨️ 快捷键说明

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