Skip to content

Commit 15b2603

Browse files
Constantine ShulyupinConstantine Shulyupin
Constantine Shulyupin
authored and
Constantine Shulyupin
committed
+misc_drv.c fixes, +pr_fmt, removed timer
1 parent 015c0c4 commit 15b2603

File tree

5 files changed

+97
-91
lines changed

5 files changed

+97
-91
lines changed

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
ccflags-y+=-DDEBUG
33
ccflags-y+=-DUSE_PLATFORM_DEVICE
44
ccflags-y+=-fmax-errors=5
5+
#ccflags-y+=-DCTRACER_ON -include $M/ctracer.h
56
#ccflags-y+=-D USE_MISCDEV # uncomment to use single misc device instead char devices region
67

78
obj-m+= ldt.o
@@ -10,6 +11,7 @@ obj-m+= ldt_plat_dev.o # implements platform_device and resource
1011
#obj-m+= chrdev_region_sample.o
1112
obj-m+= ldt_configfs_basic.o
1213
obj-m+= kthread_sample.o
14+
obj-m+= misc_drv.o
1315

1416
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
1517

kthread_sample.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ static int thread_sample(void *data)
1010
while (!kthread_should_stop()) {
1111
ret = wait_for_completion_interruptible(&completion);
1212
if (ret == -ERESTARTSYS) {
13-
pr_debug("%s: %s\n", __func__, "interrupted");
13+
pr_debug("interrupted\n");
1414
return -EINTR;
1515
}
1616
/*

ldt_plat_drv.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,11 @@ static __devinit int ldt_plat_probe(struct platform_device *pdev)
4444
property = be32_to_cpu(*p);
4545
}
4646
#endif
47-
//struct ldt_data *drvdata = platform_get_drvdata(pdev);
48-
//platform_set_drvdata(pdev, drvdata);
47+
/*
48+
sample code for drvdata usage:
49+
struct ldt_data *drvdata = platform_get_drvdata(pdev);
50+
platform_set_drvdata(pdev, drvdata);
51+
*/
4952

5053
data = dev_get_platdata(&pdev->dev);
5154
pr_debug("%p %s\n", data, data);

misc_drv.c

Lines changed: 39 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
* kfifo
1919
* interrupt
2020
* tasklet
21-
* timer
2221
* driven by IRQ 6
2322
*
2423
* Run test script misc-drv-test to test the driver
@@ -31,7 +30,6 @@
3130
#include <linux/interrupt.h>
3231
#include <linux/sched.h>
3332
#include <linux/delay.h>
34-
#include <linux/timer.h>
3533
#include <linux/kfifo.h>
3634
#include <linux/fs.h>
3735
#include <linux/poll.h>
@@ -42,6 +40,9 @@
4240
#include <linux/cdev.h>
4341
#include <asm/apic.h>
4442

43+
#undef pr_fmt
44+
#define pr_fmt(fmt) "%s.c:%d %s " fmt, KBUILD_MODNAME, __LINE__, __func__
45+
4546
static int port = 0x3f4;
4647
module_param(port, int, 0);
4748
MODULE_PARM_DESC(port, "io port number, default 0x3f4 - floppy");
@@ -54,13 +55,15 @@ static int irq = 6;
5455
module_param(irq, int, 0);
5556
MODULE_PARM_DESC(irq, "interrupt request number, default 6 - floppy");
5657

58+
5759
#define FIFO_SIZE 128 /* must be power of two */
5860

5961
#define MISC_DRV_TX 0
6062
#define MISC_DRV_RX 0
6163
#define MISC_DRV_TX_FULL 1
6264
#define MISC_DRV_RX_READY 1
6365

66+
static char port_emulation[2];
6467

6568
/**
6669
* struct misc_drv_data - the driver data
@@ -83,9 +86,7 @@ struct misc_drv_data {
8386
spinlock_t fifo_lock;
8487
wait_queue_head_t readable, writeable;
8588
struct tasklet_struct misc_drv_tasklet;
86-
struct timer_list misc_drv_timer;
87-
//void __iomem *port_ptr;
88-
void *port_ptr;
89+
void __iomem *port_ptr;
8990
struct resource *port_res;
9091
};
9192

@@ -95,81 +96,53 @@ static void misc_drv_tasklet_func(unsigned long d)
9596
{
9697
char data_out, data_in;
9798
struct misc_drv_data *drvdata = (void*) d;
98-
int tx_ready, rx_ready;
9999

100-
tx_ready = !ioread8(drvdata->port_ptr + MISC_DRV_TX_FULL);
101-
102-
while (tx_ready && kfifo_out_spinlocked(&drvdata->out_fifo,
100+
while ( !ioread8(drvdata->port_ptr + MISC_DRV_TX_FULL)
101+
&& kfifo_out_spinlocked(&drvdata->out_fifo,
103102
&data_out, sizeof(data_out), &drvdata->fifo_lock)) {
104103
wake_up_interruptible(&drvdata->writeable);
105-
pr_debug("%s: data_out=%d %c\n", __func__, data_out, data_out >= 32 ? data_out : ' ');
104+
pr_debug("data_out=%d %c\n", data_out, data_out >= 32 ? data_out : ' ');
106105
iowrite8(data_out, drvdata->port_ptr + MISC_DRV_TX);
107-
/* set flag full and implicitly flag ready */
106+
/* set full flag and implicitly ready flag */
108107
iowrite8(1, drvdata->port_ptr + MISC_DRV_TX_FULL);
109108
/*
110109
In regular drivers hardware invokes interrupts.
111110
Because this drivers works without real hardware
112111
we simulate interrupt invocation with function send_IPI_all.
113112
In driver, which works with real hardware this is not required.
114113
*/
115-
//apic->send_IPI_all(IRQ0_VECTOR+irq);
114+
apic->send_IPI_all(IRQ0_VECTOR+irq);
116115
}
117116
while (ioread8(drvdata->port_ptr + MISC_DRV_RX_READY)) {
118117
data_in = ioread8(drvdata->port_ptr + MISC_DRV_RX);
119-
pr_debug("%s: data_in=%d %c\n", __func__, data_in, data_in >= 32 ? data_in : ' ');
118+
pr_debug("data_in=%d %c\n", data_in, data_in >= 32 ? data_in : ' ');
120119
kfifo_in_spinlocked(&drvdata->in_fifo, &data_in,
121120
sizeof(data_in), &drvdata->fifo_lock);
122121
wake_up_interruptible(&drvdata->readable);
123-
/* clear flag ready and implicitly flag full */
122+
/* clear ready flag and implicitly full flag */
124123
iowrite8(0, drvdata->port_ptr + MISC_DRV_RX_READY);
125124
}
126125
}
127126

128-
/*
129-
* interrupt section
130-
*/
131-
132-
static int isr_counter;
133-
134127
static irqreturn_t misc_drv_isr(int irq, void *d)
135128
{
136129
struct misc_drv_data *drvdata = (void*) d;
137-
isr_counter++;
138-
//tasklet_schedule(&drvdata->misc_drv_tasklet);
139-
return IRQ_HANDLED; /* our IRQ */
140-
}
141130

142-
/*
143-
* timer section
144-
*/
145-
146-
static void misc_drv_timer_func(unsigned long d)
147-
{
148-
struct misc_drv_data *drvdata = (void*) d;
149-
/*
150-
* this timer is used just to fire drvdata->misc_drv_tasklet,
151-
* because there is no interrupts in loopback mode
152-
*/
153-
//if (loopback)
154131
tasklet_schedule(&drvdata->misc_drv_tasklet);
155-
mod_timer(&drvdata->misc_drv_timer, jiffies + HZ / 100);
132+
return IRQ_HANDLED;
156133
}
157134

158-
/*
159-
* file_operations section
160-
*/
161-
162135
static int misc_drv_open(struct inode *inode, struct file *file)
163136
{
164-
pr_debug("%s: from %s\n", __func__, current->comm);
137+
pr_debug("from %s\n", current->comm);
165138
/* client related data can be allocated here and
166139
stored in file->private_data */
167140
return 0;
168141
}
169142

