diff options
Diffstat (limited to 'drivers/firewire/nosy.c')
-rw-r--r-- | drivers/firewire/nosy.c | 322 |
1 files changed, 153 insertions, 169 deletions
diff --git a/drivers/firewire/nosy.c b/drivers/firewire/nosy.c index 079710bf1197..ea392d0985a5 100644 --- a/drivers/firewire/nosy.c +++ b/drivers/firewire/nosy.c | |||
@@ -1,7 +1,6 @@ | |||
1 | /* -*- c-file-style: "linux" -*- | 1 | /* |
2 | * | 2 | * nosy - Snoop mode driver for TI PCILynx 1394 controllers |
3 | * nosy.c - Snoop mode driver for TI pcilynx 1394 controllers | 3 | * Copyright (C) 2002-2007 Kristian Høgsberg |
4 | * Copyright (C) 2002 Kristian Høgsberg | ||
5 | * | 4 | * |
6 | * This program is free software; you can redistribute it and/or modify | 5 | * 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 | 6 | * it under the terms of the GNU General Public License as published by |
@@ -18,23 +17,25 @@ | |||
18 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 17 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
19 | */ | 18 | */ |
20 | 19 | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/sched.h> /* required for linux/wait.h */ | ||
25 | #include <linux/wait.h> | ||
26 | #include <linux/errno.h> | 20 | #include <linux/errno.h> |
27 | #include <linux/module.h> | 21 | #include <linux/fs.h> |
28 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/io.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/miscdevice.h> | ||
27 | #include <linux/module.h> | ||
29 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
30 | #include <linux/fs.h> | ||
31 | #include <linux/poll.h> | 29 | #include <linux/poll.h> |
32 | #include <linux/miscdevice.h> | 30 | #include <linux/sched.h> /* required for linux/wait.h */ |
33 | #include <asm/byteorder.h> | 31 | #include <linux/slab.h> |
32 | #include <linux/spinlock.h> | ||
33 | #include <linux/timex.h> | ||
34 | #include <linux/uaccess.h> | ||
35 | #include <linux/wait.h> | ||
36 | |||
34 | #include <asm/atomic.h> | 37 | #include <asm/atomic.h> |
35 | #include <asm/io.h> | 38 | #include <asm/byteorder.h> |
36 | #include <asm/uaccess.h> | ||
37 | #include <asm/timex.h> | ||
38 | 39 | ||
39 | #include "nosy.h" | 40 | #include "nosy.h" |
40 | #include "nosy-user.h" | 41 | #include "nosy-user.h" |
@@ -46,7 +47,7 @@ | |||
46 | #define error(s, args...) printk(KERN_ERR s, ## args) | 47 | #define error(s, args...) printk(KERN_ERR s, ## args) |
47 | #define debug(s, args...) printk(KERN_DEBUG s, ## args) | 48 | #define debug(s, args...) printk(KERN_DEBUG s, ## args) |
48 | 49 | ||
49 | static const char driver_name[] = "nosy"; | 50 | static char driver_name[] = KBUILD_MODNAME; |
50 | 51 | ||
51 | struct pcl_status { | 52 | struct pcl_status { |
52 | unsigned int transfer_count : 13; | 53 | unsigned int transfer_count : 13; |
@@ -77,8 +78,7 @@ struct pcl { | |||
77 | } __attribute__ ((packed)); | 78 | } __attribute__ ((packed)); |
78 | 79 | ||
79 | struct packet { | 80 | struct packet { |
80 | unsigned int length : 16; | 81 | unsigned int length; |
81 | unsigned int code : 16; | ||
82 | char data[0]; | 82 | char data[0]; |
83 | }; | 83 | }; |
84 | 84 | ||
@@ -87,8 +87,8 @@ struct packet_buffer { | |||
87 | size_t capacity; | 87 | size_t capacity; |
88 | long total_packet_count, lost_packet_count; | 88 | long total_packet_count, lost_packet_count; |
89 | atomic_t size; | 89 | atomic_t size; |
90 | struct packet *head, *tail; | 90 | struct packet *head, *tail; |
91 | wait_queue_head_t wait; | 91 | wait_queue_head_t wait; |
92 | }; | 92 | }; |
93 | 93 | ||
94 | struct pcilynx { | 94 | struct pcilynx { |
@@ -106,7 +106,6 @@ struct pcilynx { | |||
106 | struct miscdevice misc; | 106 | struct miscdevice misc; |
107 | }; | 107 | }; |
108 | 108 | ||
109 | |||
110 | struct client { | 109 | struct client { |
111 | struct pcilynx *lynx; | 110 | struct pcilynx *lynx; |
112 | unsigned long tcode_mask; | 111 | unsigned long tcode_mask; |
@@ -115,7 +114,7 @@ struct client { | |||
115 | }; | 114 | }; |
116 | 115 | ||
117 | #define MAX_MINORS 64 | 116 | #define MAX_MINORS 64 |
118 | struct pcilynx *minors[MAX_MINORS]; | 117 | static struct pcilynx *minors[MAX_MINORS]; |
119 | 118 | ||
120 | static int | 119 | static int |
121 | packet_buffer_init(struct packet_buffer *buffer, size_t capacity) | 120 | packet_buffer_init(struct packet_buffer *buffer, size_t capacity) |
@@ -128,7 +127,7 @@ packet_buffer_init(struct packet_buffer *buffer, size_t capacity) | |||
128 | buffer->capacity = capacity; | 127 | buffer->capacity = capacity; |
129 | buffer->lost_packet_count = 0; | 128 | buffer->lost_packet_count = 0; |
130 | atomic_set(&buffer->size, 0); | 129 | atomic_set(&buffer->size, 0); |
131 | init_waitqueue_head(&buffer->wait); | 130 | init_waitqueue_head(&buffer->wait); |
132 | 131 | ||
133 | return 0; | 132 | return 0; |
134 | } | 133 | } |
@@ -158,8 +157,7 @@ packet_buffer_get(struct packet_buffer *buffer, void *data, size_t user_length) | |||
158 | if (copy_to_user(data, buffer->head->data, length)) | 157 | if (copy_to_user(data, buffer->head->data, length)) |
159 | return -EFAULT; | 158 | return -EFAULT; |
160 | buffer->head = (struct packet *) &buffer->head->data[length]; | 159 | buffer->head = (struct packet *) &buffer->head->data[length]; |
161 | } | 160 | } else { |
162 | else { | ||
163 | size_t split = end - buffer->head->data; | 161 | size_t split = end - buffer->head->data; |
164 | 162 | ||
165 | if (copy_to_user(data, buffer->head->data, split)) | 163 | if (copy_to_user(data, buffer->head->data, split)) |
@@ -169,11 +167,12 @@ packet_buffer_get(struct packet_buffer *buffer, void *data, size_t user_length) | |||
169 | buffer->head = (struct packet *) &buffer->data[length - split]; | 167 | buffer->head = (struct packet *) &buffer->data[length - split]; |
170 | } | 168 | } |
171 | 169 | ||
172 | /* Decrease buffer->size as the last thing, since this is what | 170 | /* |
171 | * Decrease buffer->size as the last thing, since this is what | ||
173 | * keeps the interrupt from overwriting the packet we are | 172 | * keeps the interrupt from overwriting the packet we are |
174 | * retrieving from the buffer. */ | 173 | * retrieving from the buffer. |
175 | 174 | */ | |
176 | atomic_sub(sizeof (struct packet) + length, &buffer->size); | 175 | atomic_sub(sizeof(struct packet) + length, &buffer->size); |
177 | 176 | ||
178 | return length; | 177 | return length; |
179 | } | 178 | } |
@@ -185,8 +184,8 @@ packet_buffer_put(struct packet_buffer *buffer, void *data, size_t length) | |||
185 | 184 | ||
186 | buffer->total_packet_count++; | 185 | buffer->total_packet_count++; |
187 | 186 | ||
188 | if (buffer->capacity < | 187 | if (buffer->capacity < |
189 | atomic_read(&buffer->size) + sizeof (struct packet) + length) { | 188 | atomic_read(&buffer->size) + sizeof(struct packet) + length) { |
190 | buffer->lost_packet_count++; | 189 | buffer->lost_packet_count++; |
191 | return; | 190 | return; |
192 | } | 191 | } |
@@ -197,69 +196,68 @@ packet_buffer_put(struct packet_buffer *buffer, void *data, size_t length) | |||
197 | if (&buffer->tail->data[length] < end) { | 196 | if (&buffer->tail->data[length] < end) { |
198 | memcpy(buffer->tail->data, data, length); | 197 | memcpy(buffer->tail->data, data, length); |
199 | buffer->tail = (struct packet *) &buffer->tail->data[length]; | 198 | buffer->tail = (struct packet *) &buffer->tail->data[length]; |
200 | } | 199 | } else { |
201 | else { | ||
202 | size_t split = end - buffer->tail->data; | 200 | size_t split = end - buffer->tail->data; |
203 | 201 | ||
204 | memcpy(buffer->tail->data, data, split); | 202 | memcpy(buffer->tail->data, data, split); |
205 | memcpy(buffer->data, data + split, length - split); | 203 | memcpy(buffer->data, data + split, length - split); |
206 | buffer->tail = (struct packet *) &buffer->data[length - split]; | 204 | buffer->tail = (struct packet *) &buffer->data[length - split]; |
207 | } | 205 | } |
208 | 206 | ||
209 | /* Finally, adjust buffer size and wake up userspace reader. */ | 207 | /* Finally, adjust buffer size and wake up userspace reader. */ |
210 | 208 | ||
211 | atomic_add(sizeof (struct packet) + length, &buffer->size); | 209 | atomic_add(sizeof(struct packet) + length, &buffer->size); |
212 | wake_up_interruptible(&buffer->wait); | 210 | wake_up_interruptible(&buffer->wait); |
213 | } | 211 | } |
214 | 212 | ||
215 | static inline void | 213 | static inline void |
216 | reg_write(struct pcilynx *lynx, int offset, u32 data) | 214 | reg_write(struct pcilynx *lynx, int offset, u32 data) |
217 | { | 215 | { |
218 | writel(data, lynx->registers + offset); | 216 | writel(data, lynx->registers + offset); |
219 | } | 217 | } |
220 | 218 | ||
221 | static inline u32 | 219 | static inline u32 |
222 | reg_read(struct pcilynx *lynx, int offset) | 220 | reg_read(struct pcilynx *lynx, int offset) |
223 | { | 221 | { |
224 | return readl(lynx->registers + offset); | 222 | return readl(lynx->registers + offset); |
225 | } | 223 | } |
226 | 224 | ||
227 | static inline void | 225 | static inline void |
228 | reg_set_bits(struct pcilynx *lynx, int offset, u32 mask) | 226 | reg_set_bits(struct pcilynx *lynx, int offset, u32 mask) |
229 | { | 227 | { |
230 | reg_write(lynx, offset, (reg_read(lynx, offset) | mask)); | 228 | reg_write(lynx, offset, (reg_read(lynx, offset) | mask)); |
231 | } | 229 | } |
232 | 230 | ||
233 | /* Maybe the pcl programs could be setup to just append data instead | 231 | /* |
234 | * of using a whole packet. */ | 232 | * Maybe the pcl programs could be set up to just append data instead |
235 | 233 | * of using a whole packet. | |
236 | static inline void | 234 | */ |
237 | run_pcl(struct pcilynx *lynx, dma_addr_t pcl_bus, int dmachan) | 235 | static inline void |
236 | run_pcl(struct pcilynx *lynx, dma_addr_t pcl_bus, | ||
237 | int dmachan) | ||
238 | { | 238 | { |
239 | reg_write(lynx, DMA0_CURRENT_PCL + dmachan * 0x20, pcl_bus); | 239 | reg_write(lynx, DMA0_CURRENT_PCL + dmachan * 0x20, pcl_bus); |
240 | reg_write(lynx, DMA0_CHAN_CTRL + dmachan * 0x20, | 240 | reg_write(lynx, DMA0_CHAN_CTRL + dmachan * 0x20, |
241 | DMA_CHAN_CTRL_ENABLE | DMA_CHAN_CTRL_LINK); | 241 | DMA_CHAN_CTRL_ENABLE | DMA_CHAN_CTRL_LINK); |
242 | } | 242 | } |
243 | 243 | ||
244 | static int | 244 | static int |
245 | set_phy_reg(struct pcilynx *lynx, int addr, int val) | 245 | set_phy_reg(struct pcilynx *lynx, int addr, int val) |
246 | { | 246 | { |
247 | if (addr > 15) { | 247 | if (addr > 15) { |
248 | debug("%s: PHY register address %d out of range", | 248 | debug("PHY register address %d out of range\n", addr); |
249 | __FUNCTION__, addr); | 249 | return -1; |
250 | return -1; | 250 | } |
251 | } | 251 | |
252 | 252 | if (val > 0xff) { | |
253 | if (val > 0xff) { | 253 | debug("PHY register value %d out of range\n", val); |
254 | debug("%s: PHY register value %d out of range", | 254 | return -1; |
255 | __FUNCTION__, val); | 255 | } |
256 | return -1; | 256 | |
257 | } | 257 | reg_write(lynx, LINK_PHY, LINK_PHY_WRITE | |
258 | |||
259 | reg_write(lynx, LINK_PHY, LINK_PHY_WRITE | | ||
260 | LINK_PHY_ADDR(addr) | LINK_PHY_WDATA(val)); | 258 | LINK_PHY_ADDR(addr) | LINK_PHY_WDATA(val)); |
261 | 259 | ||
262 | return 0; | 260 | return 0; |
263 | } | 261 | } |
264 | 262 | ||
265 | static void | 263 | static void |
@@ -317,7 +315,7 @@ nosy_open(struct inode *inode, struct file *file) | |||
317 | if (minor > MAX_MINORS || minors[minor] == NULL) | 315 | if (minor > MAX_MINORS || minors[minor] == NULL) |
318 | return -ENODEV; | 316 | return -ENODEV; |
319 | 317 | ||
320 | file->private_data = nosy_add_client(minors[minor]); | 318 | file->private_data = nosy_add_client(minors[minor]); |
321 | if (file->private_data == NULL) | 319 | if (file->private_data == NULL) |
322 | return -ENOMEM; | 320 | return -ENOMEM; |
323 | else | 321 | else |
@@ -329,7 +327,7 @@ nosy_release(struct inode *inode, struct file *file) | |||
329 | { | 327 | { |
330 | nosy_remove_client(file->private_data); | 328 | nosy_remove_client(file->private_data); |
331 | 329 | ||
332 | return 0; | 330 | return 0; |
333 | } | 331 | } |
334 | 332 | ||
335 | static unsigned int | 333 | static unsigned int |
@@ -358,19 +356,17 @@ nosy_ioctl(struct inode *inode, struct file *file, | |||
358 | unsigned int cmd, unsigned long arg) | 356 | unsigned int cmd, unsigned long arg) |
359 | { | 357 | { |
360 | struct client *client = file->private_data; | 358 | struct client *client = file->private_data; |
359 | struct nosy_stats stats; | ||
361 | 360 | ||
362 | switch (cmd) { | 361 | switch (cmd) { |
363 | case NOSY_IOC_GET_STATS: { | 362 | case NOSY_IOC_GET_STATS: |
364 | struct nosy_stats stats; | ||
365 | |||
366 | stats.total_packet_count = client->buffer.total_packet_count; | 363 | stats.total_packet_count = client->buffer.total_packet_count; |
367 | stats.lost_packet_count = client->buffer.lost_packet_count; | 364 | stats.lost_packet_count = client->buffer.lost_packet_count; |
368 | if (copy_to_user((void *) arg, &stats, sizeof stats)) | 365 | if (copy_to_user((void *) arg, &stats, sizeof stats)) |
369 | return -EFAULT; | 366 | return -EFAULT; |
370 | else | 367 | else |
371 | return 0; | 368 | return 0; |
372 | } | 369 | |
373 | |||
374 | case NOSY_IOC_START: | 370 | case NOSY_IOC_START: |
375 | nosy_start_snoop(client); | 371 | nosy_start_snoop(client); |
376 | return 0; | 372 | return 0; |
@@ -389,13 +385,13 @@ nosy_ioctl(struct inode *inode, struct file *file, | |||
389 | } | 385 | } |
390 | } | 386 | } |
391 | 387 | ||
392 | static struct file_operations nosy_ops = { | 388 | static const struct file_operations nosy_ops = { |
393 | .owner = THIS_MODULE, | 389 | .owner = THIS_MODULE, |
394 | .read = nosy_read, | 390 | .read = nosy_read, |
395 | .ioctl = nosy_ioctl, | 391 | .ioctl = nosy_ioctl, |
396 | .poll = nosy_poll, | 392 | .poll = nosy_poll, |
397 | .open = nosy_open, | 393 | .open = nosy_open, |
398 | .release = nosy_release, | 394 | .release = nosy_release, |
399 | }; | 395 | }; |
400 | 396 | ||
401 | #define PHY_PACKET_SIZE 12 /* 1 payload, 1 inverse, 1 ack = 3 quadlets */ | 397 | #define PHY_PACKET_SIZE 12 /* 1 payload, 1 inverse, 1 ack = 3 quadlets */ |
@@ -412,7 +408,6 @@ static void | |||
412 | packet_handler(struct pcilynx *lynx) | 408 | packet_handler(struct pcilynx *lynx) |
413 | { | 409 | { |
414 | unsigned long flags; | 410 | unsigned long flags; |
415 | struct list_head *pos; | ||
416 | struct client *client; | 411 | struct client *client; |
417 | unsigned long tcode_mask; | 412 | unsigned long tcode_mask; |
418 | size_t length; | 413 | size_t length; |
@@ -434,12 +429,10 @@ packet_handler(struct pcilynx *lynx) | |||
434 | 429 | ||
435 | spin_lock_irqsave(&lynx->client_list_lock, flags); | 430 | spin_lock_irqsave(&lynx->client_list_lock, flags); |
436 | 431 | ||
437 | list_for_each(pos, &lynx->client_list) { | 432 | list_for_each_entry(client, &lynx->client_list, link) |
438 | client = list_entry(pos, struct client, link); | ||
439 | if (client->tcode_mask & tcode_mask) | 433 | if (client->tcode_mask & tcode_mask) |
440 | packet_buffer_put(&client->buffer, | 434 | packet_buffer_put(&client->buffer, |
441 | lynx->rcv_buffer, length + 4); | 435 | lynx->rcv_buffer, length + 4); |
442 | } | ||
443 | 436 | ||
444 | spin_unlock_irqrestore(&lynx->client_list_lock, flags); | 437 | spin_unlock_irqrestore(&lynx->client_list_lock, flags); |
445 | } | 438 | } |
@@ -448,7 +441,6 @@ static void | |||
448 | bus_reset_handler(struct pcilynx *lynx) | 441 | bus_reset_handler(struct pcilynx *lynx) |
449 | { | 442 | { |
450 | unsigned long flags; | 443 | unsigned long flags; |
451 | struct list_head *pos; | ||
452 | struct client *client; | 444 | struct client *client; |
453 | struct timeval tv; | 445 | struct timeval tv; |
454 | 446 | ||
@@ -456,23 +448,19 @@ bus_reset_handler(struct pcilynx *lynx) | |||
456 | 448 | ||
457 | spin_lock_irqsave(&lynx->client_list_lock, flags); | 449 | spin_lock_irqsave(&lynx->client_list_lock, flags); |
458 | 450 | ||
459 | list_for_each(pos, &lynx->client_list) { | 451 | list_for_each_entry(client, &lynx->client_list, link) |
460 | client = list_entry(pos, struct client, link); | ||
461 | packet_buffer_put(&client->buffer, &tv.tv_usec, 4); | 452 | packet_buffer_put(&client->buffer, &tv.tv_usec, 4); |
462 | } | ||
463 | 453 | ||
464 | spin_unlock_irqrestore(&lynx->client_list_lock, flags); | 454 | spin_unlock_irqrestore(&lynx->client_list_lock, flags); |
465 | } | 455 | } |
466 | 456 | ||
467 | |||
468 | |||
469 | static irqreturn_t | 457 | static irqreturn_t |
470 | irq_handler(int irq, void *device) | 458 | irq_handler(int irq, void *device) |
471 | { | 459 | { |
472 | struct pcilynx *lynx = (struct pcilynx *) device; | 460 | struct pcilynx *lynx = device; |
473 | u32 pci_int_status; | 461 | u32 pci_int_status; |
474 | 462 | ||
475 | pci_int_status = reg_read(lynx, PCI_INT_STATUS); | 463 | pci_int_status = reg_read(lynx, PCI_INT_STATUS); |
476 | 464 | ||
477 | if ((pci_int_status & PCI_INT_INT_PEND) == 0) | 465 | if ((pci_int_status & PCI_INT_INT_PEND) == 0) |
478 | /* Not our interrupt, bail out quickly. */ | 466 | /* Not our interrupt, bail out quickly. */ |
@@ -505,19 +493,19 @@ irq_handler(int irq, void *device) | |||
505 | static void | 493 | static void |
506 | remove_card(struct pci_dev *dev) | 494 | remove_card(struct pci_dev *dev) |
507 | { | 495 | { |
508 | struct pcilynx *lynx; | 496 | struct pcilynx *lynx; |
509 | 497 | ||
510 | lynx = pci_get_drvdata(dev); | 498 | lynx = pci_get_drvdata(dev); |
511 | if (!lynx) | 499 | if (!lynx) |
512 | return; | 500 | return; |
513 | pci_set_drvdata(dev, NULL); | 501 | pci_set_drvdata(dev, NULL); |
514 | 502 | ||
515 | reg_write(lynx, PCI_INT_ENABLE, 0); | 503 | reg_write(lynx, PCI_INT_ENABLE, 0); |
516 | free_irq(lynx->pci_device->irq, lynx); | 504 | free_irq(lynx->pci_device->irq, lynx); |
517 | 505 | ||
518 | pci_free_consistent(lynx->pci_device, sizeof (struct pcl), | 506 | pci_free_consistent(lynx->pci_device, sizeof(struct pcl), |
519 | lynx->rcv_start_pcl, lynx->rcv_start_pcl_bus); | 507 | lynx->rcv_start_pcl, lynx->rcv_start_pcl_bus); |
520 | pci_free_consistent(lynx->pci_device, sizeof (struct pcl), | 508 | pci_free_consistent(lynx->pci_device, sizeof(struct pcl), |
521 | lynx->rcv_pcl, lynx->rcv_pcl_bus); | 509 | lynx->rcv_pcl, lynx->rcv_pcl_bus); |
522 | pci_free_consistent(lynx->pci_device, PAGE_SIZE, | 510 | pci_free_consistent(lynx->pci_device, PAGE_SIZE, |
523 | lynx->rcv_buffer, lynx->rcv_buffer_bus); | 511 | lynx->rcv_buffer, lynx->rcv_buffer_bus); |
@@ -532,64 +520,58 @@ remove_card(struct pci_dev *dev) | |||
532 | 520 | ||
533 | #define RCV_BUFFER_SIZE (16 * 1024) | 521 | #define RCV_BUFFER_SIZE (16 * 1024) |
534 | 522 | ||
535 | #define FAIL(s, args...) \ | ||
536 | do { \ | ||
537 | error(s, ## args); \ | ||
538 | return err; \ | ||
539 | } while (0) | ||
540 | |||
541 | static int __devinit | 523 | static int __devinit |
542 | add_card(struct pci_dev *dev, const struct pci_device_id *unused) | 524 | add_card(struct pci_dev *dev, const struct pci_device_id *unused) |
543 | { | 525 | { |
544 | struct pcilynx *lynx; | 526 | struct pcilynx *lynx; |
545 | u32 p, end; | 527 | u32 p, end; |
546 | int err, i; | 528 | int i; |
547 | |||
548 | err = -ENXIO; | ||
549 | 529 | ||
550 | if (pci_set_dma_mask(dev, 0xffffffff)) | 530 | if (pci_set_dma_mask(dev, 0xffffffff)) { |
551 | FAIL("DMA address limits not supported " | 531 | error("DMA address limits not supported " |
552 | "for PCILynx hardware.\n"); | 532 | "for PCILynx hardware\n"); |
553 | if (pci_enable_device(dev)) | 533 | return -ENXIO; |
554 | FAIL("Failed to enable PCILynx hardware.\n"); | 534 | } |
555 | pci_set_master(dev); | 535 | if (pci_enable_device(dev)) { |
556 | 536 | error("Failed to enable PCILynx hardware\n"); | |
557 | err = -ENOMEM; | 537 | return -ENXIO; |
538 | } | ||
539 | pci_set_master(dev); | ||
558 | 540 | ||
559 | lynx = kzalloc(sizeof *lynx, GFP_KERNEL); | 541 | lynx = kzalloc(sizeof *lynx, GFP_KERNEL); |
560 | if (lynx == NULL) | 542 | if (lynx == NULL) { |
561 | FAIL("Failed to allocate control structure memory.\n"); | 543 | error("Failed to allocate control structure memory\n"); |
562 | 544 | return -ENOMEM; | |
563 | lynx->pci_device = dev; | 545 | } |
564 | pci_set_drvdata(dev, lynx); | 546 | lynx->pci_device = dev; |
547 | pci_set_drvdata(dev, lynx); | ||
565 | 548 | ||
566 | spin_lock_init(&lynx->client_list_lock); | 549 | spin_lock_init(&lynx->client_list_lock); |
567 | INIT_LIST_HEAD(&lynx->client_list); | 550 | INIT_LIST_HEAD(&lynx->client_list); |
568 | 551 | ||
569 | lynx->registers = ioremap_nocache(pci_resource_start(dev, 0), | 552 | lynx->registers = ioremap_nocache(pci_resource_start(dev, 0), |
570 | PCILYNX_MAX_REGISTER); | 553 | PCILYNX_MAX_REGISTER); |
571 | 554 | ||
572 | lynx->rcv_start_pcl = pci_alloc_consistent(lynx->pci_device, | 555 | lynx->rcv_start_pcl = pci_alloc_consistent(lynx->pci_device, |
573 | sizeof(struct pcl), | 556 | sizeof(struct pcl), &lynx->rcv_start_pcl_bus); |
574 | &lynx->rcv_start_pcl_bus); | 557 | lynx->rcv_pcl = pci_alloc_consistent(lynx->pci_device, |
575 | lynx->rcv_pcl = pci_alloc_consistent(lynx->pci_device, | 558 | sizeof(struct pcl), &lynx->rcv_pcl_bus); |
576 | sizeof(struct pcl), | 559 | lynx->rcv_buffer = pci_alloc_consistent(lynx->pci_device, |
577 | &lynx->rcv_pcl_bus); | 560 | RCV_BUFFER_SIZE, &lynx->rcv_buffer_bus); |
578 | lynx->rcv_buffer = pci_alloc_consistent(lynx->pci_device, RCV_BUFFER_SIZE, | 561 | if (lynx->rcv_start_pcl == NULL || |
579 | &lynx->rcv_buffer_bus); | ||
580 | if (lynx->rcv_start_pcl == NULL || | ||
581 | lynx->rcv_pcl == NULL || | 562 | lynx->rcv_pcl == NULL || |
582 | lynx->rcv_buffer == NULL) | 563 | lynx->rcv_buffer == NULL) { |
583 | /* FIXME: do proper error handling. */ | 564 | /* FIXME: do proper error handling. */ |
584 | FAIL("Failed to allocate receive buffer.\n"); | 565 | error("Failed to allocate receive buffer\n"); |
585 | 566 | return -ENOMEM; | |
567 | } | ||
586 | lynx->rcv_start_pcl->next = lynx->rcv_pcl_bus; | 568 | lynx->rcv_start_pcl->next = lynx->rcv_pcl_bus; |
587 | lynx->rcv_pcl->next = PCL_NEXT_INVALID; | 569 | lynx->rcv_pcl->next = PCL_NEXT_INVALID; |
588 | lynx->rcv_pcl->async_error_next = PCL_NEXT_INVALID; | 570 | lynx->rcv_pcl->async_error_next = PCL_NEXT_INVALID; |
589 | 571 | ||
590 | lynx->rcv_pcl->buffer[0].control = | 572 | lynx->rcv_pcl->buffer[0].control = |
591 | PCL_CMD_RCV | PCL_BIGENDIAN | 2044; | 573 | PCL_CMD_RCV | PCL_BIGENDIAN | 2044; |
592 | lynx->rcv_pcl->buffer[0].pointer = lynx->rcv_buffer_bus + 4; | 574 | lynx->rcv_pcl->buffer[0].pointer = lynx->rcv_buffer_bus + 4; |
593 | p = lynx->rcv_buffer_bus + 2048; | 575 | p = lynx->rcv_buffer_bus + 2048; |
594 | end = lynx->rcv_buffer_bus + RCV_BUFFER_SIZE; | 576 | end = lynx->rcv_buffer_bus + RCV_BUFFER_SIZE; |
595 | for (i = 1; p < end; i++, p += 2048) { | 577 | for (i = 1; p < end; i++, p += 2048) { |
@@ -599,31 +581,31 @@ add_card(struct pci_dev *dev, const struct pci_device_id *unused) | |||
599 | } | 581 | } |
600 | lynx->rcv_pcl->buffer[i - 1].control |= PCL_LAST_BUFF; | 582 | lynx->rcv_pcl->buffer[i - 1].control |= PCL_LAST_BUFF; |
601 | 583 | ||
602 | reg_set_bits(lynx, MISC_CONTROL, MISC_CONTROL_SWRESET); | 584 | reg_set_bits(lynx, MISC_CONTROL, MISC_CONTROL_SWRESET); |
603 | /* Fix buggy cards with autoboot pin not tied low: */ | 585 | /* Fix buggy cards with autoboot pin not tied low: */ |
604 | reg_write(lynx, DMA0_CHAN_CTRL, 0); | 586 | reg_write(lynx, DMA0_CHAN_CTRL, 0); |
605 | reg_write(lynx, DMA_GLOBAL_REGISTER, 0x00 << 24); | 587 | reg_write(lynx, DMA_GLOBAL_REGISTER, 0x00 << 24); |
606 | 588 | ||
607 | #if 0 | 589 | #if 0 |
608 | /* now, looking for PHY register set */ | 590 | /* now, looking for PHY register set */ |
609 | if ((get_phy_reg(lynx, 2) & 0xe0) == 0xe0) { | 591 | if ((get_phy_reg(lynx, 2) & 0xe0) == 0xe0) { |
610 | lynx->phyic.reg_1394a = 1; | 592 | lynx->phyic.reg_1394a = 1; |
611 | PRINT(KERN_INFO, lynx->id, | 593 | PRINT(KERN_INFO, lynx->id, |
612 | "found 1394a conform PHY (using extended register set)"); | 594 | "found 1394a conform PHY (using extended register set)"); |
613 | lynx->phyic.vendor = get_phy_vendorid(lynx); | 595 | lynx->phyic.vendor = get_phy_vendorid(lynx); |
614 | lynx->phyic.product = get_phy_productid(lynx); | 596 | lynx->phyic.product = get_phy_productid(lynx); |
615 | } else { | 597 | } else { |
616 | lynx->phyic.reg_1394a = 0; | 598 | lynx->phyic.reg_1394a = 0; |
617 | PRINT(KERN_INFO, lynx->id, "found old 1394 PHY"); | 599 | PRINT(KERN_INFO, lynx->id, "found old 1394 PHY"); |
618 | } | 600 | } |
619 | #endif | 601 | #endif |
620 | 602 | ||
621 | /* Setup the general receive FIFO max size. */ | 603 | /* Setup the general receive FIFO max size. */ |
622 | reg_write(lynx, FIFO_SIZES, 255); | 604 | reg_write(lynx, FIFO_SIZES, 255); |
623 | 605 | ||
624 | reg_set_bits(lynx, PCI_INT_ENABLE, PCI_INT_DMA_ALL); | 606 | reg_set_bits(lynx, PCI_INT_ENABLE, PCI_INT_DMA_ALL); |
625 | 607 | ||
626 | reg_write(lynx, LINK_INT_ENABLE, | 608 | reg_write(lynx, LINK_INT_ENABLE, |
627 | LINK_INT_PHY_TIME_OUT | LINK_INT_PHY_REG_RCVD | | 609 | LINK_INT_PHY_TIME_OUT | LINK_INT_PHY_REG_RCVD | |
628 | LINK_INT_PHY_BUSRESET | LINK_INT_IT_STUCK | | 610 | LINK_INT_PHY_BUSRESET | LINK_INT_IT_STUCK | |
629 | LINK_INT_AT_STUCK | LINK_INT_SNTRJ | | 611 | LINK_INT_AT_STUCK | LINK_INT_SNTRJ | |
@@ -638,58 +620,60 @@ add_card(struct pci_dev *dev, const struct pci_device_id *unused) | |||
638 | 620 | ||
639 | run_pcl(lynx, lynx->rcv_start_pcl_bus, 0); | 621 | run_pcl(lynx, lynx->rcv_start_pcl_bus, 0); |
640 | 622 | ||
641 | if (request_irq(dev->irq, irq_handler, IRQF_SHARED, driver_name, lynx)) | 623 | if (request_irq(dev->irq, irq_handler, IRQF_SHARED, |
642 | FAIL("Failed to allocate shared interrupt %d.", dev->irq); | 624 | driver_name, lynx)) { |
625 | error("Failed to allocate shared interrupt %d\n", dev->irq); | ||
626 | return -EIO; | ||
627 | } | ||
643 | 628 | ||
644 | lynx->misc.parent = &dev->dev; | 629 | lynx->misc.parent = &dev->dev; |
645 | lynx->misc.minor = MISC_DYNAMIC_MINOR; | 630 | lynx->misc.minor = MISC_DYNAMIC_MINOR; |
646 | lynx->misc.name = "nosy"; | 631 | lynx->misc.name = "nosy"; |
647 | lynx->misc.fops = &nosy_ops; | 632 | lynx->misc.fops = &nosy_ops; |
648 | if (misc_register(&lynx->misc)) | 633 | if (misc_register(&lynx->misc)) { |
649 | FAIL("Failed to register misc char device."); | 634 | error("Failed to register misc char device\n"); |
635 | return -ENOMEM; | ||
636 | } | ||
650 | minors[lynx->misc.minor] = lynx; | 637 | minors[lynx->misc.minor] = lynx; |
651 | 638 | ||
652 | notify("Initialized PCILynx IEEE1394 card, irq=%d\n", dev->irq); | 639 | notify("Initialized PCILynx IEEE1394 card, irq=%d\n", dev->irq); |
653 | 640 | ||
654 | return 0; | 641 | return 0; |
655 | } | 642 | } |
656 | 643 | ||
657 | static struct pci_device_id pci_table[] __devinitdata = { | 644 | static struct pci_device_id pci_table[] __devinitdata = { |
658 | { | 645 | { |
659 | .vendor = PCI_VENDOR_ID_TI, | 646 | .vendor = PCI_VENDOR_ID_TI, |
660 | .device = PCI_DEVICE_ID_TI_PCILYNX, | 647 | .device = PCI_DEVICE_ID_TI_PCILYNX, |
661 | .subvendor = PCI_ANY_ID, | 648 | .subvendor = PCI_ANY_ID, |
662 | .subdevice = PCI_ANY_ID, | 649 | .subdevice = PCI_ANY_ID, |
663 | }, | 650 | }, |
664 | { } /* Terminating entry */ | 651 | { } /* Terminating entry */ |
665 | }; | 652 | }; |
666 | 653 | ||
667 | static struct pci_driver lynx_pci_driver = { | 654 | static struct pci_driver lynx_pci_driver = { |
668 | .name = (char *) driver_name, | 655 | .name = driver_name, |
669 | .id_table = pci_table, | 656 | .id_table = pci_table, |
670 | .probe = add_card, | 657 | .probe = add_card, |
671 | .remove = __devexit_p(remove_card), | 658 | .remove = remove_card, |
672 | }; | 659 | }; |
673 | 660 | ||
674 | MODULE_AUTHOR("Kristian Høgsberg"); | 661 | MODULE_AUTHOR("Kristian Hoegsberg"); |
675 | MODULE_DESCRIPTION("Snoop mode driver for TI pcilynx 1394 controllers"); | 662 | MODULE_DESCRIPTION("Snoop mode driver for TI pcilynx 1394 controllers"); |
676 | MODULE_LICENSE("GPL"); | 663 | MODULE_LICENSE("GPL"); |
677 | MODULE_DEVICE_TABLE(pci, pci_table); | 664 | MODULE_DEVICE_TABLE(pci, pci_table); |
678 | 665 | ||
679 | static int __init nosy_init(void) | 666 | static int __init nosy_init(void) |
680 | { | 667 | { |
681 | /* notify("Loaded %s version %s.\n", driver_name, VERSION); */ | 668 | return pci_register_driver(&lynx_pci_driver); |
682 | |||
683 | return pci_register_driver(&lynx_pci_driver); | ||
684 | } | 669 | } |
685 | 670 | ||
686 | static void __exit nosy_cleanup(void) | 671 | static void __exit nosy_cleanup(void) |
687 | { | 672 | { |
688 | pci_unregister_driver(&lynx_pci_driver); | 673 | pci_unregister_driver(&lynx_pci_driver); |
689 | 674 | ||
690 | notify("Unloaded %s.\n", driver_name); | 675 | notify("Unloaded %s.\n", driver_name); |
691 | } | 676 | } |
692 | 677 | ||
693 | |||
694 | module_init(nosy_init); | 678 | module_init(nosy_init); |
695 | module_exit(nosy_cleanup); | 679 | module_exit(nosy_cleanup); |