1 #include <linux/init.h>
2 #include <linux/module.h>
4 #include <linux/types.h>
6 #include <asm/uaccess.h>
7 #include <linux/poll.h>
8 #include <linux/sched.h>
9 #include <linux/interrupt.h>
10 #include <asm/delay.h>
12 static const char *version
= "$Id: dhwk.c,v 1.1 2007-03-10 22:35:54 sithglan Exp $";
13 static unsigned long ioaddr
;
14 static unsigned long locks
;
16 #define BUFFER_SIZE 32768
18 static unsigned char send_buffer
[BUFFER_SIZE
];
19 static unsigned char recv_buffer
[BUFFER_SIZE
];
21 static wait_queue_head_t send_wq
;
22 static wait_queue_head_t receive_wq
;
23 static u8 irq
; /* FIXME: Get it from the pci struct */
24 static int my_dhwk_dev_id
;
26 MODULE_LICENSE("Dual BSD/GPL");
28 #define MODULE_NAME "dhwk"
31 #define INTERRUPTS_PLEASE 1
33 #define SDR (ioaddr + 0)
34 #define RDR (ioaddr + 2)
35 #define ISR (ioaddr + 4)
36 #define CTR (ioaddr + 6)
39 dhwk_open(struct inode
*inode
, struct file
*f
)
41 if (iminor(inode
) != 0) {
47 if (( (f
->f_flags
& O_ACCMODE
) == O_RDONLY
48 || (f
->f_flags
& O_ACCMODE
) == O_RDWR
)
50 if (f
->f_flags
& O_NONBLOCK
) {
59 if (( (f
->f_flags
& O_ACCMODE
) == O_WRONLY
60 || (f
->f_flags
& O_ACCMODE
) == O_RDWR
)
62 if (f
->f_flags
& O_NONBLOCK
) {
71 if (( (f
->f_flags
& O_ACCMODE
) == O_RDONLY
72 || (f
->f_flags
& O_ACCMODE
) == O_RDWR
)) {
73 test_and_set_bit(0, &locks
);
76 if (( (f
->f_flags
& O_ACCMODE
) == O_WRONLY
77 || (f
->f_flags
& O_ACCMODE
) == O_RDWR
)) {
78 test_and_set_bit(1, &locks
);
85 dhwk_release(struct inode
*i
, struct file
*f
)
88 if (( (f
->f_flags
& O_ACCMODE
) == O_RDONLY
89 || (f
->f_flags
& O_ACCMODE
) == O_RDWR
)) {
93 if (( (f
->f_flags
& O_ACCMODE
) == O_WRONLY
94 || (f
->f_flags
& O_ACCMODE
) == O_RDWR
)) {
102 dhwk_read(struct file
*f
, char __user
*u
, size_t size
, loff_t
*offset
)
109 if (! access_ok(VERIFY_WRITE
, u
, size
)) {
113 while (count
< size
) {
117 if (next_status
== 0) {
119 if (! (status
& 0x0200)) {
120 /* Receive FIFO Empty */
121 if (f
->f_flags
& O_NONBLOCK
) {
122 __copy_to_user(u
+ count
- (count
% BUFFER_SIZE
),
123 recv_buffer
, count
% BUFFER_SIZE
+ 1);
127 #if INTERRUPTS_PLEASE
128 wait_event_interruptible(receive_wq
, inw(ISR
) & 0x0200);
129 if (signal_pending(current
)) {
135 goto dhwk_read_again
;
138 } else if (! (status
& 0x0400)) {
139 /* Receive FIFO Half Full */
150 if ((word
& 0xFF) != 0xc3) {
151 short debug_enable
= inw(ioaddr
+ 8);
152 printk(KERN_ALERT
"dhwk: Fehler: 0x%08x\n", 0x00 | word
);
156 recv_buffer
[count
% BUFFER_SIZE
] = (unsigned char) word
;
158 if (count
% BUFFER_SIZE
== (BUFFER_SIZE
- 1)
159 || count
== (size
- 1)) {
160 __copy_to_user(u
+ count
- (count
% BUFFER_SIZE
),
161 recv_buffer
, count
% BUFFER_SIZE
+ 1);
171 dhwk_write(struct file
*f
, const char __user
*u
, size_t size
, loff_t
*offset
)
178 if (! access_ok(VERIFY_READ
, u
, size
)) {
182 while (count
< size
) {
183 if (grabbed
<= count
) {
184 __copy_from_user(send_buffer
, u
+ count
,
185 (size
- count
) < BUFFER_SIZE
? (size
- count
) : BUFFER_SIZE
);
186 grabbed
+= (size
- count
) < BUFFER_SIZE
? (size
- count
) : BUFFER_SIZE
;
191 if (next_status
== 0) {
193 if (! (status
& 0x8000)) {
195 if (f
->f_flags
& O_NONBLOCK
) {
199 #if INTERRUPTS_PLEASE
200 wait_event_interruptible(send_wq
, inw(ISR
) & 0x0800);
201 if (signal_pending(current
)) {
207 goto dhwk_write_again
;
210 } else if (status
& 0x4000) {
211 /* Send FIFO not HALF Full */
218 outw(0x0000 | send_buffer
[count
% BUFFER_SIZE
], SDR
);
226 dhwk_poll(struct file
*f
, struct poll_table_struct
*pts
)
235 if (( (f
->f_flags
& O_ACCMODE
) == O_RDONLY
236 || (f
->f_flags
& O_ACCMODE
) == O_RDWR
)) {
237 if (f
->f_flags
& O_NONBLOCK
) {
239 mask
|= POLLIN
| POLLRDNORM
;
247 goto dhwk_poll_again
;
251 if (( (f
->f_flags
& O_ACCMODE
) == O_WRONLY
252 || (f
->f_flags
& O_ACCMODE
) == O_RDWR
)) {
253 if ((f
->f_flags
& O_NONBLOCK
)) {
254 /* If write is possible */
255 if (! (reg
& 0x8000)) {
256 mask
|= POLLOUT
| POLLWRNORM
;
264 goto dhwk_poll_again
;
273 dhwk_pci_init(struct pci_dev
*pdev
, const struct pci_device_id
*ent
)
277 printk(KERN_ALERT
"dhwk: Gruppe 2: %s\n", version
);
279 ret
= pci_enable_device(pdev
);
281 printk(KERN_ERR
"dhwk: Could not enable pci device.\n");
282 pci_disable_device(pdev
);
286 ret
= pci_request_regions(pdev
, MODULE_NAME
);
288 printk(KERN_ERR
"dhwk: Could not request regions.\n");
289 pci_disable_device(pdev
);
295 ioaddr
= pci_resource_start(pdev
, 0);
296 printk(KERN_ALERT
"dhwk: ioaddr at 0x%08x irq 0x%02x\n", (unsigned int) ioaddr
, irq
);
298 /* Pull Reset (twice) */
304 /* CLEAR WRONG STATUS */
308 /* Enable Sender and Receiver and all available Interrupts */
309 while ((inw(CTR
) & 0x06FF) != 0x06FF) {
315 static void __devexit
316 dhwk_pci_exit(struct pci_dev
*pdev
)
320 ret
= inw(ISR
); /* Get pending interrupts down */
322 pci_release_regions(pdev
);
323 pci_disable_device(pdev
);
324 pci_set_drvdata(pdev
, NULL
);
325 printk(KERN_ALERT
"dhwk: Gruppe 2: Module unloaded.\n");
328 static struct pci_device_id dhwk_pci_tbl
[] = {
329 {0x2222, 0xaffe, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0}, /* FIXME */
331 {0xbaff, 0xaffe, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0}, /* FIXME */
336 static struct pci_driver dhwk_pci_driver
= {
338 .id_table
= dhwk_pci_tbl
,
339 .probe
= dhwk_pci_init
,
340 .remove
= dhwk_pci_exit
,
343 struct file_operations dhwk_fops
= {
344 .owner
= THIS_MODULE
,
349 .release
= dhwk_release
,
353 interrupt_handler(int irq_to_check
, void *dev_id
, struct pt_regs
*regs
)
355 register unsigned short status
;
358 if (status
& 0x0200) {
359 wake_up_interruptible(& receive_wq
);
362 if (status
& 0x8000) {
363 wake_up_interruptible(& send_wq
);
366 if (irq_to_check
== irq
) {
379 ret
= pci_module_init(& dhwk_pci_driver
);
384 ret
= register_chrdev(DHWK_MAJOR
, MODULE_NAME
, & dhwk_fops
);
386 printk (KERN_ALERT
"dhwk: unable to get major %d\n", DHWK_MAJOR
);
387 pci_unregister_driver(& dhwk_pci_driver
);
391 init_waitqueue_head(& send_wq
);
392 init_waitqueue_head(& receive_wq
);
394 #if INTERRUPTS_PLEASE
396 ret
= request_irq(irq
, interrupt_handler
, SA_INTERRUPT
, "dhwk", &my_dhwk_dev_id
);
398 ret
= request_irq(irq
, interrupt_handler
, SA_SHIRQ
, "dhwk", &my_dhwk_dev_id
);
400 printk (KERN_ALERT
"dhwk: unable to register interrupt %d\n", irq
);
401 pci_unregister_driver(& dhwk_pci_driver
);
402 unregister_chrdev(DHWK_MAJOR
, MODULE_NAME
);
413 free_irq(irq
, &my_dhwk_dev_id
);
414 pci_unregister_driver(& dhwk_pci_driver
);
415 unregister_chrdev(DHWK_MAJOR
, MODULE_NAME
);
418 module_init(dhwk_init
);
419 module_exit(dhwk_exit
);