Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/rust/whatsys/examples/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 152 B image not shown  

Quelle  pcips2.c   Sprache: unbekannt

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * linux/drivers/input/serio/pcips2.c
 *
 *  Copyright (C) 2003 Russell King, All Rights Reserved.
 *
 *  I'm not sure if this is a generic PS/2 PCI interface or specific to
 *  the Mobility Electronics docking station.
 */

#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/input.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/serio.h>
#include <linux/delay.h>
#include <asm/io.h>

#define PS2_CTRL  (0)
#define PS2_STATUS  (1)
#define PS2_DATA  (2)

#define PS2_CTRL_CLK  (1<<0)
#define PS2_CTRL_DAT  (1<<1)
#define PS2_CTRL_TXIRQ  (1<<2)
#define PS2_CTRL_ENABLE  (1<<3)
#define PS2_CTRL_RXIRQ  (1<<4)

#define PS2_STAT_CLK  (1<<0)
#define PS2_STAT_DAT  (1<<1)
#define PS2_STAT_PARITY  (1<<2)
#define PS2_STAT_RXFULL  (1<<5)
#define PS2_STAT_TXBUSY  (1<<6)
#define PS2_STAT_TXEMPTY (1<<7)

struct pcips2_data {
 struct serio *io;
 unsigned int base;
 struct pci_dev *dev;
};

static int pcips2_write(struct serio *io, unsigned char val)
{
 struct pcips2_data *ps2if = io->port_data;
 unsigned int stat;

 do {
  stat = inb(ps2if->base + PS2_STATUS);
  cpu_relax();
 } while (!(stat & PS2_STAT_TXEMPTY));

 outb(val, ps2if->base + PS2_DATA);

 return 0;
}

static irqreturn_t pcips2_interrupt(int irq, void *devid)
{
 struct pcips2_data *ps2if = devid;
 unsigned char status, scancode;
 int handled = 0;

 do {
  unsigned int flag;

  status = inb(ps2if->base + PS2_STATUS);
  if (!(status & PS2_STAT_RXFULL))
   break;
  handled = 1;
  scancode = inb(ps2if->base + PS2_DATA);
  if (status == 0xff && scancode == 0xff)
   break;

  flag = (status & PS2_STAT_PARITY) ? 0 : SERIO_PARITY;

  if (hweight8(scancode) & 1)
   flag ^= SERIO_PARITY;

  serio_interrupt(ps2if->io, scancode, flag);
 } while (1);
 return IRQ_RETVAL(handled);
}

static void pcips2_flush_input(struct pcips2_data *ps2if)
{
 unsigned char status, scancode;

 do {
  status = inb(ps2if->base + PS2_STATUS);
  if (!(status & PS2_STAT_RXFULL))
   break;
  scancode = inb(ps2if->base + PS2_DATA);
  if (status == 0xff && scancode == 0xff)
   break;
 } while (1);
}

static int pcips2_open(struct serio *io)
{
 struct pcips2_data *ps2if = io->port_data;
 int ret, val = 0;

 outb(PS2_CTRL_ENABLE, ps2if->base);
 pcips2_flush_input(ps2if);

 ret = request_irq(ps2if->dev->irq, pcips2_interrupt, IRQF_SHARED,
     "pcips2", ps2if);
 if (ret == 0)
  val = PS2_CTRL_ENABLE | PS2_CTRL_RXIRQ;

 outb(val, ps2if->base);

 return ret;
}

static void pcips2_close(struct serio *io)
{
 struct pcips2_data *ps2if = io->port_data;

 outb(0, ps2if->base);

 free_irq(ps2if->dev->irq, ps2if);
}

static int pcips2_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
 struct pcips2_data *ps2if;
 struct serio *serio;
 int ret;

 ret = pci_enable_device(dev);
 if (ret)
  goto out;

 ret = pci_request_regions(dev, "pcips2");
 if (ret)
  goto disable;

 ps2if = kzalloc(sizeof(*ps2if), GFP_KERNEL);
 serio = kzalloc(sizeof(*serio), GFP_KERNEL);
 if (!ps2if || !serio) {
  ret = -ENOMEM;
  goto release;
 }


 serio->id.type  = SERIO_8042;
 serio->write  = pcips2_write;
 serio->open  = pcips2_open;
 serio->close  = pcips2_close;
 strscpy(serio->name, pci_name(dev), sizeof(serio->name));
 strscpy(serio->phys, dev_name(&dev->dev), sizeof(serio->phys));
 serio->port_data = ps2if;
 serio->dev.parent = &dev->dev;
 ps2if->io  = serio;
 ps2if->dev  = dev;
 ps2if->base  = pci_resource_start(dev, 0);

 pci_set_drvdata(dev, ps2if);

 serio_register_port(ps2if->io);
 return 0;

 release:
 kfree(ps2if);
 kfree(serio);
 pci_release_regions(dev);
 disable:
 pci_disable_device(dev);
 out:
 return ret;
}

static void pcips2_remove(struct pci_dev *dev)
{
 struct pcips2_data *ps2if = pci_get_drvdata(dev);

 serio_unregister_port(ps2if->io);
 kfree(ps2if);
 pci_release_regions(dev);
 pci_disable_device(dev);
}

static const struct pci_device_id pcips2_ids[] = {
 {
  .vendor  = 0x14f2, /* MOBILITY */
  .device  = 0x0123, /* Keyboard */
  .subvendor = PCI_ANY_ID,
  .subdevice = PCI_ANY_ID,
  .class  = PCI_CLASS_INPUT_KEYBOARD << 8,
  .class_mask = 0xffff00,
 },
 {
  .vendor  = 0x14f2, /* MOBILITY */
  .device  = 0x0124, /* Mouse */
  .subvendor = PCI_ANY_ID,
  .subdevice = PCI_ANY_ID,
  .class  = PCI_CLASS_INPUT_MOUSE << 8,
  .class_mask = 0xffff00,
 },
 { 0, }
};
MODULE_DEVICE_TABLE(pci, pcips2_ids);

static struct pci_driver pcips2_driver = {
 .name   = "pcips2",
 .id_table  = pcips2_ids,
 .probe   = pcips2_probe,
 .remove   = pcips2_remove,
};

module_pci_driver(pcips2_driver);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Russell King ");
MODULE_DESCRIPTION("PCI PS/2 keyboard/mouse driver");

Messung V0.5
C=98 H=78 G=88

[ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet)  ]