170143
static int misc_drv_release(struct inode *inode, struct file *file)
171144
{
172-
pr_debug("%s: from %s\n", __func__,current->comm);
145+
pr_debug("from %s\n", current->comm);
173146
/* client related data can be retrieved from file->private_data
174147
and released here */
175148
return 0;
@@ -181,16 +154,16 @@ static ssize_t misc_drv_read(struct file *file, char __user *buf,
181154
int ret = 0;
182155
unsigned int copied;
183156

184-
pr_debug("%s: from %s\n", __func__, current->comm);
157+
pr_debug("from %s\n", current->comm);
185158
if (kfifo_is_empty(&drvdata->in_fifo)) {
186159
if (file->f_flags & O_NONBLOCK) {
187160
return -EAGAIN;
188161
} else {
189-
pr_debug("%s: %s\n", __func__, "waiting");
162+
pr_debug("%s\n", "waiting");
190163
ret = wait_event_interruptible(drvdata->readable,
191164
!kfifo_is_empty(&drvdata->in_fifo));
192165
if (ret == -ERESTARTSYS) {
193-
pr_err("%s:%d %s %s\n", __FILE__, __LINE__, __func__, "interrupted");
166+
pr_err("interrupted\n");
194167
return -EINTR;
195168
}
196169
}
@@ -199,8 +172,7 @@ static ssize_t misc_drv_read(struct file *file, char __user *buf,
199172
return -EINTR;
200173
ret = kfifo_to_user(&drvdata->in_fifo, buf, count, &copied);
201174
mutex_unlock(&drvdata->read_lock);
202-
trvd(ret);
203-
trvd(copied);
175+
204176
return ret ? ret : copied;
205177
}
206178

@@ -209,18 +181,16 @@ static ssize_t misc_drv_write(struct file *file, const char __user *buf,
209181
{
210182
int ret;
211183
unsigned int copied;
212-
trl();
213-
trvp(drvdata);
214184

215-
pr_debug("%s: from %s\n", __func__,current->comm);
185+
pr_debug("from %s\n", current->comm);
216186
if (kfifo_is_full(&drvdata->out_fifo)) {
217187
if (file->f_flags & O_NONBLOCK) {
218188
return -EAGAIN;
219189
} else {
220190
ret = wait_event_interruptible(drvdata->writeable,
221191
!kfifo_is_full(&drvdata->out_fifo));
222192
if (ret == -ERESTARTSYS) {
223-
pr_err("%s:%d %s %s\n", __FILE__, __LINE__, __func__, "interrupted");
193+
pr_err("interrupted\n");
224194
return -EINTR;
225195
}
226196
}
@@ -230,6 +200,7 @@ static ssize_t misc_drv_write(struct file *file, const char __user *buf,
230200
ret = kfifo_from_user(&drvdata->out_fifo, buf, count, &copied);
231201
mutex_unlock(&drvdata->write_lock);
232202
tasklet_schedule(&drvdata->misc_drv_tasklet);
203+
233204
return ret ? ret : copied;
234205
}
235206

@@ -251,23 +222,6 @@ static unsigned int misc_drv_poll(struct file *file, poll_table *pt)
251222
return mask;
252223
}
253224

254-
/*
255-
* pages_flag - set or clear a flag for sequence of pages
256-
*
257-
* more generic solution instead SetPageReserved, ClearPageReserved etc
258-
*
259-
* Poposing to move pages_flag to linux/page-flags.h
260-
*/
261-
262-
static void pages_flag(struct page *page, int page_num, int mask, int value)
263-
{
264-
for (; page_num; page_num--, page++)
265-
if (value)
266-
__set_bit(mask, &page->flags);
267-
else
268-
__clear_bit(mask, &page->flags);
269-
}
270-
271225
static const struct file_operations misc_drv_fops = {
272226
.owner = THIS_MODULE,
273227
.open = misc_drv_open,
@@ -291,13 +245,11 @@ static void misc_drv_cleanup(void)
291245
{
292246
if (misc_drv_dev.this_device)
293247
misc_deregister(&misc_drv_dev);
294-
//del_timer(&drvdata->misc_drv_timer);
295248
if (irq) {
296249
free_irq(irq, drvdata);
297250
}
298251
tasklet_kill(&drvdata->misc_drv_tasklet);
299252

300-
pr_debug("%s: isr_counter=%d\n", __func__, isr_counter);
301253
if (drvdata->port_ptr) ioport_unmap(drvdata->port_ptr);
302254
if (drvdata->port_res)
303255
release_region(port, port_size);
@@ -311,16 +263,13 @@ struct misc_drv_data * misc_drv_data_init(void)
311263
drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
312264
if (!drvdata)
313265
return NULL;
314-
trl();
315-
trvp(drvdata);
316266
init_waitqueue_head(&drvdata->readable);
317267
init_waitqueue_head(&drvdata->writeable);
318268
INIT_KFIFO(drvdata->in_fifo);
319269
INIT_KFIFO(drvdata->out_fifo);
320270
mutex_init(&drvdata->read_lock);
321271
mutex_init(&drvdata->write_lock);
322272
tasklet_init(&drvdata->misc_drv_tasklet, misc_drv_tasklet_func, (unsigned long)drvdata);
323-
//setup_timer(&drvdata->misc_drv_timer, misc_drv_timer_func,(unsigned long)drvdata);
324273
return drvdata;
325274
}
326275

@@ -334,41 +283,43 @@ static __devinit int misc_drv_init(void)
334283

335284
drvdata = misc_drv_data_init();
336285
if (!drvdata) {
337-
pr_err("%s:%d %s %s\n", __FILE__, __LINE__, __func__, "misc_drv_data_init failed");
286+
pr_err("misc_drv_data_init failed\n");
338287
goto exit;
339288
}
340289

341290
drvdata->port_res = request_region(port, port_size, KBUILD_MODNAME);
342291
if (!drvdata->port_res) {
343-
pr_err("%s:%d %s %s\n", __FILE__, __LINE__, __func__, "request_region failed");
292+
pr_err("request_region failed\n");
344293
return -EBUSY;
345294
}
346-
//drvdata->port_ptr = a;
347-
348-
drvdata->port_ptr = ioport_map(port, port_size);
349-
pr_debug("%s: drvdata->port_ptr=%p\n", __func__, drvdata->port_ptr);
295+
/*
296+
Real port can mappled with function with ioport_map:
297+
drvdata->port_ptr = ioport_map(port, port_size);
298+
But, because we use emulation mode, we use array instead mapped ports
299+
*/
300+
drvdata->port_ptr = port_emulation;
350301
if (!drvdata->port_ptr) {
351-
pr_err("%s:%d %s %s\n", __FILE__, __LINE__, __func__, "ioport_map failed");
302+
pr_err("ioport_map failed\n");
352303
return -ENODEV;
353304
}
354-
trvp(drvdata->port_ptr);
355-
356-
isr_counter = 0;
305+
/* clear ports */
306+
iowrite8(0, drvdata->port_ptr + MISC_DRV_TX);
307+
iowrite8(0, drvdata->port_ptr + MISC_DRV_TX_FULL);
357308

358309
ret = misc_register(&misc_drv_dev);
359310
if (ret < 0) {
360-
pr_err("%s:%d %s %s\n", __FILE__, __LINE__, __func__, "misc_register failed");
311+
pr_err("misc_register failed\n");
361312
goto exit;
362313
}
363-
pr_debug("%s: misc_drv_dev.minor=%d\n", __func__, misc_drv_dev.minor);
314+
pr_debug("misc_drv_dev.minor=%d\n", misc_drv_dev.minor);
364315
ret = request_irq(irq, misc_drv_isr, 0, KBUILD_MODNAME, drvdata);
365316
if (ret < 0) {
366-
pr_err("%s:%d %s %s\n", __FILE__, __LINE__, __func__, "request_irq failed");
317+
pr_err("request_irq failed\n");
367318
return ret;
368319
}
369320

370321
exit:
371-
pr_debug("%s: ret=%d\n", __func__, ret);
322+
pr_debug("ret=%d\n", ret);
372323
if (ret < 0)
373324
misc_drv_cleanup();
374325
return ret;

0 commit comments

Comments
 (0)