OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [input/] [serio/] [pcips2.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * linux/drivers/input/serio/pcips2.c
3
 *
4
 *  Copyright (C) 2003 Russell King, All Rights Reserved.
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License.
9
 *
10
 *  I'm not sure if this is a generic PS/2 PCI interface or specific to
11
 *  the Mobility Electronics docking station.
12
 */
13
#include <linux/module.h>
14
#include <linux/interrupt.h>
15
#include <linux/ioport.h>
16
#include <linux/input.h>
17
#include <linux/pci.h>
18
#include <linux/init.h>
19
#include <linux/serio.h>
20
#include <linux/delay.h>
21
#include <asm/io.h>
22
 
23
#define PS2_CTRL                (0)
24
#define PS2_STATUS              (1)
25
#define PS2_DATA                (2)
26
 
27
#define PS2_CTRL_CLK            (1<<0)
28
#define PS2_CTRL_DAT            (1<<1)
29
#define PS2_CTRL_TXIRQ          (1<<2)
30
#define PS2_CTRL_ENABLE         (1<<3)
31
#define PS2_CTRL_RXIRQ          (1<<4)
32
 
33
#define PS2_STAT_CLK            (1<<0)
34
#define PS2_STAT_DAT            (1<<1)
35
#define PS2_STAT_PARITY         (1<<2)
36
#define PS2_STAT_RXFULL         (1<<5)
37
#define PS2_STAT_TXBUSY         (1<<6)
38
#define PS2_STAT_TXEMPTY        (1<<7)
39
 
40
struct pcips2_data {
41
        struct serio    *io;
42
        unsigned int    base;
43
        struct pci_dev  *dev;
44
};
45
 
46
static int pcips2_write(struct serio *io, unsigned char val)
47
{
48
        struct pcips2_data *ps2if = io->port_data;
49
        unsigned int stat;
50
 
51
        do {
52
                stat = inb(ps2if->base + PS2_STATUS);
53
                cpu_relax();
54
        } while (!(stat & PS2_STAT_TXEMPTY));
55
 
56
        outb(val, ps2if->base + PS2_DATA);
57
 
58
        return 0;
59
}
60
 
61
static irqreturn_t pcips2_interrupt(int irq, void *devid)
62
{
63
        struct pcips2_data *ps2if = devid;
64
        unsigned char status, scancode;
65
        int handled = 0;
66
 
67
        do {
68
                unsigned int flag;
69
 
70
                status = inb(ps2if->base + PS2_STATUS);
71
                if (!(status & PS2_STAT_RXFULL))
72
                        break;
73
                handled = 1;
74
                scancode = inb(ps2if->base + PS2_DATA);
75
                if (status == 0xff && scancode == 0xff)
76
                        break;
77
 
78
                flag = (status & PS2_STAT_PARITY) ? 0 : SERIO_PARITY;
79
 
80
                if (hweight8(scancode) & 1)
81
                        flag ^= SERIO_PARITY;
82
 
83
                serio_interrupt(ps2if->io, scancode, flag);
84
        } while (1);
85
        return IRQ_RETVAL(handled);
86
}
87
 
88
static void pcips2_flush_input(struct pcips2_data *ps2if)
89
{
90
        unsigned char status, scancode;
91
 
92
        do {
93
                status = inb(ps2if->base + PS2_STATUS);
94
                if (!(status & PS2_STAT_RXFULL))
95
                        break;
96
                scancode = inb(ps2if->base + PS2_DATA);
97
                if (status == 0xff && scancode == 0xff)
98
                        break;
99
        } while (1);
100
}
101
 
102
static int pcips2_open(struct serio *io)
103
{
104
        struct pcips2_data *ps2if = io->port_data;
105
        int ret, val = 0;
106
 
107
        outb(PS2_CTRL_ENABLE, ps2if->base);
108
        pcips2_flush_input(ps2if);
109
 
110
        ret = request_irq(ps2if->dev->irq, pcips2_interrupt, IRQF_SHARED,
111
                          "pcips2", ps2if);
112
        if (ret == 0)
113
                val = PS2_CTRL_ENABLE | PS2_CTRL_RXIRQ;
114
 
115
        outb(val, ps2if->base);
116
 
117
        return ret;
118
}
119
 
120
static void pcips2_close(struct serio *io)
121
{
122
        struct pcips2_data *ps2if = io->port_data;
123
 
124
        outb(0, ps2if->base);
125
 
126
        free_irq(ps2if->dev->irq, ps2if);
127
}
128
 
129
static int __devinit pcips2_probe(struct pci_dev *dev, const struct pci_device_id *id)
130
{
131
        struct pcips2_data *ps2if;
132
        struct serio *serio;
133
        int ret;
134
 
135
        ret = pci_enable_device(dev);
136
        if (ret)
137
                goto out;
138
 
139
        ret = pci_request_regions(dev, "pcips2");
140
        if (ret)
141
                goto disable;
142
 
143
        ps2if = kzalloc(sizeof(struct pcips2_data), GFP_KERNEL);
144
        serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
145
        if (!ps2if || !serio) {
146
                ret = -ENOMEM;
147
                goto release;
148
        }
149
 
150
 
151
        serio->id.type          = SERIO_8042;
152
        serio->write            = pcips2_write;
153
        serio->open             = pcips2_open;
154
        serio->close            = pcips2_close;
155
        strlcpy(serio->name, pci_name(dev), sizeof(serio->name));
156
        strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys));
157
        serio->port_data        = ps2if;
158
        serio->dev.parent       = &dev->dev;
159
        ps2if->io               = serio;
160
        ps2if->dev              = dev;
161
        ps2if->base             = pci_resource_start(dev, 0);
162
 
163
        pci_set_drvdata(dev, ps2if);
164
 
165
        serio_register_port(ps2if->io);
166
        return 0;
167
 
168
 release:
169
        kfree(ps2if);
170
        kfree(serio);
171
        pci_release_regions(dev);
172
 disable:
173
        pci_disable_device(dev);
174
 out:
175
        return ret;
176
}
177
 
178
static void __devexit pcips2_remove(struct pci_dev *dev)
179
{
180
        struct pcips2_data *ps2if = pci_get_drvdata(dev);
181
 
182
        serio_unregister_port(ps2if->io);
183
        pci_set_drvdata(dev, NULL);
184
        kfree(ps2if);
185
        pci_release_regions(dev);
186
        pci_disable_device(dev);
187
}
188
 
189
static struct pci_device_id pcips2_ids[] = {
190
        {
191
                .vendor         = 0x14f2,       /* MOBILITY */
192
                .device         = 0x0123,       /* Keyboard */
193
                .subvendor      = PCI_ANY_ID,
194
                .subdevice      = PCI_ANY_ID,
195
                .class          = PCI_CLASS_INPUT_KEYBOARD << 8,
196
                .class_mask     = 0xffff00,
197
        },
198
        {
199
                .vendor         = 0x14f2,       /* MOBILITY */
200
                .device         = 0x0124,       /* Mouse */
201
                .subvendor      = PCI_ANY_ID,
202
                .subdevice      = PCI_ANY_ID,
203
                .class          = PCI_CLASS_INPUT_MOUSE << 8,
204
                .class_mask     = 0xffff00,
205
        },
206
        { 0, }
207
};
208
 
209
static struct pci_driver pcips2_driver = {
210
        .name                   = "pcips2",
211
        .id_table               = pcips2_ids,
212
        .probe                  = pcips2_probe,
213
        .remove                 = __devexit_p(pcips2_remove),
214
};
215
 
216
static int __init pcips2_init(void)
217
{
218
        return pci_register_driver(&pcips2_driver);
219
}
220
 
221
static void __exit pcips2_exit(void)
222
{
223
        pci_unregister_driver(&pcips2_driver);
224
}
225
 
226
module_init(pcips2_init);
227
module_exit(pcips2_exit);
228
 
229
MODULE_LICENSE("GPL");
230
MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
231
MODULE_DESCRIPTION("PCI PS/2 keyboard/mouse driver");
232
MODULE_DEVICE_TABLE(pci, pcips2_ids);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.