xref: /openbmc/linux/drivers/firewire/nosy.c (revision 16547667)
1b5e47729SStefan Richter /*
2b5e47729SStefan Richter  * nosy - Snoop mode driver for TI PCILynx 1394 controllers
3b5e47729SStefan Richter  * Copyright (C) 2002-2007 Kristian Høgsberg
428646821SStefan Richter  *
528646821SStefan Richter  * This program is free software; you can redistribute it and/or modify
628646821SStefan Richter  * it under the terms of the GNU General Public License as published by
728646821SStefan Richter  * the Free Software Foundation; either version 2 of the License, or
828646821SStefan Richter  * (at your option) any later version.
928646821SStefan Richter  *
1028646821SStefan Richter  * This program is distributed in the hope that it will be useful,
1128646821SStefan Richter  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1228646821SStefan Richter  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1328646821SStefan Richter  * GNU General Public License for more details.
1428646821SStefan Richter  *
1528646821SStefan Richter  * You should have received a copy of the GNU General Public License
1628646821SStefan Richter  * along with this program; if not, write to the Free Software Foundation,
1728646821SStefan Richter  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1828646821SStefan Richter  */
1928646821SStefan Richter 
2028646821SStefan Richter #include <linux/errno.h>
2128646821SStefan Richter #include <linux/fs.h>
22b5e47729SStefan Richter #include <linux/init.h>
23b5e47729SStefan Richter #include <linux/interrupt.h>
24b5e47729SStefan Richter #include <linux/io.h>
25b5e47729SStefan Richter #include <linux/kernel.h>
2628646821SStefan Richter #include <linux/miscdevice.h>
27b5e47729SStefan Richter #include <linux/module.h>
28b5e47729SStefan Richter #include <linux/pci.h>
29b5e47729SStefan Richter #include <linux/poll.h>
30b5e47729SStefan Richter #include <linux/sched.h> /* required for linux/wait.h */
31b5e47729SStefan Richter #include <linux/slab.h>
32b5e47729SStefan Richter #include <linux/spinlock.h>
33b5e47729SStefan Richter #include <linux/timex.h>
34b5e47729SStefan Richter #include <linux/uaccess.h>
35b5e47729SStefan Richter #include <linux/wait.h>
36b5e47729SStefan Richter 
3728646821SStefan Richter #include <asm/atomic.h>
38b5e47729SStefan Richter #include <asm/byteorder.h>
3928646821SStefan Richter 
4028646821SStefan Richter #include "nosy.h"
4128646821SStefan Richter #include "nosy-user.h"
4228646821SStefan Richter 
4328646821SStefan Richter #define TCODE_PHY_PACKET		0x10
4428646821SStefan Richter #define PCI_DEVICE_ID_TI_PCILYNX	0x8000
4528646821SStefan Richter 
4628646821SStefan Richter #define notify(s, args...) printk(KERN_NOTICE s, ## args)
4728646821SStefan Richter #define error(s, args...) printk(KERN_ERR s, ## args)
4828646821SStefan Richter #define debug(s, args...) printk(KERN_DEBUG s, ## args)
4928646821SStefan Richter 
50b5e47729SStefan Richter static char driver_name[] = KBUILD_MODNAME;
5128646821SStefan Richter 
5228646821SStefan Richter struct pcl_status {
5328646821SStefan Richter 	unsigned int transfer_count : 13;
5428646821SStefan Richter 	unsigned int reserved0 : 1;
5528646821SStefan Richter 	unsigned int ack_type : 1;
5628646821SStefan Richter 	unsigned int ack : 4;
5728646821SStefan Richter 	unsigned int rcv_speed : 2;
5828646821SStefan Richter 	unsigned int rcv_dma_channel : 6;
5928646821SStefan Richter 	unsigned int packet_complete : 1;
6028646821SStefan Richter 	unsigned int packet_error : 1;
6128646821SStefan Richter 	unsigned int master_error : 1;
6228646821SStefan Richter 	unsigned int iso_mode : 1;
6328646821SStefan Richter 	unsigned int self_id : 1;
6428646821SStefan Richter };
6528646821SStefan Richter 
6628646821SStefan Richter /* this is the physical layout of a PCL, its size is 128 bytes */
6728646821SStefan Richter struct pcl {
6828646821SStefan Richter         u32 next;
6928646821SStefan Richter         u32 async_error_next;
7028646821SStefan Richter         u32 user_data;
7128646821SStefan Richter         struct pcl_status pcl_status;
7228646821SStefan Richter         u32 remaining_transfer_count;
7328646821SStefan Richter         u32 next_data_buffer;
7428646821SStefan Richter         struct {
7528646821SStefan Richter                 u32 control;
7628646821SStefan Richter                 u32 pointer;
7728646821SStefan Richter         } buffer[13] __attribute__ ((packed));
7828646821SStefan Richter } __attribute__ ((packed));
7928646821SStefan Richter 
8028646821SStefan Richter struct packet {
81b5e47729SStefan Richter 	unsigned int length;
8228646821SStefan Richter 	char data[0];
8328646821SStefan Richter };
8428646821SStefan Richter 
8528646821SStefan Richter struct packet_buffer {
8628646821SStefan Richter 	char *data;
8728646821SStefan Richter 	size_t capacity;
8828646821SStefan Richter 	long total_packet_count, lost_packet_count;
8928646821SStefan Richter 	atomic_t size;
9028646821SStefan Richter 	struct packet *head, *tail;
9128646821SStefan Richter 	wait_queue_head_t wait;
9228646821SStefan Richter };
9328646821SStefan Richter 
9428646821SStefan Richter struct pcilynx {
9528646821SStefan Richter 	struct pci_dev *pci_device;
9628646821SStefan Richter 	unsigned char *registers;
9728646821SStefan Richter 
9828646821SStefan Richter 	struct pcl *rcv_start_pcl, *rcv_pcl;
9928646821SStefan Richter 	u32 *rcv_buffer;
10028646821SStefan Richter 
10128646821SStefan Richter 	dma_addr_t rcv_start_pcl_bus, rcv_pcl_bus, rcv_buffer_bus;
10228646821SStefan Richter 
10328646821SStefan Richter 	spinlock_t client_list_lock;
10428646821SStefan Richter 	struct list_head client_list;
10528646821SStefan Richter 
10628646821SStefan Richter 	struct miscdevice misc;
10728646821SStefan Richter };
10828646821SStefan Richter 
10928646821SStefan Richter struct client {
11028646821SStefan Richter 	struct pcilynx *lynx;
111c7b2a99cSStefan Richter 	u32 tcode_mask;
11228646821SStefan Richter 	struct packet_buffer buffer;
11328646821SStefan Richter 	struct list_head link;
11428646821SStefan Richter };
11528646821SStefan Richter 
11628646821SStefan Richter #define MAX_MINORS 64
117b5e47729SStefan Richter static struct pcilynx *minors[MAX_MINORS];
11828646821SStefan Richter 
11928646821SStefan Richter static int
12028646821SStefan Richter packet_buffer_init(struct packet_buffer *buffer, size_t capacity)
12128646821SStefan Richter {
12228646821SStefan Richter 	buffer->data = kmalloc(capacity, GFP_KERNEL);
12328646821SStefan Richter 	if (buffer->data == NULL)
12428646821SStefan Richter 		return -ENOMEM;
12528646821SStefan Richter 	buffer->head = (struct packet *) buffer->data;
12628646821SStefan Richter 	buffer->tail = (struct packet *) buffer->data;
12728646821SStefan Richter 	buffer->capacity = capacity;
12828646821SStefan Richter 	buffer->lost_packet_count = 0;
12928646821SStefan Richter 	atomic_set(&buffer->size, 0);
13028646821SStefan Richter 	init_waitqueue_head(&buffer->wait);
13128646821SStefan Richter 
13228646821SStefan Richter 	return 0;
13328646821SStefan Richter }
13428646821SStefan Richter 
13528646821SStefan Richter static void
13628646821SStefan Richter packet_buffer_destroy(struct packet_buffer *buffer)
13728646821SStefan Richter {
13828646821SStefan Richter 	kfree(buffer->data);
13928646821SStefan Richter }
14028646821SStefan Richter 
14128646821SStefan Richter static int
14228646821SStefan Richter packet_buffer_get(struct packet_buffer *buffer, void *data, size_t user_length)
14328646821SStefan Richter {
14428646821SStefan Richter 	size_t length;
14528646821SStefan Richter 	char *end;
14628646821SStefan Richter 
14728646821SStefan Richter 	if (wait_event_interruptible(buffer->wait,
14828646821SStefan Richter 				     atomic_read(&buffer->size) > 0))
14928646821SStefan Richter 		return -ERESTARTSYS;
15028646821SStefan Richter 
15128646821SStefan Richter 	/* FIXME: Check length <= user_length. */
15228646821SStefan Richter 
15328646821SStefan Richter 	end = buffer->data + buffer->capacity;
15428646821SStefan Richter 	length = buffer->head->length;
15528646821SStefan Richter 
15628646821SStefan Richter 	if (&buffer->head->data[length] < end) {
15728646821SStefan Richter 		if (copy_to_user(data, buffer->head->data, length))
15828646821SStefan Richter 			return -EFAULT;
15928646821SStefan Richter 		buffer->head = (struct packet *) &buffer->head->data[length];
160b5e47729SStefan Richter 	} else {
16128646821SStefan Richter 		size_t split = end - buffer->head->data;
16228646821SStefan Richter 
16328646821SStefan Richter 		if (copy_to_user(data, buffer->head->data, split))
16428646821SStefan Richter 			return -EFAULT;
16528646821SStefan Richter 		if (copy_to_user(data + split, buffer->data, length - split))
16628646821SStefan Richter 			return -EFAULT;
16728646821SStefan Richter 		buffer->head = (struct packet *) &buffer->data[length - split];
16828646821SStefan Richter 	}
16928646821SStefan Richter 
170b5e47729SStefan Richter 	/*
171b5e47729SStefan Richter 	 * Decrease buffer->size as the last thing, since this is what
17228646821SStefan Richter 	 * keeps the interrupt from overwriting the packet we are
173b5e47729SStefan Richter 	 * retrieving from the buffer.
174b5e47729SStefan Richter 	 */
17528646821SStefan Richter 	atomic_sub(sizeof(struct packet) + length, &buffer->size);
17628646821SStefan Richter 
17728646821SStefan Richter 	return length;
17828646821SStefan Richter }
17928646821SStefan Richter 
18028646821SStefan Richter static void
18128646821SStefan Richter packet_buffer_put(struct packet_buffer *buffer, void *data, size_t length)
18228646821SStefan Richter {
18328646821SStefan Richter 	char *end;
18428646821SStefan Richter 
18528646821SStefan Richter 	buffer->total_packet_count++;
18628646821SStefan Richter 
18728646821SStefan Richter 	if (buffer->capacity <
18828646821SStefan Richter 	    atomic_read(&buffer->size) + sizeof(struct packet) + length) {
18928646821SStefan Richter 		buffer->lost_packet_count++;
19028646821SStefan Richter 		return;
19128646821SStefan Richter 	}
19228646821SStefan Richter 
19328646821SStefan Richter 	end = buffer->data + buffer->capacity;
19428646821SStefan Richter 	buffer->tail->length = length;
19528646821SStefan Richter 
19628646821SStefan Richter 	if (&buffer->tail->data[length] < end) {
19728646821SStefan Richter 		memcpy(buffer->tail->data, data, length);
19828646821SStefan Richter 		buffer->tail = (struct packet *) &buffer->tail->data[length];
199b5e47729SStefan Richter 	} else {
20028646821SStefan Richter 		size_t split = end - buffer->tail->data;
20128646821SStefan Richter 
20228646821SStefan Richter 		memcpy(buffer->tail->data, data, split);
20328646821SStefan Richter 		memcpy(buffer->data, data + split, length - split);
20428646821SStefan Richter 		buffer->tail = (struct packet *) &buffer->data[length - split];
20528646821SStefan Richter 	}
20628646821SStefan Richter 
20728646821SStefan Richter 	/* Finally, adjust buffer size and wake up userspace reader. */
20828646821SStefan Richter 
20928646821SStefan Richter 	atomic_add(sizeof(struct packet) + length, &buffer->size);
21028646821SStefan Richter 	wake_up_interruptible(&buffer->wait);
21128646821SStefan Richter }
21228646821SStefan Richter 
21328646821SStefan Richter static inline void
21428646821SStefan Richter reg_write(struct pcilynx *lynx, int offset, u32 data)
21528646821SStefan Richter {
21628646821SStefan Richter 	writel(data, lynx->registers + offset);
21728646821SStefan Richter }
21828646821SStefan Richter 
21928646821SStefan Richter static inline u32
22028646821SStefan Richter reg_read(struct pcilynx *lynx, int offset)
22128646821SStefan Richter {
22228646821SStefan Richter 	return readl(lynx->registers + offset);
22328646821SStefan Richter }
22428646821SStefan Richter 
22528646821SStefan Richter static inline void
22628646821SStefan Richter reg_set_bits(struct pcilynx *lynx, int offset, u32 mask)
22728646821SStefan Richter {
22828646821SStefan Richter 	reg_write(lynx, offset, (reg_read(lynx, offset) | mask));
22928646821SStefan Richter }
23028646821SStefan Richter 
231b5e47729SStefan Richter /*
232b5e47729SStefan Richter  * Maybe the pcl programs could be set up to just append data instead
233b5e47729SStefan Richter  * of using a whole packet.
234b5e47729SStefan Richter  */
23528646821SStefan Richter static inline void
236b5e47729SStefan Richter run_pcl(struct pcilynx *lynx, dma_addr_t pcl_bus,
237b5e47729SStefan Richter 			   int dmachan)
23828646821SStefan Richter {
23928646821SStefan Richter 	reg_write(lynx, DMA0_CURRENT_PCL + dmachan * 0x20, pcl_bus);
24028646821SStefan Richter 	reg_write(lynx, DMA0_CHAN_CTRL + dmachan * 0x20,
24128646821SStefan Richter 		  DMA_CHAN_CTRL_ENABLE | DMA_CHAN_CTRL_LINK);
24228646821SStefan Richter }
24328646821SStefan Richter 
24428646821SStefan Richter static int
24528646821SStefan Richter set_phy_reg(struct pcilynx *lynx, int addr, int val)
24628646821SStefan Richter {
24728646821SStefan Richter 	if (addr > 15) {
248b5e47729SStefan Richter 		debug("PHY register address %d out of range\n", addr);
24928646821SStefan Richter 		return -1;
25028646821SStefan Richter 	}
25128646821SStefan Richter 
25228646821SStefan Richter 	if (val > 0xff) {
253b5e47729SStefan Richter 		debug("PHY register value %d out of range\n", val);
25428646821SStefan Richter 		return -1;
25528646821SStefan Richter 	}
25628646821SStefan Richter 
25728646821SStefan Richter 	reg_write(lynx, LINK_PHY, LINK_PHY_WRITE |
25828646821SStefan Richter 		  LINK_PHY_ADDR(addr) | LINK_PHY_WDATA(val));
25928646821SStefan Richter 
26028646821SStefan Richter 	return 0;
26128646821SStefan Richter }
26228646821SStefan Richter 
26328646821SStefan Richter static int
26428646821SStefan Richter nosy_open(struct inode *inode, struct file *file)
26528646821SStefan Richter {
26628646821SStefan Richter 	int minor = iminor(inode);
26755e77c06SStefan Richter 	struct client *client;
26828646821SStefan Richter 
26928646821SStefan Richter 	if (minor > MAX_MINORS || minors[minor] == NULL)
27028646821SStefan Richter 		return -ENODEV;
27128646821SStefan Richter 
27255e77c06SStefan Richter 	client = kmalloc(sizeof *client, GFP_KERNEL);
27355e77c06SStefan Richter 	if (client == NULL)
27428646821SStefan Richter 		return -ENOMEM;
27555e77c06SStefan Richter 
27655e77c06SStefan Richter 	client->tcode_mask = ~0;
27755e77c06SStefan Richter 	client->lynx = minors[minor];
27855e77c06SStefan Richter 	INIT_LIST_HEAD(&client->link);
27955e77c06SStefan Richter 
28055e77c06SStefan Richter 	if (packet_buffer_init(&client->buffer, 128 * 1024) < 0) {
28155e77c06SStefan Richter 		kfree(client);
28255e77c06SStefan Richter 		return -ENOMEM;
28355e77c06SStefan Richter 	}
28455e77c06SStefan Richter 
28555e77c06SStefan Richter 	file->private_data = client;
28655e77c06SStefan Richter 
28728646821SStefan Richter 	return 0;
28828646821SStefan Richter }
28928646821SStefan Richter 
29028646821SStefan Richter static int
29128646821SStefan Richter nosy_release(struct inode *inode, struct file *file)
29228646821SStefan Richter {
29355e77c06SStefan Richter 	struct client *client = file->private_data;
29455e77c06SStefan Richter 
29555e77c06SStefan Richter 	spin_lock_irq(&client->lynx->client_list_lock);
29655e77c06SStefan Richter 	list_del_init(&client->link);
29755e77c06SStefan Richter 	spin_unlock_irq(&client->lynx->client_list_lock);
29855e77c06SStefan Richter 
29955e77c06SStefan Richter 	packet_buffer_destroy(&client->buffer);
30055e77c06SStefan Richter 	kfree(client);
30128646821SStefan Richter 
30228646821SStefan Richter 	return 0;
30328646821SStefan Richter }
30428646821SStefan Richter 
30528646821SStefan Richter static unsigned int
30628646821SStefan Richter nosy_poll(struct file *file, poll_table *pt)
30728646821SStefan Richter {
30828646821SStefan Richter 	struct client *client = file->private_data;
30928646821SStefan Richter 
31028646821SStefan Richter 	poll_wait(file, &client->buffer.wait, pt);
31128646821SStefan Richter 
31228646821SStefan Richter 	if (atomic_read(&client->buffer.size) > 0)
31328646821SStefan Richter 		return POLLIN | POLLRDNORM;
31428646821SStefan Richter 	else
31528646821SStefan Richter 		return 0;
31628646821SStefan Richter }
31728646821SStefan Richter 
31828646821SStefan Richter static ssize_t
31928646821SStefan Richter nosy_read(struct file *file, char *buffer, size_t count, loff_t *offset)
32028646821SStefan Richter {
32128646821SStefan Richter 	struct client *client = file->private_data;
32228646821SStefan Richter 
32328646821SStefan Richter 	return packet_buffer_get(&client->buffer, buffer, count);
32428646821SStefan Richter }
32528646821SStefan Richter 
326c7b2a99cSStefan Richter static long
327c7b2a99cSStefan Richter nosy_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
32828646821SStefan Richter {
32928646821SStefan Richter 	struct client *client = file->private_data;
330c7b2a99cSStefan Richter 	spinlock_t *client_list_lock = &client->lynx->client_list_lock;
33128646821SStefan Richter 	struct nosy_stats stats;
33228646821SStefan Richter 
333b5e47729SStefan Richter 	switch (cmd) {
334b5e47729SStefan Richter 	case NOSY_IOC_GET_STATS:
335c7b2a99cSStefan Richter 		spin_lock_irq(client_list_lock);
33628646821SStefan Richter 		stats.total_packet_count = client->buffer.total_packet_count;
33728646821SStefan Richter 		stats.lost_packet_count  = client->buffer.lost_packet_count;
338c7b2a99cSStefan Richter 		spin_unlock_irq(client_list_lock);
339c7b2a99cSStefan Richter 
34028646821SStefan Richter 		if (copy_to_user((void *) arg, &stats, sizeof stats))
34128646821SStefan Richter 			return -EFAULT;
34228646821SStefan Richter 		else
34328646821SStefan Richter 			return 0;
34428646821SStefan Richter 
34528646821SStefan Richter 	case NOSY_IOC_START:
34655e77c06SStefan Richter 		spin_lock_irq(client_list_lock);
34755e77c06SStefan Richter 		list_add_tail(&client->link, &client->lynx->client_list);
34855e77c06SStefan Richter 		spin_unlock_irq(client_list_lock);
34955e77c06SStefan Richter 
35028646821SStefan Richter 		return 0;
35128646821SStefan Richter 
35228646821SStefan Richter 	case NOSY_IOC_STOP:
35355e77c06SStefan Richter 		spin_lock_irq(client_list_lock);
35455e77c06SStefan Richter 		list_del_init(&client->link);
35555e77c06SStefan Richter 		spin_unlock_irq(client_list_lock);
35655e77c06SStefan Richter 
35728646821SStefan Richter 		return 0;
35828646821SStefan Richter 
35928646821SStefan Richter 	case NOSY_IOC_FILTER:
360c7b2a99cSStefan Richter 		spin_lock_irq(client_list_lock);
36128646821SStefan Richter 		client->tcode_mask = arg;
362c7b2a99cSStefan Richter 		spin_unlock_irq(client_list_lock);
36355e77c06SStefan Richter 
36428646821SStefan Richter 		return 0;
36528646821SStefan Richter 
36628646821SStefan Richter 	default:
36728646821SStefan Richter 		return -EINVAL;
36828646821SStefan Richter 		/* Flush buffer, configure filter. */
36928646821SStefan Richter 	}
37028646821SStefan Richter }
37128646821SStefan Richter 
372b5e47729SStefan Richter static const struct file_operations nosy_ops = {
37328646821SStefan Richter 	.owner =		THIS_MODULE,
37428646821SStefan Richter 	.read =			nosy_read,
375c7b2a99cSStefan Richter 	.unlocked_ioctl =	nosy_ioctl,
37628646821SStefan Richter 	.poll =			nosy_poll,
37728646821SStefan Richter 	.open =			nosy_open,
37828646821SStefan Richter 	.release =		nosy_release,
37928646821SStefan Richter };
38028646821SStefan Richter 
38128646821SStefan Richter #define PHY_PACKET_SIZE 12 /* 1 payload, 1 inverse, 1 ack = 3 quadlets */
38228646821SStefan Richter 
38328646821SStefan Richter struct link_packet {
38428646821SStefan Richter 	unsigned int priority : 4;
38528646821SStefan Richter 	unsigned int tcode : 4;
38628646821SStefan Richter 	unsigned int rt : 2;
38728646821SStefan Richter 	unsigned int tlabel : 6;
38828646821SStefan Richter 	unsigned int destination : 16;
38928646821SStefan Richter };
39028646821SStefan Richter 
39128646821SStefan Richter static void
392685c3f80SStefan Richter packet_irq_handler(struct pcilynx *lynx)
39328646821SStefan Richter {
39428646821SStefan Richter 	struct client *client;
395c7b2a99cSStefan Richter 	u32 tcode_mask;
39628646821SStefan Richter 	size_t length;
39728646821SStefan Richter 	struct link_packet *packet;
39828646821SStefan Richter 	struct timeval tv;
39928646821SStefan Richter 
40028646821SStefan Richter 	/* FIXME: Also report rcv_speed. */
40128646821SStefan Richter 
40228646821SStefan Richter 	length = lynx->rcv_pcl->pcl_status.transfer_count;
40328646821SStefan Richter 	packet = (struct link_packet *) &lynx->rcv_buffer[1];
40428646821SStefan Richter 
40528646821SStefan Richter 	do_gettimeofday(&tv);
40628646821SStefan Richter 	lynx->rcv_buffer[0] = tv.tv_usec;
40728646821SStefan Richter 
40828646821SStefan Richter 	if (length == PHY_PACKET_SIZE)
40928646821SStefan Richter 		tcode_mask = 1 << TCODE_PHY_PACKET;
41028646821SStefan Richter 	else
41128646821SStefan Richter 		tcode_mask = 1 << packet->tcode;
41228646821SStefan Richter 
413685c3f80SStefan Richter 	spin_lock(&lynx->client_list_lock);
41428646821SStefan Richter 
415b5e47729SStefan Richter 	list_for_each_entry(client, &lynx->client_list, link)
41628646821SStefan Richter 		if (client->tcode_mask & tcode_mask)
41728646821SStefan Richter 			packet_buffer_put(&client->buffer,
41828646821SStefan Richter 					  lynx->rcv_buffer, length + 4);
41928646821SStefan Richter 
420685c3f80SStefan Richter 	spin_unlock(&lynx->client_list_lock);
42128646821SStefan Richter }
42228646821SStefan Richter 
42328646821SStefan Richter static void
424685c3f80SStefan Richter bus_reset_irq_handler(struct pcilynx *lynx)
42528646821SStefan Richter {
42628646821SStefan Richter 	struct client *client;
42728646821SStefan Richter 	struct timeval tv;
42828646821SStefan Richter 
42928646821SStefan Richter 	do_gettimeofday(&tv);
43028646821SStefan Richter 
431685c3f80SStefan Richter 	spin_lock(&lynx->client_list_lock);
43228646821SStefan Richter 
433b5e47729SStefan Richter 	list_for_each_entry(client, &lynx->client_list, link)
43428646821SStefan Richter 		packet_buffer_put(&client->buffer, &tv.tv_usec, 4);
43528646821SStefan Richter 
436685c3f80SStefan Richter 	spin_unlock(&lynx->client_list_lock);
43728646821SStefan Richter }
43828646821SStefan Richter 
43928646821SStefan Richter static irqreturn_t
44028646821SStefan Richter irq_handler(int irq, void *device)
44128646821SStefan Richter {
442b5e47729SStefan Richter 	struct pcilynx *lynx = device;
44328646821SStefan Richter 	u32 pci_int_status;
44428646821SStefan Richter 
44528646821SStefan Richter 	pci_int_status = reg_read(lynx, PCI_INT_STATUS);
44628646821SStefan Richter 
44716547667SStefan Richter 	if (pci_int_status == ~0)
44816547667SStefan Richter 		/* Card was ejected. */
44916547667SStefan Richter 		return IRQ_NONE;
45016547667SStefan Richter 
45128646821SStefan Richter 	if ((pci_int_status & PCI_INT_INT_PEND) == 0)
45228646821SStefan Richter 		/* Not our interrupt, bail out quickly. */
45328646821SStefan Richter 		return IRQ_NONE;
45428646821SStefan Richter 
45528646821SStefan Richter 	if ((pci_int_status & PCI_INT_P1394_INT) != 0) {
45628646821SStefan Richter 		u32 link_int_status;
45728646821SStefan Richter 
45828646821SStefan Richter 		link_int_status = reg_read(lynx, LINK_INT_STATUS);
45928646821SStefan Richter 		reg_write(lynx, LINK_INT_STATUS, link_int_status);
46028646821SStefan Richter 
46128646821SStefan Richter 		if ((link_int_status & LINK_INT_PHY_BUSRESET) > 0)
462685c3f80SStefan Richter 			bus_reset_irq_handler(lynx);
46328646821SStefan Richter 	}
46428646821SStefan Richter 
46528646821SStefan Richter 	/* Clear the PCI_INT_STATUS register only after clearing the
46628646821SStefan Richter 	 * LINK_INT_STATUS register; otherwise the PCI_INT_P1394 will
46728646821SStefan Richter 	 * be set again immediately. */
46828646821SStefan Richter 
46928646821SStefan Richter 	reg_write(lynx, PCI_INT_STATUS, pci_int_status);
47028646821SStefan Richter 
47128646821SStefan Richter 	if ((pci_int_status & PCI_INT_DMA0_HLT) > 0) {
472685c3f80SStefan Richter 		packet_irq_handler(lynx);
47328646821SStefan Richter 		run_pcl(lynx, lynx->rcv_start_pcl_bus, 0);
47428646821SStefan Richter 	}
47528646821SStefan Richter 
47628646821SStefan Richter 	return IRQ_HANDLED;
47728646821SStefan Richter }
47828646821SStefan Richter 
47928646821SStefan Richter static void
48028646821SStefan Richter remove_card(struct pci_dev *dev)
48128646821SStefan Richter {
48228646821SStefan Richter 	struct pcilynx *lynx;
48328646821SStefan Richter 
48428646821SStefan Richter 	lynx = pci_get_drvdata(dev);
48528646821SStefan Richter 	if (!lynx)
48628646821SStefan Richter 		return;
48728646821SStefan Richter 	pci_set_drvdata(dev, NULL);
48828646821SStefan Richter 
48928646821SStefan Richter 	reg_write(lynx, PCI_INT_ENABLE, 0);
49028646821SStefan Richter 	free_irq(lynx->pci_device->irq, lynx);
49128646821SStefan Richter 
49228646821SStefan Richter 	pci_free_consistent(lynx->pci_device, sizeof(struct pcl),
49328646821SStefan Richter 			    lynx->rcv_start_pcl, lynx->rcv_start_pcl_bus);
49428646821SStefan Richter 	pci_free_consistent(lynx->pci_device, sizeof(struct pcl),
49528646821SStefan Richter 			    lynx->rcv_pcl, lynx->rcv_pcl_bus);
49628646821SStefan Richter 	pci_free_consistent(lynx->pci_device, PAGE_SIZE,
49728646821SStefan Richter 			    lynx->rcv_buffer, lynx->rcv_buffer_bus);
49828646821SStefan Richter 
49928646821SStefan Richter 	iounmap(lynx->registers);
50028646821SStefan Richter 
50128646821SStefan Richter 	minors[lynx->misc.minor] = NULL;
50228646821SStefan Richter 	misc_deregister(&lynx->misc);
50328646821SStefan Richter 
50428646821SStefan Richter 	kfree(lynx);
50528646821SStefan Richter }
50628646821SStefan Richter 
50728646821SStefan Richter #define RCV_BUFFER_SIZE (16 * 1024)
50828646821SStefan Richter 
50928646821SStefan Richter static int __devinit
51028646821SStefan Richter add_card(struct pci_dev *dev, const struct pci_device_id *unused)
51128646821SStefan Richter {
51228646821SStefan Richter 	struct pcilynx *lynx;
51328646821SStefan Richter 	u32 p, end;
514b5e47729SStefan Richter 	int i;
51528646821SStefan Richter 
516b5e47729SStefan Richter 	if (pci_set_dma_mask(dev, 0xffffffff)) {
517b5e47729SStefan Richter 		error("DMA address limits not supported "
518b5e47729SStefan Richter 		      "for PCILynx hardware\n");
519b5e47729SStefan Richter 		return -ENXIO;
520b5e47729SStefan Richter 	}
521b5e47729SStefan Richter 	if (pci_enable_device(dev)) {
522b5e47729SStefan Richter 		error("Failed to enable PCILynx hardware\n");
523b5e47729SStefan Richter 		return -ENXIO;
524b5e47729SStefan Richter 	}
52528646821SStefan Richter 	pci_set_master(dev);
52628646821SStefan Richter 
52728646821SStefan Richter 	lynx = kzalloc(sizeof *lynx, GFP_KERNEL);
528b5e47729SStefan Richter 	if (lynx == NULL) {
529b5e47729SStefan Richter 		error("Failed to allocate control structure memory\n");
530b5e47729SStefan Richter 		return -ENOMEM;
531b5e47729SStefan Richter 	}
53228646821SStefan Richter 	lynx->pci_device = dev;
53328646821SStefan Richter 	pci_set_drvdata(dev, lynx);
53428646821SStefan Richter 
53528646821SStefan Richter 	spin_lock_init(&lynx->client_list_lock);
53628646821SStefan Richter 	INIT_LIST_HEAD(&lynx->client_list);
53728646821SStefan Richter 
53828646821SStefan Richter 	lynx->registers = ioremap_nocache(pci_resource_start(dev, 0),
53928646821SStefan Richter 					  PCILYNX_MAX_REGISTER);
54028646821SStefan Richter 
54128646821SStefan Richter 	lynx->rcv_start_pcl = pci_alloc_consistent(lynx->pci_device,
542b5e47729SStefan Richter 				sizeof(struct pcl), &lynx->rcv_start_pcl_bus);
54328646821SStefan Richter 	lynx->rcv_pcl = pci_alloc_consistent(lynx->pci_device,
544b5e47729SStefan Richter 				sizeof(struct pcl), &lynx->rcv_pcl_bus);
545b5e47729SStefan Richter 	lynx->rcv_buffer = pci_alloc_consistent(lynx->pci_device,
546b5e47729SStefan Richter 				RCV_BUFFER_SIZE, &lynx->rcv_buffer_bus);
54728646821SStefan Richter 	if (lynx->rcv_start_pcl == NULL ||
54828646821SStefan Richter 	    lynx->rcv_pcl == NULL ||
549b5e47729SStefan Richter 	    lynx->rcv_buffer == NULL) {
55028646821SStefan Richter 		/* FIXME: do proper error handling. */
551b5e47729SStefan Richter 		error("Failed to allocate receive buffer\n");
552b5e47729SStefan Richter 		return -ENOMEM;
553b5e47729SStefan Richter 	}
55428646821SStefan Richter 	lynx->rcv_start_pcl->next = lynx->rcv_pcl_bus;
55528646821SStefan Richter 	lynx->rcv_pcl->next = PCL_NEXT_INVALID;
55628646821SStefan Richter 	lynx->rcv_pcl->async_error_next = PCL_NEXT_INVALID;
55728646821SStefan Richter 
55828646821SStefan Richter 	lynx->rcv_pcl->buffer[0].control =
55928646821SStefan Richter 		PCL_CMD_RCV | PCL_BIGENDIAN | 2044;
56028646821SStefan Richter 	lynx->rcv_pcl->buffer[0].pointer = lynx->rcv_buffer_bus + 4;
56128646821SStefan Richter 	p = lynx->rcv_buffer_bus + 2048;
56228646821SStefan Richter 	end = lynx->rcv_buffer_bus + RCV_BUFFER_SIZE;
56328646821SStefan Richter 	for (i = 1; p < end; i++, p += 2048) {
56428646821SStefan Richter 		lynx->rcv_pcl->buffer[i].control =
56528646821SStefan Richter 			PCL_CMD_RCV | PCL_BIGENDIAN | 2048;
56628646821SStefan Richter 		lynx->rcv_pcl->buffer[i].pointer = p;
56728646821SStefan Richter 	}
56828646821SStefan Richter 	lynx->rcv_pcl->buffer[i - 1].control |= PCL_LAST_BUFF;
56928646821SStefan Richter 
57028646821SStefan Richter 	reg_set_bits(lynx, MISC_CONTROL, MISC_CONTROL_SWRESET);
57128646821SStefan Richter 	/* Fix buggy cards with autoboot pin not tied low: */
57228646821SStefan Richter 	reg_write(lynx, DMA0_CHAN_CTRL, 0);
57328646821SStefan Richter 	reg_write(lynx, DMA_GLOBAL_REGISTER, 0x00 << 24);
57428646821SStefan Richter 
57528646821SStefan Richter #if 0
57628646821SStefan Richter 	/* now, looking for PHY register set */
57728646821SStefan Richter 	if ((get_phy_reg(lynx, 2) & 0xe0) == 0xe0) {
57828646821SStefan Richter 		lynx->phyic.reg_1394a = 1;
57928646821SStefan Richter 		PRINT(KERN_INFO, lynx->id,
58028646821SStefan Richter 		      "found 1394a conform PHY (using extended register set)");
58128646821SStefan Richter 		lynx->phyic.vendor = get_phy_vendorid(lynx);
58228646821SStefan Richter 		lynx->phyic.product = get_phy_productid(lynx);
58328646821SStefan Richter 	} else {
58428646821SStefan Richter 		lynx->phyic.reg_1394a = 0;
58528646821SStefan Richter 		PRINT(KERN_INFO, lynx->id, "found old 1394 PHY");
58628646821SStefan Richter 	}
58728646821SStefan Richter #endif
58828646821SStefan Richter 
58928646821SStefan Richter 	/* Setup the general receive FIFO max size. */
59028646821SStefan Richter 	reg_write(lynx, FIFO_SIZES, 255);
59128646821SStefan Richter 
59228646821SStefan Richter 	reg_set_bits(lynx, PCI_INT_ENABLE, PCI_INT_DMA_ALL);
59328646821SStefan Richter 
59428646821SStefan Richter 	reg_write(lynx, LINK_INT_ENABLE,
59528646821SStefan Richter 		  LINK_INT_PHY_TIME_OUT | LINK_INT_PHY_REG_RCVD |
59628646821SStefan Richter 		  LINK_INT_PHY_BUSRESET | LINK_INT_IT_STUCK |
59728646821SStefan Richter 		  LINK_INT_AT_STUCK | LINK_INT_SNTRJ |
59828646821SStefan Richter 		  LINK_INT_TC_ERR | LINK_INT_GRF_OVER_FLOW |
59928646821SStefan Richter 		  LINK_INT_ITF_UNDER_FLOW | LINK_INT_ATF_UNDER_FLOW);
60028646821SStefan Richter 
60128646821SStefan Richter 	/* Disable the L flag in self ID packets. */
60228646821SStefan Richter 	set_phy_reg(lynx, 4, 0);
60328646821SStefan Richter 
60428646821SStefan Richter 	/* Put this baby into snoop mode */
60528646821SStefan Richter 	reg_set_bits(lynx, LINK_CONTROL, LINK_CONTROL_SNOOP_ENABLE);
60628646821SStefan Richter 
60728646821SStefan Richter 	run_pcl(lynx, lynx->rcv_start_pcl_bus, 0);
60828646821SStefan Richter 
609b5e47729SStefan Richter 	if (request_irq(dev->irq, irq_handler, IRQF_SHARED,
610b5e47729SStefan Richter 			driver_name, lynx)) {
611b5e47729SStefan Richter 		error("Failed to allocate shared interrupt %d\n", dev->irq);
612b5e47729SStefan Richter 		return -EIO;
613b5e47729SStefan Richter 	}
61428646821SStefan Richter 
61528646821SStefan Richter 	lynx->misc.parent = &dev->dev;
61628646821SStefan Richter 	lynx->misc.minor = MISC_DYNAMIC_MINOR;
61728646821SStefan Richter 	lynx->misc.name = "nosy";
61828646821SStefan Richter 	lynx->misc.fops = &nosy_ops;
619b5e47729SStefan Richter 	if (misc_register(&lynx->misc)) {
620b5e47729SStefan Richter 		error("Failed to register misc char device\n");
621b5e47729SStefan Richter 		return -ENOMEM;
622b5e47729SStefan Richter 	}
62328646821SStefan Richter 	minors[lynx->misc.minor] = lynx;
62428646821SStefan Richter 
62528646821SStefan Richter 	notify("Initialized PCILynx IEEE1394 card, irq=%d\n", dev->irq);
62628646821SStefan Richter 
62728646821SStefan Richter 	return 0;
62828646821SStefan Richter }
62928646821SStefan Richter 
63028646821SStefan Richter static struct pci_device_id pci_table[] __devinitdata = {
63128646821SStefan Richter 	{
63228646821SStefan Richter 		.vendor =    PCI_VENDOR_ID_TI,
63328646821SStefan Richter 		.device =    PCI_DEVICE_ID_TI_PCILYNX,
63428646821SStefan Richter 		.subvendor = PCI_ANY_ID,
63528646821SStefan Richter 		.subdevice = PCI_ANY_ID,
63628646821SStefan Richter 	},
63728646821SStefan Richter 	{ }	/* Terminating entry */
63828646821SStefan Richter };
63928646821SStefan Richter 
64028646821SStefan Richter static struct pci_driver lynx_pci_driver = {
641b5e47729SStefan Richter 	.name =		driver_name,
64228646821SStefan Richter 	.id_table =	pci_table,
64328646821SStefan Richter 	.probe =	add_card,
644b5e47729SStefan Richter 	.remove =	remove_card,
64528646821SStefan Richter };
64628646821SStefan Richter 
647b5e47729SStefan Richter MODULE_AUTHOR("Kristian Hoegsberg");
64828646821SStefan Richter MODULE_DESCRIPTION("Snoop mode driver for TI pcilynx 1394 controllers");
64928646821SStefan Richter MODULE_LICENSE("GPL");
65028646821SStefan Richter MODULE_DEVICE_TABLE(pci, pci_table);
65128646821SStefan Richter 
65228646821SStefan Richter static int __init nosy_init(void)
65328646821SStefan Richter {
65428646821SStefan Richter 	return pci_register_driver(&lynx_pci_driver);
65528646821SStefan Richter }
65628646821SStefan Richter 
65728646821SStefan Richter static void __exit nosy_cleanup(void)
65828646821SStefan Richter {
65928646821SStefan Richter 	pci_unregister_driver(&lynx_pci_driver);
66028646821SStefan Richter 
66128646821SStefan Richter 	notify("Unloaded %s.\n", driver_name);
66228646821SStefan Richter }
66328646821SStefan Richter 
66428646821SStefan Richter module_init(nosy_init);
66528646821SStefan Richter module_exit(nosy_cleanup);
666