📄 pcikbd.c
字号:
{ poll_aux_status(); pcimouse_outb(KBD_CCMD_WRITE_MOUSE, pcimouse_iobase + KBD_CNTL_REG);/* Write magic cookie */ poll_aux_status(); pcimouse_outb(val, pcimouse_iobase + KBD_DATA_REG); /* Write data */ udelay(1);}/* * Write to device & handle returned ack */static int __init aux_write_ack(int val){ aux_write_dev(val); poll_aux_status(); if ((pcimouse_inb(pcimouse_iobase + KBD_STATUS_REG) & AUX_STAT_OBF) == AUX_STAT_OBF) return (pcimouse_inb(pcimouse_iobase + KBD_DATA_REG)); return 0;}/* * Write aux device command */static void aux_write_cmd(int val){ poll_aux_status(); pcimouse_outb(KBD_CCMD_WRITE_MODE, pcimouse_iobase + KBD_CNTL_REG); poll_aux_status(); pcimouse_outb(val, pcimouse_iobase + KBD_DATA_REG);}/* * Interrupt from the auxiliary device: a character * is waiting in the keyboard/aux controller. */void pcimouse_interrupt(int irq, void *dev_id, struct pt_regs *regs){ unsigned long flags; int head, maxhead; unsigned char val; spin_lock_irqsave(&pcikbd_lock, flags); head = queue->head; maxhead = (queue->tail - 1) & (AUX_BUF_SIZE - 1); if ((pcimouse_inb(pcimouse_iobase + KBD_STATUS_REG) & AUX_STAT_OBF) != AUX_STAT_OBF) { spin_unlock_irqrestore(&pcikbd_lock, flags); return; } val = pcimouse_inb(pcimouse_iobase + KBD_DATA_REG); queue->buf[head] = val; add_mouse_randomness(val); if (head != maxhead) { head++; head &= AUX_BUF_SIZE - 1; } queue->head = head; spin_unlock_irqrestore(&pcikbd_lock, flags); kill_fasync(&queue->fasync, SIGIO, POLL_IN); wake_up_interruptible(&queue->proc_list);}static int aux_release(struct inode * inode, struct file * file){ unsigned long flags; aux_fasync(-1, file, 0); spin_lock_irqsave(&pcikbd_lock, flags); if (--aux_count) goto out; /* Disable controller ints */ aux_write_cmd(AUX_INTS_OFF); poll_aux_status(); /* Disable Aux device */ pcimouse_outb(KBD_CCMD_MOUSE_DISABLE, pcimouse_iobase + KBD_CNTL_REG); poll_aux_status();out: spin_unlock_irqrestore(&pcikbd_lock, flags); return 0;}/* * Install interrupt handler. * Enable auxiliary device. */static int aux_open(struct inode * inode, struct file * file){ unsigned long flags; if (!aux_present) return -ENODEV; spin_lock_irqsave(&pcikbd_lock, flags); if (aux_count++) { spin_unlock_irqrestore(&pcikbd_lock, flags); return 0; } if (!poll_aux_status()) { aux_count--; spin_unlock_irqrestore(&pcikbd_lock, flags); return -EBUSY; } queue->head = queue->tail = 0; /* Flush input queue */ poll_aux_status(); pcimouse_outb(KBD_CCMD_MOUSE_ENABLE, pcimouse_iobase+KBD_CNTL_REG); /* Enable Aux */ aux_write_dev(AUX_ENABLE_DEV); /* Enable aux device */ aux_write_cmd(AUX_INTS_ON); /* Enable controller ints */ poll_aux_status(); spin_unlock_irqrestore(&pcikbd_lock, flags); return 0;}/* * Write to the aux device. */static ssize_t aux_write(struct file * file, const char * buffer, size_t count, loff_t *ppos){ ssize_t retval = 0; unsigned long flags; if (count) { ssize_t written = 0; spin_lock_irqsave(&pcikbd_lock, flags); do { char c; spin_unlock_irqrestore(&pcikbd_lock, flags); get_user(c, buffer++); spin_lock_irqsave(&pcikbd_lock, flags); if (!poll_aux_status()) break; pcimouse_outb(KBD_CCMD_WRITE_MOUSE, pcimouse_iobase + KBD_CNTL_REG); if (!poll_aux_status()) break; pcimouse_outb(c, pcimouse_iobase + KBD_DATA_REG); written++; } while (--count); spin_unlock_irqrestore(&pcikbd_lock, flags); retval = -EIO; if (written) { retval = written; file->f_dentry->d_inode->i_mtime = CURRENT_TIME; } } return retval;}/* * Generic part continues... *//* * Put bytes from input queue to buffer. */static ssize_t aux_read(struct file * file, char * buffer, size_t count, loff_t *ppos){ DECLARE_WAITQUEUE(wait, current); ssize_t i = count; unsigned char c; if (queue_empty()) { if (file->f_flags & O_NONBLOCK) return -EAGAIN; add_wait_queue(&queue->proc_list, &wait);repeat: set_current_state(TASK_INTERRUPTIBLE); if (queue_empty() && !signal_pending(current)) { schedule(); goto repeat; } current->state = TASK_RUNNING; remove_wait_queue(&queue->proc_list, &wait); } while (i > 0 && !queue_empty()) { c = get_from_queue(); put_user(c, buffer++); i--; } if (count-i) { file->f_dentry->d_inode->i_atime = CURRENT_TIME; return count-i; } if (signal_pending(current)) return -ERESTARTSYS; return 0;}static unsigned int aux_poll(struct file *file, poll_table * wait){ poll_wait(file, &queue->proc_list, wait); if (!queue_empty()) return POLLIN | POLLRDNORM; return 0;}struct file_operations psaux_fops = { owner: THIS_MODULE, read: aux_read, write: aux_write, poll: aux_poll, open: aux_open, release: aux_release, fasync: aux_fasync,};static int aux_no_open(struct inode *inode, struct file *file){ return -ENODEV;}struct file_operations psaux_no_fops = { owner: THIS_MODULE, open: aux_no_open,};static struct miscdevice psaux_mouse = { PSMOUSE_MINOR, "ps2aux", &psaux_fops};static struct miscdevice psaux_no_mouse = { PSMOUSE_MINOR, "ps2aux", &psaux_no_fops};int __init pcimouse_init(void){ struct linux_ebus *ebus; struct linux_ebus_device *edev; struct linux_ebus_child *child; if (pcikbd_mrcoffee) { if ((pcimouse_iobase = pcikbd_iobase) == 0) { printk("pcimouse_init: no 8042 given\n"); goto do_enodev; } pcimouse_irq = 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_MS_NAME1) == 0 || strcmp(child->prom_name, PCI_MS_NAME2) == 0) goto found; } } } } printk("pcimouse_init: no 8042 found\n"); goto do_enodev;found: pcimouse_iobase = child->resource[0].start; pcimouse_irq = child->irqs[0]; } queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL); if (!queue) { printk("pcimouse_init: kmalloc(aux_queue) failed.\n"); return -ENOMEM; } memset(queue, 0, sizeof(*queue)); init_waitqueue_head(&queue->proc_list); if (request_irq(pcimouse_irq, &pcimouse_interrupt, SA_SHIRQ, "mouse", (void *)pcimouse_iobase)) { printk("8042: Cannot register IRQ %s\n", __irq_itoa(pcimouse_irq)); goto do_enodev; } printk("8042(mouse) at %lx (irq %s)\n", pcimouse_iobase, __irq_itoa(pcimouse_irq)); printk("8042: PS/2 auxiliary pointing device detected.\n"); aux_present = 1; pckbd_read_mask = AUX_STAT_OBF; misc_register(&psaux_mouse); spin_lock_irq(&pcikbd_lock); pcimouse_outb(KBD_CCMD_MOUSE_ENABLE, pcimouse_iobase + KBD_CNTL_REG); aux_write_ack(AUX_RESET); aux_write_ack(AUX_SET_SAMPLE); aux_write_ack(100); aux_write_ack(AUX_SET_RES); aux_write_ack(3); aux_write_ack(AUX_SET_SCALE21); poll_aux_status(); pcimouse_outb(KBD_CCMD_MOUSE_DISABLE, pcimouse_iobase + KBD_CNTL_REG); poll_aux_status(); pcimouse_outb(KBD_CCMD_WRITE_MODE, pcimouse_iobase + KBD_CNTL_REG); poll_aux_status(); pcimouse_outb(AUX_INTS_OFF, pcimouse_iobase + KBD_DATA_REG); poll_aux_status(); spin_unlock_irq(&pcikbd_lock); return 0;do_enodev: misc_register(&psaux_no_mouse); return -ENODEV;}int __init pcimouse_no_init(void){ misc_register(&psaux_no_mouse); return -ENODEV;}int __init ps2kbd_probe(void){ int pnode, enode, node, dnode, xnode; int kbnode = 0, msnode = 0, bnode = 0; int devices = 0; char prop[128]; int len;#ifndef __sparc_v9__ /* * MrCoffee has hardware but has no PROM nodes whatsoever. */ len = prom_getproperty(prom_root_node, "name", prop, sizeof(prop)); if (len < 0) { printk("ps2kbd_probe: no name of root node\n"); goto do_enodev; } if (strncmp(prop, "SUNW,JavaStation-1", len) == 0) { pcikbd_mrcoffee = 1; /* Brain damage detected */ goto found; }#endif /* * Get the nodes for keyboard and mouse from aliases on normal systems. */ node = prom_getchild(prom_root_node); node = prom_searchsiblings(node, "aliases"); if (!node) goto do_enodev; len = prom_getproperty(node, "keyboard", prop, sizeof(prop)); if (len > 0) { prop[len] = 0; kbnode = prom_finddevice(prop); } if (!kbnode) goto do_enodev; len = prom_getproperty(node, "mouse", prop, sizeof(prop)); if (len > 0) { prop[len] = 0; msnode = prom_finddevice(prop); } if (!msnode) goto do_enodev; /* * Find matching EBus nodes... */ node = prom_getchild(prom_root_node); pnode = prom_searchsiblings(node, "pci"); /* * Check for SUNW,sabre on Ultra5/10/AXi. */ len = prom_getproperty(pnode, "model", prop, sizeof(prop)); if ((len > 0) && !strncmp(prop, "SUNW,sabre", len)) { pnode = prom_getchild(pnode); pnode = prom_searchsiblings(pnode, "pci"); } /* * For each PCI bus... */ while (pnode) { enode = prom_getchild(pnode); enode = prom_searchsiblings(enode, "ebus"); /* * For each EBus on this PCI... */ while (enode) { node = prom_getchild(enode); bnode = prom_searchsiblings(node, "beeper"); node = prom_getchild(enode); node = prom_searchsiblings(node, "8042"); /* * For each '8042' on this EBus... */ while (node) { dnode = prom_getchild(node); /* * Does it match? */ if ((xnode = prom_searchsiblings(dnode, PCI_KB_NAME1)) == kbnode) { ++devices; } else if ((xnode = prom_searchsiblings(dnode, PCI_KB_NAME2)) == kbnode) { ++devices; } if ((xnode = prom_searchsiblings(dnode, PCI_MS_NAME1)) == msnode) { ++devices; } else if ((xnode = prom_searchsiblings(dnode, PCI_MS_NAME2)) == msnode) { ++devices; } /* * Found everything we need? */ if (devices == 2) goto found; node = prom_getsibling(node); node = prom_searchsiblings(node, "8042"); } enode = prom_getsibling(enode); enode = prom_searchsiblings(enode, "ebus"); } pnode = prom_getsibling(pnode); pnode = prom_searchsiblings(pnode, "pci"); }do_enodev: sunkbd_setinitfunc(pcimouse_no_init); return -ENODEV;found: sunkbd_setinitfunc(pcimouse_init); sunkbd_setinitfunc(pcikbd_init); kbd_ops.compute_shiftstate = pci_compute_shiftstate; kbd_ops.setledstate = pci_setledstate; kbd_ops.getledstate = pci_getledstate; kbd_ops.setkeycode = pci_setkeycode; kbd_ops.getkeycode = pci_getkeycode; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -