1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
/* $Id: uctrl.c,v 1.2 1999/09/07 23:11:08 shadow Exp $
* uctrl.c: TS102 Microcontroller interface on Tadpole Sparcbook 3
*
* Copyright 1999 Derrick J Brashear (shadow@dementia.org)
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/malloc.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/mm.h>
#include <asm/openprom.h>
#include <asm/oplib.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/sbus.h>
#define UCTRL_MINOR 174
struct uctrl_driver {
volatile u32 *regs;
int irq;
};
static struct uctrl_driver drv;
static loff_t
uctrl_llseek(struct file *file, loff_t offset, int type)
{
return -ESPIPE;
}
static int
uctrl_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
switch (cmd) {
default:
return -EINVAL;
}
return 0;
}
static int
uctrl_open(struct inode *inode, struct file *file)
{
MOD_INC_USE_COUNT;
return 0;
}
static int
uctrl_release(struct inode *inode, struct file *file)
{
MOD_DEC_USE_COUNT;
return 0;
}
void uctrl_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct uctrl_driver *driver = (struct uctrl_driver *)dev_id;
printk("in uctrl_interrupt\n");
}
static struct file_operations uctrl_fops = {
uctrl_llseek,
NULL, /* read */
NULL, /* write */
NULL, /* readdir */
NULL, /* poll */
uctrl_ioctl,
NULL, /* mmap */
uctrl_open,
NULL, /* flush */
uctrl_release
};
static struct miscdevice uctrl_dev = {
UCTRL_MINOR,
"uctrl",
&uctrl_fops
};
#ifdef MODULE
int init_module(void)
#else
__initfunc(int uctrl_init(void))
#endif
{
struct uctrl_driver *driver = &drv;
int len;
struct linux_prom_irqs tmp_irq[2];
unsigned int vaddr[2] = { 0, 0 };
int tmpnode, uctrlnode = prom_getchild(prom_root_node);
tmpnode = prom_searchsiblings(uctrlnode, "obio");
if (tmpnode)
uctrlnode = prom_getchild(tmpnode);
uctrlnode = prom_searchsiblings(uctrlnode, "uctrl");
if (!uctrlnode)
return -ENODEV;
/* the prom mapped it for us */
len = prom_getproperty(uctrlnode, "address", (void *) vaddr,
sizeof(vaddr));
driver->regs = vaddr[0];
len = prom_getproperty(uctrlnode, "intr", (char *) tmp_irq,
sizeof(tmp_irq));
if(!driver->irq)
driver->irq = tmp_irq[0].pri;
request_irq(driver->irq, uctrl_interrupt, 0,
"uctrl", driver);
enable_irq(driver->irq);
if (misc_register(&uctrl_dev)) {
printk("%s: unable to get misc minor %d\n",
__FUNCTION__, uctrl_dev.minor);
disable_irq(driver->irq);
free_irq(driver->irq, driver);
return -ENODEV;
}
printk(KERN_INFO, "uctrl: 0x%x (irq %d)\n", driver->regs, __irq_itoa(driver->irq));
return 0;
}
#ifdef MODULE
void cleanup_module(void)
{
struct uctrl_driver *driver = &drv;
misc_deregister(&uctrl_dev);
if (driver->irq) {
disable_irq(driver->irq);
free_irq(driver->irq, driver);
}
if (driver->regs)
driver->regs = 0;
}
#endif
|