0x3f1));
}
+/*
+ * HI == seconds (bits 0:2)
+ * LO == fraction units of 1/8000 of a second, as per 1394 (bits 19:31)
+ *
+ * Convert to units and then to HZ, for comparison to jiffies.
+ *
+ * By default this will end up being 800 units, or 100ms (125usec per
+ * unit).
+ *
+ * NOTE: The spec says 1/8000, but also says we can compute based on 1/8192
+ * like CSR specifies. Should make our math less complex.
+ */
+static inline void calculate_expire(struct csr_control *csr)
+{
+ unsigned long units;
+
+ /* Take the seconds, and convert to units */
+ units = (unsigned long)(csr->split_timeout_hi & 0x07) << 13;
+
+ /* Add in the fractional units */
+ units += (unsigned long)(csr->split_timeout_lo >> 19);
+
+ /* Convert to jiffies */
+ csr->expire = (unsigned long)(units * HZ) >> 13UL;
+
+ /* Just to keep from rounding low */
+ csr->expire++;
+
+ HPSB_VERBOSE("CSR: setting expire to %lu, HZ=%lu", csr->expire, HZ);
+}
+
static void add_host(struct hpsb_host *host)
{
host->csr.node_ids = 0;
host->csr.split_timeout_hi = 0;
host->csr.split_timeout_lo = 800 << 19;
+ calculate_expire(&host->csr);
host->csr.cycle_time = 0;
host->csr.bus_time = 0;
host->csr.bus_manager_id = 0x3f;
case CSR_SPLIT_TIMEOUT_HI:
host->csr.split_timeout_hi =
be32_to_cpu(*(data++)) & 0x00000007;
+ calculate_expire(&host->csr);
out;
case CSR_SPLIT_TIMEOUT_LO:
host->csr.split_timeout_lo =
be32_to_cpu(*(data++)) & 0xfff80000;
+ calculate_expire(&host->csr);
out;
/* address gap */
* eventually. */
HPSB_WARN("Node [" NODE_BUS_FMT "] wants to release "
"broadcast channel 31. Ignoring.",
- NODE_BUS_ARGS(nodeid));
+ NODE_BUS_ARGS(host, nodeid));
data &= ~0x1; /* keep broadcast channel allocated */
}
* eventually. */
HPSB_WARN("Node [" NODE_BUS_FMT "] wants to release "
"broadcast channel 31. Ignoring.",
- NODE_BUS_ARGS(nodeid));
+ NODE_BUS_ARGS(host, nodeid));
data &= ~0x100000000ULL; /* keep broadcast channel allocated */
}
quadlet_t state;
quadlet_t node_ids;
quadlet_t split_timeout_hi, split_timeout_lo;
+ unsigned long expire; // Calculated from split_timeout
quadlet_t cycle_time;
quadlet_t bus_time;
quadlet_t bus_manager_id;
for (i = 0; i < dma->n_dma_pages; i++) {
if (off < sg_dma_len(&dma->sglist[i])) {
*rem = off;
- return i;
+ break;
}
off -= sg_dma_len(&dma->sglist[i]);
}
- panic("dma_region_find: offset %lu beyond end of DMA mapping\n", offset);
+ BUG_ON(i >= dma->n_dma_pages);
+
+ return i;
}
dma_addr_t dma_region_offset_to_bus(struct dma_region *dma, unsigned long offset)
/*
* dv1394-private.h - DV input/output over IEEE 1394 on OHCI chips
* Copyright (C)2001 Daniel Maas <dmaas@dcine.com>
- * receive, proc_fs by Dan Dennedy <dan@dennedy.org>
+ * receive by Dan Dennedy <dan@dennedy.org>
*
* based on:
* video1394.h - driver for OHCI 1394 boards
/*
* dv1394.c - DV input/output over IEEE 1394 on OHCI chips
* Copyright (C)2001 Daniel Maas <dmaas@dcine.com>
- * receive, proc_fs by Dan Dennedy <dan@dennedy.org>
+ * receive by Dan Dennedy <dan@dennedy.org>
*
* based on:
* video1394.c - video driver for OHCI 1394 boards
- add proc fs interface to set cip_n, cip_d, syt_offset, and video signal
- expose xmit and recv as separate devices (not exclusive)
- expose NTSC and PAL as separate devices (can be overridden)
- - read/edit channel in procfs
*/
#include <asm/atomic.h>
#include <asm/io.h>
#include <asm/uaccess.h>
-#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <asm/pgtable.h>
#include <asm/page.h>
init.api_version = DV1394_API_VERSION;
init.n_frames = DV1394_MAX_FRAMES / 4;
- /* the following are now set via proc_fs or devfs */
+ /* the following are now set via devfs */
init.channel = video->channel;
init.format = video->pal_or_ntsc;
init.cip_n = video->cip_n;
}
-/*** PROC_FS INTERFACE ******************************************************/
-#ifdef CONFIG_PROC_FS
-static LIST_HEAD(dv1394_procfs);
-struct dv1394_procfs_entry {
- struct list_head list;
- struct proc_dir_entry *procfs;
- char name[32];
- struct dv1394_procfs_entry *parent;
-};
-static spinlock_t dv1394_procfs_lock = SPIN_LOCK_UNLOCKED;
-
-static int dv1394_procfs_read( char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct video_card *video = (struct video_card*) data;
-
- snprintf( page, count,
- "\
-format=%s\n\
-channel=%d\n\
-cip_n=%lu\n\
-cip_d=%lu\n\
-syt_offset=%u\n",
- (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"),
- video->channel,
- video->cip_n, video->cip_d, video->syt_offset );
- return strlen(page);
-}
-
-/* lifted from the stallion.c driver */
-#undef TOLOWER
-#define TOLOWER(x) ((((x) >= 'A') && ((x) <= 'Z')) ? ((x) + 0x20) : (x))
-static unsigned long atol(char *str)
-{
- unsigned long val;
- int base, c;
- char *sp;
-
- val = 0;
- sp = str;
- if ((*sp == '0') && (*(sp+1) == 'x')) {
- base = 16;
- sp += 2;
- } else if (*sp == '0') {
- base = 8;
- sp++;
- } else {
- base = 10;
- }
-
- for (; (*sp != 0); sp++) {
- c = (*sp > '9') ? (TOLOWER(*sp) - 'a' + 10) : (*sp - '0');
- if ((c < 0) || (c >= base)) {
- printk(KERN_ERR "dv1394: atol() invalid argument %s\n", str);
- val = 0;
- break;
- }
- val = (val * base) + c;
- }
- return(val);
-}
-
-static int dv1394_procfs_write( struct file *file,
- const char *buffer, unsigned long count, void *data)
-{
- int len = 0;
- char new_value[65];
- char *pos;
- struct video_card *video = (struct video_card*) data;
-
- if (count > 64)
- len = 64;
- else
- len = count;
-
- if (copy_from_user( new_value, buffer, len))
- return -EFAULT;
-
- new_value[len] = 0;
- pos = strchr(new_value, '=');
- if (pos != NULL) {
- int val_len = len - (pos-new_value) - 1;
- char buf[65];
- memset(buf, 0, 65);
- strncpy(buf, pos+1, val_len);
- if (buf[val_len-1] == '\n') buf[val_len-1] = 0;
-
- if (strnicmp( new_value, "format", (pos-new_value)) == 0) {
- if (strnicmp( buf, "NTSC", val_len) == 0)
- video->pal_or_ntsc = DV1394_NTSC;
- else if (strnicmp( buf, "PAL", val_len) == 0)
- video->pal_or_ntsc = DV1394_PAL;
-
- } else if (strnicmp( new_value, "cip_n", (pos-new_value)) == 0) {
- video->cip_n = atol(buf);
- } else if (strnicmp( new_value, "cip_d", (pos-new_value)) == 0) {
- video->cip_d = atol(buf);
- } else if (strnicmp( new_value, "syt_offset", (pos-new_value)) == 0) {
- video->syt_offset = atol(buf);
- } else if (strnicmp( new_value, "channel", (pos-new_value)) == 0) {
- video->channel = atol(buf);
- }
- }
-
- return len;
-}
-
-struct dv1394_procfs_entry *
-dv1394_procfs_find( char *name)
-{
- struct list_head *lh;
- struct dv1394_procfs_entry *p;
-
- spin_lock( &dv1394_procfs_lock);
- if (!list_empty(&dv1394_procfs)) {
- list_for_each(lh, &dv1394_procfs) {
- p = list_entry(lh, struct dv1394_procfs_entry, list);
- if (!strncmp(p->name, name, sizeof(p->name))) {
- spin_unlock( &dv1394_procfs_lock);
- return p;
- }
- }
- }
- spin_unlock( &dv1394_procfs_lock);
- return NULL;
-}
-
-static int dv1394_procfs_add_entry(struct video_card *video)
-{
- char buf[32];
- struct dv1394_procfs_entry *p;
- struct dv1394_procfs_entry *parent;
-
- p = kmalloc(sizeof(struct dv1394_procfs_entry), GFP_KERNEL);
- if (!p) {
- printk(KERN_ERR "dv1394: cannot allocate dv1394_procfs_entry\n");
- goto err;
- }
- memset(p, 0, sizeof(struct dv1394_procfs_entry));
-
- snprintf(buf, sizeof(buf), "dv/host%d/%s", (video->id>>2),
- (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"));
-
- parent = dv1394_procfs_find(buf);
- if (parent == NULL) {
- printk(KERN_ERR "dv1394: unable to locate parent procfs of %s\n", buf);
- goto err_free;
- }
-
- p->procfs = create_proc_entry(
- (video->mode == MODE_RECEIVE ? "in" : "out"),
- 0666, parent->procfs);
-
- if (p->procfs == NULL) {
- printk(KERN_ERR "dv1394: unable to create /proc/bus/ieee1394/%s/%s\n",
- parent->name,
- (video->mode == MODE_RECEIVE ? "in" : "out"));
- goto err_free;
- }
-
- p->procfs->owner = THIS_MODULE;
- p->procfs->data = video;
- p->procfs->read_proc = dv1394_procfs_read;
- p->procfs->write_proc = dv1394_procfs_write;
-
- spin_lock( &dv1394_procfs_lock);
- INIT_LIST_HEAD(&p->list);
- list_add_tail(&p->list, &dv1394_procfs);
- spin_unlock( &dv1394_procfs_lock);
-
- return 0;
-
- err_free:
- kfree(p);
- err:
- return -ENOMEM;
-}
-
-static int
-dv1394_procfs_add_dir( char *name,
- struct dv1394_procfs_entry *parent,
- struct dv1394_procfs_entry **out)
-{
- struct dv1394_procfs_entry *p;
-
- p = kmalloc(sizeof(struct dv1394_procfs_entry), GFP_KERNEL);
- if (!p) {
- printk(KERN_ERR "dv1394: cannot allocate dv1394_procfs_entry\n");
- goto err;
- }
- memset(p, 0, sizeof(struct dv1394_procfs_entry));
-
- if (parent == NULL) {
- snprintf(p->name, sizeof(p->name), "%s", name);
- p->procfs = proc_mkdir( name, ieee1394_procfs_entry);
- } else {
- snprintf(p->name, sizeof(p->name), "%s/%s", parent->name, name);
- p->procfs = proc_mkdir( name, parent->procfs);
- }
- if (p->procfs == NULL) {
- printk(KERN_ERR "dv1394: unable to create /proc/bus/ieee1394/%s\n", p->name);
- goto err_free;
- }
-
- p->procfs->owner = THIS_MODULE;
- p->parent = parent;
- if (out != NULL) *out = p;
-
- spin_lock( &dv1394_procfs_lock);
- INIT_LIST_HEAD(&p->list);
- list_add_tail(&p->list, &dv1394_procfs);
- spin_unlock( &dv1394_procfs_lock);
-
- return 0;
-
- err_free:
- kfree(p);
- err:
- return -ENOMEM;
-}
-
-void dv1394_procfs_del( char *name)
-{
- struct dv1394_procfs_entry *p = dv1394_procfs_find(name);
- if (p != NULL) {
- if (p->parent == NULL)
- remove_proc_entry(p->name, ieee1394_procfs_entry);
- else
- remove_proc_entry(p->name, p->parent->procfs);
-
- spin_lock( &dv1394_procfs_lock);
- list_del(&p->list);
- spin_unlock( &dv1394_procfs_lock);
- kfree(p);
- }
-}
-#endif /* CONFIG_PROC_FS */
-
/*** DEVICE DRIVER HANDLERS ************************************************/
static void it_tasklet_func(unsigned long data)
video->channel = 63; /* default to broadcast channel */
video->active_frame = -1;
- /* initialize the following for proc_fs */
+ /* initialize the following */
video->pal_or_ntsc = format;
video->cip_n = 0; /* 0 = use builtin default */
video->cip_d = 0;
video->syt_offset = 0;
video->mode = mode;
-#ifdef CONFIG_PROC_FS
- if ( dv1394_procfs_add_entry(video) < 0 )
- goto err_free;
-#endif
-
for (i = 0; i < DV1394_MAX_FRAMES; i++)
video->frames[i] = NULL;
);
devfs_remove("ieee1394/%s", buf);
-#ifdef CONFIG_PROC_FS
- dv1394_procfs_del(buf);
-#endif
list_del(&video->list);
kfree(video);
}
struct video_card *video = NULL;
unsigned long flags;
struct list_head *lh, *templh;
- char buf[32];
int n;
/* We only work with the OHCI-1394 driver */
devfs_remove("ieee1394/dv/host%d/NTSC", n);
devfs_remove("ieee1394/dv/host%d/PAL", n);
devfs_remove("ieee1394/dv/host%d", n);
-
-#ifdef CONFIG_PROC_FS
- snprintf(buf, sizeof(buf), "dv/host%d/NTSC", n);
- dv1394_procfs_del(buf);
- snprintf(buf, sizeof(buf), "dv/host%d/PAL", n);
- dv1394_procfs_del(buf);
- snprintf(buf, sizeof(buf), "dv/host%d", n);
- dv1394_procfs_del(buf);
-#endif
}
static void dv1394_add_host (struct hpsb_host *host)
{
struct ti_ohci *ohci;
- char buf[16];
/* We only work with the OHCI-1394 driver */
if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME))
ohci = (struct ti_ohci *)host->hostdata;
-#ifdef CONFIG_PROC_FS
-{
- struct dv1394_procfs_entry *p;
- p = dv1394_procfs_find("dv");
- if (p != NULL) {
- snprintf(buf, sizeof(buf), "host%d", ohci->id);
- dv1394_procfs_add_dir(buf, p, &p);
- dv1394_procfs_add_dir("NTSC", p, NULL);
- dv1394_procfs_add_dir("PAL", p, NULL);
- }
-}
-#endif
-
devfs_mk_dir("ieee1394/dv/host%d", ohci->id);
devfs_mk_dir("ieee1394/dv/host%d/NTSC", ohci->id);
devfs_mk_dir("ieee1394/dv/host%d/PAL", ohci->id);
hpsb_unregister_highlevel(&dv1394_highlevel);
ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
devfs_remove("ieee1394/dv");
-#ifdef CONFIG_PROC_FS
- dv1394_procfs_del("dv");
-#endif
}
static int __init dv1394_init_module(void)
devfs_mk_dir("ieee1394/dv");
-#ifdef CONFIG_PROC_FS
- ret = dv1394_procfs_add_dir("dv",NULL,NULL);
- if (ret < 0) {
- printk(KERN_ERR "dv1394: unable to create /proc/bus/ieee1394/dv\n");
- ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
- devfs_remove("ieee1394/dv");
- return -ENOMEM;
- }
-#endif
-
hpsb_register_highlevel(&dv1394_highlevel);
hpsb_register_protocol(&dv1394_driver);
/*
* dv1394.h - DV input/output over IEEE 1394 on OHCI chips
* Copyright (C)2001 Daniel Maas <dmaas@dcine.com>
- * receive, proc_fs by Dan Dennedy <dan@dennedy.org>
+ * receive by Dan Dennedy <dan@dennedy.org>
*
* based on:
* video1394.h - driver for OHCI 1394 boards
#define TRACE() printk(KERN_ERR "%s:%s[%d] ---- TRACE\n", driver_name, __FUNCTION__, __LINE__)
static char version[] __devinitdata =
- "$Rev: 986 $ Ben Collins <bcollins@debian.org>";
+ "$Rev: 1010 $ Ben Collins <bcollins@debian.org>";
struct fragment_info {
struct list_head list;
if (hpsb_get_tlabel(p, !in_interrupt())) {
ETH1394_PRINT_G(KERN_ERR, "No more tlabels left while sending "
- "to node " NODE_BUS_FMT "\n", NODE_BUS_ARGS(node));
+ "to node " NODE_BUS_FMT "\n", NODE_BUS_ARGS(host, node));
return -1;
}
p->header[0] = (p->node_id << 16) | (p->tlabel << 10)
case ETHTOOL_GDRVINFO: {
struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
strcpy (info.driver, driver_name);
- strcpy (info.version, "$Rev: 986 $");
+ strcpy (info.version, "$Rev: 1010 $");
/* FIXME XXX provide sane businfo */
strcpy (info.bus_info, "ieee1394");
if (copy_to_user (useraddr, &info, sizeof (info)))
*/
struct hpsb_highlevel {
+ struct module *owner;
const char *name;
/* Any of the following pointers can legally be NULL, except for
#include <linux/list.h>
#include <linux/init.h>
#include <linux/slab.h>
-#include <linux/workqueue.h>
#include "ieee1394_types.h"
#include "hosts.h"
list_for_each(lh, &hpsb_hosts) {
if (host == list_entry(lh, struct hpsb_host, host_list)) {
if (try_module_get(host->driver->owner)) {
- host->refcount++;
+ atomic_inc(&host->refcount);
retval = 1;
}
break;
module_put(host->driver->owner);
down(&hpsb_hosts_lock);
- host->refcount--;
-
- if (!host->refcount && host->is_shutdown)
+ if (atomic_dec_and_test(&host->refcount) && host->is_shutdown)
kfree(host);
up(&hpsb_hosts_lock);
}
h->hostdata = h + 1;
h->driver = drv;
- h->refcount = 1;
+ atomic_set(&h->refcount, 1);
INIT_LIST_HEAD(&h->pending_packets);
spin_lock_init(&h->pending_pkt_lock);
atomic_set(&h->generation, 0);
- INIT_WORK(&h->timeout_tq, (void (*)(void*))abort_timedouts, h);
+ init_timer(&h->timeout);
+ h->timeout.data = (unsigned long) h;
+ h->timeout.function = abort_timedouts;
+ h->timeout_interval = HZ / 20; // 50ms by default
h->topology_map = h->csr.topology_map + 3;
h->speed_map = (u8 *)(h->csr.speed_map + 2);
#include <linux/device.h>
#include <linux/wait.h>
#include <linux/list.h>
-#include <linux/workqueue.h>
+#include <linux/timer.h>
#include <asm/semaphore.h>
#include "ieee1394_types.h"
atomic_t generation;
- int refcount;
+ atomic_t refcount;
struct list_head pending_packets;
spinlock_t pending_pkt_lock;
- struct work_struct timeout_tq;
+ struct timer_list timeout;
+ unsigned long timeout_interval;
unsigned char iso_listen_count[64];
enum isoctl_cmd {
/* rawiso API - see iso.h for the meanings of these commands
+ (they correspond exactly to the hpsb_iso_* API functions)
* INIT = allocate resources
* START = begin transmission/reception
* STOP = halt transmission/reception
RECV_STOP,
RECV_RELEASE,
RECV_SHUTDOWN,
+ RECV_FLUSH
};
enum reset_types {
_IOW ('#', 0x27, struct raw1394_iso_packets)
#define RAW1394_IOC_ISO_XMIT_SYNC \
_IO ('#', 0x28)
+#define RAW1394_IOC_ISO_RECV_FLUSH \
+ _IO ('#', 0x29)
#endif /* __IEEE1394_IOCTL_H */
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/proc_fs.h>
#include <linux/bitops.h>
-#include <linux/workqueue.h>
#include <linux/kdev_t.h>
#include <asm/byteorder.h>
#include <asm/semaphore.h>
/* Some globals used */
const char *hpsb_speedto_str[] = { "S100", "S200", "S400", "S800", "S1600", "S3200" };
+#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
static void dump_packet(const char *text, quadlet_t *data, int size)
{
- int i;
+ int i;
- size /= 4;
- size = (size > 4 ? 4 : size);
+ size /= 4;
+ size = (size > 4 ? 4 : size);
- printk(KERN_DEBUG "ieee1394: %s", text);
- for (i = 0; i < size; i++) {
- printk(" %8.8x", data[i]);
- }
- printk("\n");
+ printk(KERN_DEBUG "ieee1394: %s", text);
+ for (i = 0; i < size; i++)
+ printk(" %08x", data[i]);
+ printk("\n");
}
+#else
+#define dump_packet(x,y,z)
+#endif
static void run_packet_complete(struct hpsb_packet *packet)
{
void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid)
{
if (host->in_bus_reset) {
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
- HPSB_INFO("Including SelfID 0x%x", sid);
-#endif
+ HPSB_VERBOSE("Including SelfID 0x%x", sid);
host->topology_map[host->selfid_count++] = sid;
} else {
HPSB_NOTICE("Spurious SelfID packet (0x%08x) received from bus %d",
} else {
HPSB_NOTICE("Stopping out-of-control reset loop");
HPSB_NOTICE("Warning - topology map and speed map will not be valid");
+ host->reset_retries = 0;
}
} else {
+ host->reset_retries = 0;
build_speed_map(host, host->node_count);
}
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
- HPSB_INFO("selfid_complete called with successful SelfID stage "
- "... irm_id: 0x%X node_id: 0x%X",host->irm_id,host->node_id);
-#endif
+ HPSB_VERBOSE("selfid_complete called with successful SelfID stage "
+ "... irm_id: 0x%X node_id: 0x%X",host->irm_id,host->node_id);
+
/* irm_id is kept up to date by check_selfids() */
if (host->irm_id == host->node_id) {
host->is_irm = 1;
spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
up(&packet->state_change);
- schedule_work(&host->timeout_tq);
+ mod_timer(&host->timeout, jiffies + host->timeout_interval);
}
/**
}
}
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
dump_packet("send packet local:", packet->header,
packet->header_size);
-#endif
+
hpsb_packet_sent(host, packet, packet->expect_response?ACK_PENDING:ACK_COMPLETE);
hpsb_packet_received(host, data, size, 0);
+ NODEID_TO_NODE(packet->node_id)];
}
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
switch (packet->speed_code) {
case 2:
dump_packet("send packet 400:", packet->header,
dump_packet("send packet 100:", packet->header,
packet->header_size);
}
-#endif
return host->driver->transmit_packet(host, packet);
}
}
if (lh == &host->pending_packets) {
- HPSB_DEBUG("unsolicited response packet received - np");
+ HPSB_DEBUG("unsolicited response packet received - no tlabel match");
dump_packet("contents:", data, 16);
spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
return;
if (!tcode_match || (packet->tlabel != tlabel)
|| (packet->node_id != (data[1] >> 16))) {
- HPSB_INFO("unsolicited response packet received");
+ HPSB_INFO("unsolicited response packet received - tcode mismatch");
dump_packet("contents:", data, 16);
spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
return;
}
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
dump_packet("received packet:", data, size);
-#endif
tcode = (data[0] >> 4) & 0xf;
}
}
-void abort_timedouts(struct hpsb_host *host)
+void abort_timedouts(unsigned long __opaque)
{
+ struct hpsb_host *host = (struct hpsb_host *)__opaque;
unsigned long flags;
struct hpsb_packet *packet;
unsigned long expire;
- struct list_head *lh, *next, *tlh;
+ struct list_head *lh, *tlh;
LIST_HEAD(expiredlist);
spin_lock_irqsave(&host->csr.lock, flags);
- expire = (host->csr.split_timeout_hi * 8000
- + (host->csr.split_timeout_lo >> 19))
- * HZ / 8000;
- /* Avoid shortening of timeout due to rounding errors: */
- expire++;
+ expire = host->csr.expire;
spin_unlock_irqrestore(&host->csr.lock, flags);
-
spin_lock_irqsave(&host->pending_pkt_lock, flags);
- for (lh = host->pending_packets.next; lh != &host->pending_packets; lh = next) {
+ list_for_each_safe(lh, tlh, &host->pending_packets) {
packet = list_entry(lh, struct hpsb_packet, list);
- next = lh->next;
if (time_before(packet->sendtime + expire, jiffies)) {
list_del(&packet->list);
list_add(&packet->list, &expiredlist);
}
if (!list_empty(&host->pending_packets))
- schedule_work(&host->timeout_tq);
+ mod_timer(&host->timeout, jiffies + host->timeout_interval);
spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
return retval;
}
-struct proc_dir_entry *ieee1394_procfs_entry;
-
static int __init ieee1394_init(void)
{
hpsb_packet_cache = kmem_cache_create("hpsb_packet", sizeof(struct hpsb_packet),
return -ENODEV;
}
-#ifdef CONFIG_PROC_FS
- /* Must be done before we start everything else, since the drivers
- * may use it. */
- ieee1394_procfs_entry = proc_mkdir("ieee1394", proc_bus);
- if (ieee1394_procfs_entry == NULL) {
- HPSB_ERR("unable to create /proc/bus/ieee1394\n");
- unregister_chrdev(IEEE1394_MAJOR, "ieee1394");
- devfs_remove("ieee1394");
- return -ENOMEM;
- }
- ieee1394_procfs_entry->owner = THIS_MODULE;
-#endif
-
init_hpsb_highlevel();
init_csr();
if (!disable_nodemgr)
unregister_chrdev(IEEE1394_MAJOR, "ieee1394");
devfs_remove("ieee1394");
- remove_proc_entry("ieee1394", proc_bus);
}
module_init(ieee1394_init);
EXPORT_SYMBOL(hpsb_packet_received);
EXPORT_SYMBOL(ieee1394_register_chardev);
EXPORT_SYMBOL(ieee1394_unregister_chardev);
-EXPORT_SYMBOL(ieee1394_procfs_entry);
/** ieee1394_transactions.c **/
EXPORT_SYMBOL(hpsb_get_tlabel);
EXPORT_SYMBOL(hpsb_iso_packet_sent);
EXPORT_SYMBOL(hpsb_iso_packet_received);
EXPORT_SYMBOL(hpsb_iso_wake);
+EXPORT_SYMBOL(hpsb_iso_recv_flush);
#include <linux/slab.h>
#include <linux/devfs_fs_kernel.h>
-#include <linux/proc_fs.h>
#include <asm/semaphore.h>
#include "hosts.h"
return list_entry(l, struct hpsb_packet, driver_list);
}
-void abort_timedouts(struct hpsb_host *host);
+void abort_timedouts(unsigned long __opaque);
void abort_requests(struct hpsb_host *host);
struct hpsb_packet *alloc_hpsb_packet(size_t data_size);
/* release a block of minor numbers */
void ieee1394_unregister_chardev(int blocknum);
-/* the proc_fs entry for /proc/ieee1394 */
-extern struct proc_dir_entry *ieee1394_procfs_entry;
-
/* Our sysfs bus entry */
extern struct bus_type ieee1394_bus_type;
u16 specifier_id_hi = (specifier_id & 0x00ffff00) >> 8;
u8 specifier_id_lo = specifier_id & 0xff;
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
- HPSB_DEBUG("Send GASP: channel = %d, length = %d", channel, length);
-#endif
+ HPSB_VERBOSE("Send GASP: channel = %d, length = %d", channel, length);
length += 8;
#define NODEID_TO_NODE(nodeid) (nodeid & NODE_MASK)
/* Can be used to consistently print a node/bus ID. */
-#define NODE_BUS_FMT "%02d:%04d"
-#define NODE_BUS_ARGS(nodeid) NODEID_TO_NODE(nodeid), NODEID_TO_BUS(nodeid)
+#define NODE_BUS_FMT "%d-%02d:%04d"
+#define NODE_BUS_ARGS(__host, __nodeid) \
+ __host->id, NODEID_TO_NODE(__nodeid), NODEID_TO_BUS(__nodeid)
#define HPSB_PRINT(level, fmt, args...) printk(level "ieee1394: " fmt "\n" , ## args)
#define HPSB_WARN(fmt, args...) HPSB_PRINT(KERN_WARNING, fmt , ## args)
#define HPSB_ERR(fmt, args...) HPSB_PRINT(KERN_ERR, fmt , ## args)
+#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
+#define HPSB_VERBOSE(fmt, args...) HPSB_PRINT(KERN_DEBUG, fmt , ## args)
+#else
+#define HPSB_VERBOSE(fmt, args...)
+#endif
+
#define HPSB_PANIC(fmt, args...) panic("ieee1394: " fmt "\n" , ## args)
#define HPSB_TRACE() HPSB_PRINT(KERN_INFO, "TRACE - %s, %s(), line %d", __FILE__, __FUNCTION__, __LINE__)
return iso->host->driver->isoctl(iso, RECV_SET_CHANNEL_MASK, (unsigned long) &mask);
}
+int hpsb_iso_recv_flush(struct hpsb_iso *iso)
+{
+ if (iso->type != HPSB_ISO_RECV)
+ return -EINVAL;
+ return iso->host->driver->isoctl(iso, RECV_FLUSH, 0);
+}
+
static int do_iso_xmit_start(struct hpsb_iso *iso, int cycle)
{
int retval = iso->host->driver->isoctl(iso, XMIT_START, cycle);
/* N packets have been read out of the buffer, re-use the buffer space */
int hpsb_iso_recv_release_packets(struct hpsb_iso *recv, unsigned int n_packets);
+/* check for arrival of new packets immediately (even if irq_interval
+ has not yet been reached) */
+int hpsb_iso_recv_flush(struct hpsb_iso *iso);
+
/* returns # of packets ready to send or receive */
int hpsb_iso_n_ready(struct hpsb_iso *iso);
static void nodemgr_remove_ud(struct unit_directory *ud)
{
struct device *dev = &ud->device;
+ struct list_head *lh, *next;
int i;
+ list_for_each_safe(lh, next, &ud->device.children) {
+ struct unit_directory *ud;
+ ud = container_of(list_to_dev(lh), struct unit_directory, device);
+ nodemgr_remove_ud(ud);
+ }
+
for (i = 0; i < ARRAY_SIZE(fw_ud_attrs); i++)
device_remove_file(dev, fw_ud_attrs[i]);
ud = container_of(list_to_dev(lh), struct unit_directory, device);
snprintf(ud->device.name, DEVICE_NAME_SIZE,
- "IEEE-1394 unit directory %d-" NODE_BUS_FMT "-%u",
- hi->host->id, NODE_BUS_ARGS(ne->nodeid), ud->id);
+ "IEEE-1394 unit directory " NODE_BUS_FMT "-%u",
+ NODE_BUS_ARGS(hi->host, ne->nodeid), ud->id);
}
}
snprintf(ne->device.bus_id, BUS_ID_SIZE, "%016Lx",
(unsigned long long)(ne->guid));
snprintf(ne->device.name, DEVICE_NAME_SIZE,
- "IEEE-1394 device %d-" NODE_BUS_FMT, host->id,
- NODE_BUS_ARGS(ne->nodeid));
+ "IEEE-1394 device " NODE_BUS_FMT,
+ NODE_BUS_ARGS(host, ne->nodeid));
device_register(&ne->device);
nodemgr_update_ud_names(hi, ne);
- HPSB_DEBUG("%s added: ID:BUS[%d-" NODE_BUS_FMT "] GUID[%016Lx]",
+ HPSB_DEBUG("%s added: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
(host->node_id == nodeid) ? "Host" : "Node",
- host->id, NODE_BUS_ARGS(nodeid), (unsigned long long)guid);
+ NODE_BUS_ARGS(host, nodeid), (unsigned long long)guid);
return ne;
}
* immediate unit directories looking for software_id and
* software_version entries, in order to get driver autoloading working. */
static struct unit_directory *nodemgr_process_unit_directory
- (struct host_info *hi, struct node_entry *ne, octlet_t address, unsigned int *id)
+ (struct host_info *hi, struct node_entry *ne, octlet_t address, unsigned int *id,
+ struct unit_directory *parent)
{
struct unit_directory *ud;
quadlet_t quad;
break;
case CONFIG_ROM_LOGICAL_UNIT_DIRECTORY:
- /* TODO: Parent this with it's UD */
- ud_temp = nodemgr_process_unit_directory(hi, ne, address + value * 4, id);
+ ud->flags |= UNIT_DIRECTORY_HAS_LUN_DIRECTORY;
+ ud_temp = nodemgr_process_unit_directory(hi, ne, address + value * 4, id,
+ parent);
+
+ if (ud_temp == NULL)
+ break;
/* inherit unspecified values */
- if (ud_temp != NULL)
+ if ((ud->flags & UNIT_DIRECTORY_VENDOR_ID) &&
+ !(ud_temp->flags & UNIT_DIRECTORY_VENDOR_ID))
{
- if ((ud->flags & UNIT_DIRECTORY_VENDOR_ID) &&
- !(ud_temp->flags & UNIT_DIRECTORY_VENDOR_ID))
- {
- ud_temp->flags |= UNIT_DIRECTORY_VENDOR_ID;
- ud_temp->vendor_id = ud->vendor_id;
- ud_temp->vendor_oui = ud->vendor_oui;
- }
- if ((ud->flags & UNIT_DIRECTORY_MODEL_ID) &&
- !(ud_temp->flags & UNIT_DIRECTORY_MODEL_ID))
- {
- ud_temp->flags |= UNIT_DIRECTORY_MODEL_ID;
- ud_temp->model_id = ud->model_id;
- }
- if ((ud->flags & UNIT_DIRECTORY_SPECIFIER_ID) &&
- !(ud_temp->flags & UNIT_DIRECTORY_SPECIFIER_ID))
- {
- ud_temp->flags |= UNIT_DIRECTORY_SPECIFIER_ID;
- ud_temp->specifier_id = ud->specifier_id;
- }
- if ((ud->flags & UNIT_DIRECTORY_VERSION) &&
- !(ud_temp->flags & UNIT_DIRECTORY_VERSION))
- {
- ud_temp->flags |= UNIT_DIRECTORY_VERSION;
- ud_temp->version = ud->version;
- }
+ ud_temp->flags |= UNIT_DIRECTORY_VENDOR_ID;
+ ud_temp->vendor_id = ud->vendor_id;
+ ud_temp->vendor_oui = ud->vendor_oui;
+ }
+ if ((ud->flags & UNIT_DIRECTORY_MODEL_ID) &&
+ !(ud_temp->flags & UNIT_DIRECTORY_MODEL_ID))
+ {
+ ud_temp->flags |= UNIT_DIRECTORY_MODEL_ID;
+ ud_temp->model_id = ud->model_id;
+ }
+ if ((ud->flags & UNIT_DIRECTORY_SPECIFIER_ID) &&
+ !(ud_temp->flags & UNIT_DIRECTORY_SPECIFIER_ID))
+ {
+ ud_temp->flags |= UNIT_DIRECTORY_SPECIFIER_ID;
+ ud_temp->specifier_id = ud->specifier_id;
+ }
+ if ((ud->flags & UNIT_DIRECTORY_VERSION) &&
+ !(ud_temp->flags & UNIT_DIRECTORY_VERSION))
+ {
+ ud_temp->flags |= UNIT_DIRECTORY_VERSION;
+ ud_temp->version = ud->version;
}
break;
memcpy(&ud->device, &nodemgr_dev_template_ud,
sizeof(ud->device));
- ud->device.parent = &ne->device;
+
+ if (parent) {
+ ud->flags |= UNIT_DIRECTORY_LUN_DIRECTORY;
+ ud->device.parent = &parent->device;
+ } else
+ ud->device.parent = &ne->device;
+
snprintf(ud->device.bus_id, BUS_ID_SIZE, "%s-%u",
ne->device.bus_id, ud->id);
break;
case CONFIG_ROM_UNIT_DIRECTORY:
- nodemgr_process_unit_directory(hi, ne, address + value * 4, &ud_id);
+ nodemgr_process_unit_directory(hi, ne, address + value * 4, &ud_id,
+ NULL);
break;
case CONFIG_ROM_DESCRIPTOR_LEAF:
ne->busopt.generation = (busoptions >> 4) & 0xf;
ne->busopt.lnkspd = busoptions & 0x7;
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
- HPSB_DEBUG("NodeMgr: raw=0x%08x irmc=%d cmc=%d isc=%d bmc=%d pmc=%d "
- "cyc_clk_acc=%d max_rec=%d gen=%d lspd=%d",
- busoptions, ne->busopt.irmc, ne->busopt.cmc,
- ne->busopt.isc, ne->busopt.bmc, ne->busopt.pmc,
- ne->busopt.cyc_clk_acc, ne->busopt.max_rec,
- ne->busopt.generation, ne->busopt.lnkspd);
-#endif
+ HPSB_VERBOSE("NodeMgr: raw=0x%08x irmc=%d cmc=%d isc=%d bmc=%d pmc=%d "
+ "cyc_clk_acc=%d max_rec=%d gen=%d lspd=%d",
+ busoptions, ne->busopt.irmc, ne->busopt.cmc,
+ ne->busopt.isc, ne->busopt.bmc, ne->busopt.pmc,
+ ne->busopt.cyc_clk_acc, ne->busopt.max_rec,
+ ne->busopt.generation, ne->busopt.lnkspd);
+
device_remove_file(&ne->device, &dev_attr_ne_vendor_oui);
nodemgr_process_root_directory(hi, ne);
if (ne->nodeid != nodeid) {
snprintf(ne->device.name, DEVICE_NAME_SIZE,
- "IEEE-1394 device %d-" NODE_BUS_FMT,
- hi->host->id, NODE_BUS_ARGS(ne->nodeid));
- HPSB_DEBUG("Node changed: %d-" NODE_BUS_FMT " -> %d-" NODE_BUS_FMT,
- ne->host->id, NODE_BUS_ARGS(ne->nodeid),
- ne->host->id, NODE_BUS_ARGS(nodeid));
+ "IEEE-1394 device " NODE_BUS_FMT,
+ NODE_BUS_ARGS(hi->host, ne->nodeid));
+ HPSB_DEBUG("Node changed: " NODE_BUS_FMT " -> " NODE_BUS_FMT,
+ NODE_BUS_ARGS(ne->host, ne->nodeid),
+ NODE_BUS_ARGS(ne->host, nodeid));
ne->nodeid = nodeid;
update_ud_names++;
* work though, and we are forced to doing quadlet sized
* reads. */
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
- HPSB_INFO("Initiating ConfigROM request for node " NODE_BUS_FMT,
- NODE_BUS_ARGS(nodeid));
-#endif
+ HPSB_VERBOSE("Initiating ConfigROM request for node " NODE_BUS_FMT,
+ NODE_BUS_ARGS(host, nodeid));
+
/*
* Must retry a few times if config rom read returns zero (how long?). Will
* not normally occur, but we should do the right thing. For example, with
if (nodemgr_read_quadlet(host, nodeid, generation,
addr, &buffer[0]) < 0) {
HPSB_ERR("ConfigROM quadlet transaction error for node "
- NODE_BUS_FMT, NODE_BUS_ARGS(nodeid));
+ NODE_BUS_FMT, NODE_BUS_ARGS(host, nodeid));
return -1;
}
if (buffer[0])
if (header_size == 1) {
HPSB_INFO("Node " NODE_BUS_FMT " has a minimal ROM. "
"Vendor is %08x",
- NODE_BUS_ARGS(nodeid), buffer[0] & 0x00ffffff);
+ NODE_BUS_ARGS(host, nodeid), buffer[0] & 0x00ffffff);
return -1;
}
if (header_size < 4) {
HPSB_INFO("Node " NODE_BUS_FMT " has non-standard ROM "
"format (%d quads), cannot parse",
- NODE_BUS_ARGS(nodeid), header_size);
+ NODE_BUS_ARGS(host, nodeid), header_size);
return -1;
}
addr, &buffer[i]) < 0) {
HPSB_ERR("ConfigROM quadlet transaction "
"error for node " NODE_BUS_FMT,
- NODE_BUS_ARGS(nodeid));
+ NODE_BUS_ARGS(host, nodeid));
return -1;
}
}
* shouldn't be held responsible, so we'll allow it with a
* warning. */
HPSB_WARN("Node " NODE_BUS_FMT " has invalid busID magic [0x%08x]",
- NODE_BUS_ARGS(nodeid), buffer[1]);
+ NODE_BUS_ARGS(host, nodeid), buffer[1]);
}
guid = ((u64)buffer[3] << 32) | buffer[4];
nodemgr_remove_node)) {
struct node_entry *ne = cleanup.ne;
- HPSB_DEBUG("Node removed: ID:BUS[%d-" NODE_BUS_FMT "] GUID[%016Lx]",
- host->id, NODE_BUS_ARGS(ne->nodeid), (unsigned long long)ne->guid);
+ HPSB_DEBUG("Node removed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
+ NODE_BUS_ARGS(host, ne->nodeid), (unsigned long long)ne->guid);
nodemgr_remove_ne(ne);
}
* happens when we get a bus reset. */
while (!down_interruptible(&hi->reset_sem) &&
!down_interruptible(&nodemgr_serialize)) {
- unsigned int generation;
+ unsigned int generation = 0;
int i;
- /* Pause for 1/4 second, to make sure things settle down. */
- for (i = HZ/4; i > 0; i-= HZ/16) {
+ /* Pause for 1/4 second in 1/16 second intervals,
+ * to make sure things settle down. */
+ for (i = 0; i < 4 ; i++) {
set_current_state(TASK_INTERRUPTIBLE);
if (schedule_timeout(HZ/16))
goto caught_signal;
/* If we get a reset before we are done waiting, then
* start the the waiting over again */
while (!down_trylock(&hi->reset_sem))
- i = HZ/4;
+ i = 0;
}
if (!nodemgr_check_irm_capability(host, reset_cycles++)) {
}
caught_signal:
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
- HPSB_DEBUG ("NodeMgr: Exiting thread");
-#endif
+ HPSB_VERBOSE("NodeMgr: Exiting thread");
complete_and_exit(&hi->exited, 0);
}
struct host_info *hi = hpsb_get_hostinfo(&nodemgr_highlevel, host);
if (hi != NULL) {
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
- HPSB_DEBUG ("NodeMgr: Processing host reset for %s", hi->daemon_name);
-#endif
+ HPSB_VERBOSE("NodeMgr: Processing host reset for %s", hi->daemon_name);
up(&hi->reset_sem);
} else
HPSB_ERR ("NodeMgr: could not process reset of unused host");
};
-#define UNIT_DIRECTORY_VENDOR_ID 0x01
-#define UNIT_DIRECTORY_MODEL_ID 0x02
-#define UNIT_DIRECTORY_SPECIFIER_ID 0x04
-#define UNIT_DIRECTORY_VERSION 0x08
-#define UNIT_DIRECTORY_VENDOR_TEXT 0x10
-#define UNIT_DIRECTORY_MODEL_TEXT 0x20
+#define UNIT_DIRECTORY_VENDOR_ID 0x01
+#define UNIT_DIRECTORY_MODEL_ID 0x02
+#define UNIT_DIRECTORY_SPECIFIER_ID 0x04
+#define UNIT_DIRECTORY_VERSION 0x08
+#define UNIT_DIRECTORY_VENDOR_TEXT 0x10
+#define UNIT_DIRECTORY_MODEL_TEXT 0x20
+#define UNIT_DIRECTORY_HAS_LUN_DIRECTORY 0x40
+#define UNIT_DIRECTORY_LUN_DIRECTORY 0x80
/*
* A unit directory corresponds to a protocol supported by the
* Adam J Richter <adam@yggdrasil.com>
* . Use of pci_class to find device
*
- * Andreas Tobler <toa@pop.agri.ch>
- * . Updated proc_fs calls
- *
* Emilie Chung <emilie.chung@axis.com>
* . Tip on Async Request Filter
*
* Ben Collins <bcollins@debian.org>
* . Working big-endian support
* . Updated to 2.4.x module scheme (PCI aswell)
- * . Removed procfs support since it trashes random mem
* . Config ROM generation
*
* Manfred Weihs <weihs@ict.tuwien.ac.at>
#include <linux/pci.h>
#include <linux/fs.h>
#include <linux/poll.h>
+#include <linux/irq.h>
#include <asm/byteorder.h>
#include <asm/atomic.h>
#include <asm/uaccess.h>
printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
static char version[] __devinitdata =
- "$Rev: 986 $ Ben Collins <bcollins@debian.org>";
+ "$Rev: 1011 $ Ben Collins <bcollins@debian.org>";
/* Module Parameters */
static int phys_dma = 1;
/* Global initialization */
static void ohci_initialize(struct ti_ohci *ohci)
{
+ char irq_buf[16];
quadlet_t buf;
spin_lock_init(&ohci->phy_reg_lock);
reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable);
buf = reg_read(ohci, OHCI1394_Version);
- PRINT(KERN_INFO, ohci->id, "OHCI-1394 %d.%d (PCI): IRQ=[%d] "
+#ifndef __sparc__
+ sprintf (irq_buf, "%d", ohci->dev->irq);
+#else
+ sprintf (irq_buf, "%s", __irq_itoa(ohci->dev->irq));
+#endif
+ PRINT(KERN_INFO, ohci->id, "OHCI-1394 %d.%d (PCI): IRQ=[%s] "
"MMIO=[%lx-%lx] Max Packet=[%d]",
((((buf) >> 16) & 0xf) + (((buf) >> 20) & 0xf) * 10),
- ((((buf) >> 4) & 0xf) + ((buf) & 0xf) * 10), ohci->dev->irq,
+ ((((buf) >> 4) & 0xf) + ((buf) & 0xf) * 10), irq_buf,
pci_resource_start(ohci->dev, 0),
pci_resource_start(ohci->dev, 0) + OHCI1394_REGISTER_SIZE - 1,
ohci->max_packet_size);
DBGMSG(ohci->id, "Inserting packet for node " NODE_BUS_FMT
", tlabel=%d, tcode=0x%x, speed=%d",
- NODE_BUS_ARGS(packet->node_id), packet->tlabel,
+ NODE_BUS_ARGS(ohci->host, packet->node_id), packet->tlabel,
packet->tcode, packet->speed_code);
d->prg_cpu[idx]->begin.address = 0;
if (packet->type == hpsb_raw) {
d->prg_cpu[idx]->data[0] = cpu_to_le32(OHCI1394_TCODE_PHY<<4);
- d->prg_cpu[idx]->data[1] = packet->header[0];
- d->prg_cpu[idx]->data[2] = packet->header[1];
+ d->prg_cpu[idx]->data[1] = cpu_to_le32(packet->header[0]);
+ d->prg_cpu[idx]->data[2] = cpu_to_le32(packet->header[1]);
} else {
d->prg_cpu[idx]->data[0] = packet->speed_code<<16 |
(packet->header[0] & 0xFFFF);
u32 ContextMatch;
};
-static void ohci_iso_recv_bufferfill_task(unsigned long data);
-static void ohci_iso_recv_packetperbuf_task(unsigned long data);
+static void ohci_iso_recv_task(unsigned long data);
static void ohci_iso_recv_stop(struct hpsb_iso *iso);
static void ohci_iso_recv_shutdown(struct hpsb_iso *iso);
static int ohci_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync);
ohci1394_init_iso_tasklet(&recv->task,
iso->channel == -1 ? OHCI_ISO_MULTICHANNEL_RECEIVE :
OHCI_ISO_RECEIVE,
- recv->dma_mode == BUFFER_FILL_MODE ?
- ohci_iso_recv_bufferfill_task :
- ohci_iso_recv_packetperbuf_task,
- (unsigned long) iso);
+ ohci_iso_recv_task, (unsigned long) iso);
if (ohci1394_register_iso_tasklet(recv->ohci, &recv->task) < 0)
goto err;
hpsb_iso_wake(iso);
}
-static void ohci_iso_recv_bufferfill_task(unsigned long data)
+static void ohci_iso_recv_bufferfill_task(struct hpsb_iso *iso, struct ohci_iso_recv *recv)
{
- struct hpsb_iso *iso = (struct hpsb_iso*) data;
- struct ohci_iso_recv *recv = iso->hostdata;
-
int loop;
/* loop over all blocks */
for (loop = 0; loop < recv->nblocks; loop++) {
/* check block_dma to see if it's done */
-
struct dma_cmd *im = &recv->block[recv->block_dma];
/* check the DMA descriptor for new writes to xferStatus */
ohci_iso_recv_bufferfill_parse(iso, recv);
}
-static void ohci_iso_recv_packetperbuf_task(unsigned long data)
+static void ohci_iso_recv_packetperbuf_task(struct hpsb_iso *iso, struct ohci_iso_recv *recv)
{
- struct hpsb_iso *iso = (struct hpsb_iso*) data;
- struct ohci_iso_recv *recv = iso->hostdata;
int count;
int wake = 0;
hpsb_iso_wake(iso);
}
+static void ohci_iso_recv_task(unsigned long data)
+{
+ struct hpsb_iso *iso = (struct hpsb_iso*) data;
+ struct ohci_iso_recv *recv = iso->hostdata;
+
+ if (recv->dma_mode == BUFFER_FILL_MODE)
+ ohci_iso_recv_bufferfill_task(iso, recv);
+ else
+ ohci_iso_recv_packetperbuf_task(iso, recv);
+}
/***********************************
* rawiso ISO transmission *
case RECV_RELEASE:
ohci_iso_recv_release(iso, (struct hpsb_iso_packet_info*) arg);
return 0;
+ case RECV_FLUSH:
+ ohci_iso_recv_task((unsigned long) iso);
+ return 0;
case RECV_SHUTDOWN:
ohci_iso_recv_shutdown(iso);
return 0;
case OHCI_INIT_DONE:
hpsb_remove_host(ohci->host);
+ /* Clear out BUS Options */
+ reg_write(ohci, OHCI1394_ConfigROMhdr, 0);
+ reg_write(ohci, OHCI1394_BusOptions,
+ (reg_read(ohci, OHCI1394_BusOptions) & 0x0000f007) |
+ 0x00ff0000);
+ memset(ohci->csr_config_rom_cpu, 0, OHCI_CONFIG_ROM_LEN);
+
case OHCI_INIT_HAVE_IRQ:
+ /* Clear interrupt registers */
+ reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
+ reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
+ reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff);
+ reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff);
+ reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff);
+ reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff);
+
+ /* Disable IRM Contender */
+ set_phy_reg(ohci, 4, ~0xc0 & get_phy_reg(ohci, 4));
+
+ /* Clear link control register */
+ reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff);
+
+ /* Let all other nodes know to ignore us */
+ ohci_devctl(ohci->host, RESET_BUS, LONG_RESET_NO_FORCE_ROOT);
+
/* Soft reset before we start - this disables
* interrupts and clears linkEnable and LPS. */
ohci_soft_reset(ohci);
#include <linux/pci.h>
#include <linux/fs.h>
#include <linux/poll.h>
+#include <linux/irq.h>
#include <linux/kdev_t.h>
#include <asm/byteorder.h>
#include <asm/atomic.h>
case have_intr:
reg_write(lynx, PCI_INT_ENABLE, 0);
free_irq(lynx->dev->irq, lynx);
+
+ /* Disable IRM Contender */
+ if (lynx->phyic.reg_1394a)
+ set_phy_reg(lynx, 4, ~0xc0 & get_phy_reg(lynx, 4));
+
+ /* Let all other nodes know to ignore us */
+ lynx_devctl(lynx->host, RESET_BUS, LONG_RESET_NO_FORCE_ROOT);
+
case have_iomappings:
reg_set_bits(lynx, MISC_CONTROL, MISC_CONTROL_SWRESET);
/* Fix buggy cards with autoboot pin not tied low: */
return error; \
} while (0)
+ char irq_buf[16];
struct hpsb_host *host;
struct ti_lynx *lynx; /* shortcut to currently handled device */
struct ti_pcl pcl;
/* Fix buggy cards with autoboot pin not tied low: */
reg_write(lynx, DMA0_CHAN_CTRL, 0);
+#ifndef __sparc__
+ sprintf (irq_buf, "%d", dev->irq);
+#else
+ sprintf (irq_buf, "%s", __irq_itoa(dev->irq));
+#endif
+
if (!request_irq(dev->irq, lynx_irq_handler, SA_SHIRQ,
PCILYNX_DRIVER_NAME, lynx)) {
- PRINT(KERN_INFO, lynx->id, "allocated interrupt %d", dev->irq);
+ PRINT(KERN_INFO, lynx->id, "allocated interrupt %s", irq_buf);
lynx->state = have_intr;
} else {
- FAIL("failed to allocate shared interrupt %d", dev->irq);
+ FAIL("failed to allocate shared interrupt %s", irq_buf);
}
/* alloc_pcl return values are not checked, it is expected that the
i2c_adapter.algo_data = &i2c_adapter_data;
i2c_adapter_data.data = lynx;
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
- PRINT(KERN_DEBUG, lynx->id,"original eeprom control: %d",reg_read(lynx,SERIAL_EEPROM_CONTROL));
-#endif
+ PRINTD(KERN_DEBUG, lynx->id,"original eeprom control: %d",
+ reg_read(lynx, SERIAL_EEPROM_CONTROL));
/* reset hardware to sane state */
lynx->i2c_driven_state = 0x00000070;
if (i2c_transfer(&i2c_adapter, msg, 2) < 0) {
PRINT(KERN_ERR, lynx->id, "unable to read bus info block from i2c");
} else {
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
int i;
-#endif
+
PRINT(KERN_INFO, lynx->id, "got bus info block from serial eeprom");
- /* FIXME: probably we shoud rewrite the max_rec, max_ROM(1394a), generation(1394a) and link_spd(1394a) field
- and recalculate the CRC */
+ /* FIXME: probably we shoud rewrite the max_rec, max_ROM(1394a),
+ * generation(1394a) and link_spd(1394a) field and recalculate
+ * the CRC */
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
- for (i=0; i < 5 ; i++)
- PRINT(KERN_DEBUG, lynx->id, "Businfo block quadlet %i: %08x",i, be32_to_cpu(lynx->config_rom[i]));
-#endif
+ for (i = 0; i < 5 ; i++)
+ PRINTD(KERN_DEBUG, lynx->id, "Businfo block quadlet %i: %08x",
+ i, be32_to_cpu(lynx->config_rom[i]));
/* info_length, crc_length and 1394 magic number to check, if it is really a bus info block */
if (((be32_to_cpu(lynx->config_rom[0]) & 0xffff0000) == 0x04040000) &&
req->req.length, ((req->req.misc >> 8) & 0xFF),
(req->req.misc & 0xFF),((req->req.misc >> 16) & 0xFFFF));
/* check addressrange */
- if ((((req->req.address) & ~(0xFFFFFFFFFFFF)) != 0) ||
- (((req->req.address + req->req.length) & ~(0xFFFFFFFFFFFF)) != 0)) {
+ if ((((req->req.address) & ~((u64)0xFFFFFFFFFFFFLL)) != 0) ||
+ (((req->req.address + req->req.length) & ~((u64)0xFFFFFFFFFFFFLL)) != 0)) {
req->req.length = 0;
return (-EINVAL);
}
return raw1394_iso_recv_packets(fi, (void*) arg);
case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS:
return hpsb_iso_recv_release_packets(fi->iso_handle, arg);
+ case RAW1394_IOC_ISO_RECV_FLUSH:
+ return hpsb_iso_recv_flush(fi->iso_handle);
case RAW1394_IOC_ISO_SHUTDOWN:
raw1394_iso_shutdown(fi);
return 0;
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/sched.h>
-#include <linux/proc_fs.h>
#include <linux/blkdev.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
#include "sbp2.h"
static char version[] __devinitdata =
- "$Rev: 967 $ Ben Collins <bcollins@debian.org>";
+ "$Rev: 1010 $ Ben Collins <bcollins@debian.org>";
/*
* Module load parameter definitions
ud = container_of(dev, struct unit_directory, device);
+ /* Don't probe UD's that have the LUN flag. We'll probe the LUN(s)
+ * instead. */
+ if (ud->flags & UNIT_DIRECTORY_HAS_LUN_DIRECTORY)
+ return -ENODEV;
+
/* This will only add it if it doesn't exist */
hi = sbp2_add_host(ud->ne->host);
SBP2_DEBUG("sbp2_query_logins: orb byte-swapped");
- sbp2util_packet_dump(scsi_id->query_logins_orb, sizeof(stuct sbp2_query_logins_orb),
+ sbp2util_packet_dump(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb),
"sbp2 query logins orb", scsi_id->query_logins_orb_dma);
memset(scsi_id->query_logins_response, 0, sizeof(struct sbp2_query_logins_response));
SBP2_128KB_BROKEN_FIRMWARE &&
(max_sectors * 512) > (128*1024)) {
SBP2_WARN("Node " NODE_BUS_FMT ": Bridge only supports 128KB max transfer size.",
- NODE_BUS_ARGS(ud->ne->nodeid));
+ NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid));
SBP2_WARN("WARNING: Current max_sectors setting is larger than 128KB (%d sectors)!",
max_sectors);
workarounds |= SBP2_BREAKAGE_128K_MAX_TRANSFER;
if ((firmware_revision & 0xffff00) ==
sbp2_broken_inquiry_list[i]) {
SBP2_WARN("Node " NODE_BUS_FMT ": Using 36byte inquiry workaround",
- NODE_BUS_ARGS(ud->ne->nodeid));
+ NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid));
workarounds |= SBP2_BREAKAGE_INQUIRY_HACK;
break; /* No need to continue. */
}
}
- /* If our list is empty, add a base scsi_id (happens in a normal
- * case where there is no logical_unit_number entry */
- if (list_empty(&scsi_group->scsi_id_list)) {
- scsi_id = kmalloc(sizeof(*scsi_id), GFP_KERNEL);
- if (!scsi_id) {
- SBP2_ERR("Out of memory adding scsi_id");
- return;
- }
- memset(scsi_id, 0, sizeof(*scsi_id));
+ /* If this is a logical unit directory entry, process the parent
+ * to get the common values. */
+ if (ud->flags & UNIT_DIRECTORY_LUN_DIRECTORY) {
+ struct unit_directory *parent_ud =
+ container_of(ud->device.parent, struct unit_directory, device);
+ sbp2_parse_unit_directory(scsi_group, parent_ud);
+ } else {
+ /* If our list is empty, add a base scsi_id (happens in a normal
+ * case where there is no logical_unit_number entry */
+ if (list_empty(&scsi_group->scsi_id_list)) {
+ scsi_id = kmalloc(sizeof(*scsi_id), GFP_KERNEL);
+ if (!scsi_id) {
+ SBP2_ERR("Out of memory adding scsi_id");
+ return;
+ }
+ memset(scsi_id, 0, sizeof(*scsi_id));
- scsi_id->sbp2_device_type_and_lun = SBP2_DEVICE_TYPE_LUN_UNINITIALIZED;
- list_add_tail(&scsi_id->list, &scsi_group->scsi_id_list);
- }
+ scsi_id->sbp2_device_type_and_lun = SBP2_DEVICE_TYPE_LUN_UNINITIALIZED;
+ list_add_tail(&scsi_id->list, &scsi_group->scsi_id_list);
+ }
- /* Update the generic fields in all the LUN's */
- list_for_each (lh, &scsi_group->scsi_id_list) {
- scsi_id = list_entry(lh, struct scsi_id_instance_data, list);
+ /* Update the generic fields in all the LUN's */
+ list_for_each (lh, &scsi_group->scsi_id_list) {
+ scsi_id = list_entry(lh, struct scsi_id_instance_data, list);
- scsi_id->sbp2_management_agent_addr = management_agent_addr;
- scsi_id->sbp2_command_set_spec_id = command_set_spec_id;
- scsi_id->sbp2_command_set = command_set;
- scsi_id->sbp2_unit_characteristics = unit_characteristics;
- scsi_id->sbp2_firmware_revision = firmware_revision;
- scsi_id->workarounds = workarounds;
+ scsi_id->sbp2_management_agent_addr = management_agent_addr;
+ scsi_id->sbp2_command_set_spec_id = command_set_spec_id;
+ scsi_id->sbp2_command_set = command_set;
+ scsi_id->sbp2_unit_characteristics = unit_characteristics;
+ scsi_id->sbp2_firmware_revision = firmware_revision;
+ scsi_id->workarounds = workarounds;
+ }
}
}
scsi_id->max_payload_size = min(sbp2_speedto_max_payload[scsi_id->speed_code],
(u8)(((be32_to_cpu(hi->host->csr.rom[2]) >> 12) & 0xf) - 1));
- SBP2_ERR("Node[" NODE_BUS_FMT "]: Max speed [%s] - Max payload [%u]",
- NODE_BUS_ARGS(scsi_id->ne->nodeid), hpsb_speedto_str[scsi_id->speed_code],
+ SBP2_ERR("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [%u]",
+ NODE_BUS_ARGS(hi->host, scsi_id->ne->nodeid),
+ hpsb_speedto_str[scsi_id->speed_code],
1 << ((u32)scsi_id->max_payload_size + 2));
return(0);
return "SCSI emulation for IEEE-1394 SBP-2 Devices";
}
-/* Called for contents of procfs */
-#define SPRINTF(args...) \
- do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0)
-
-static int sbp2scsi_proc_info(struct Scsi_Host *scsi_host, char *buffer, char **start, off_t offset,
- int length, int inout)
-{
- Scsi_Device *scd;
- struct hpsb_host *host;
- char *pos = buffer;
-
- /* if someone is sending us data, just throw it away */
- if (inout)
- return length;
-
- host = hpsb_get_host_bykey(&sbp2_highlevel, (unsigned long)scsi_host);
- if (!host) /* shouldn't happen, but... */
- return -ESRCH;
-
- SPRINTF("Host scsi%d : SBP-2 IEEE-1394 (%s)\n",
- scsi_host->host_no, host->driver->name);
- SPRINTF("Driver version : %s\n", version);
-
- SPRINTF("\nModule options :\n");
- SPRINTF(" max_speed : %s\n", hpsb_speedto_str[max_speed]);
- SPRINTF(" max_sectors : %d\n", max_sectors);
- SPRINTF(" serialize_io : %s\n", serialize_io ? "yes" : "no");
- SPRINTF(" exclusive_login : %s\n", exclusive_login ? "yes" : "no");
-
- SPRINTF("\nAttached devices : %s\n", !list_empty(&scsi_host->my_devices) ?
- "" : "none");
-
- list_for_each_entry (scd, &scsi_host->my_devices, siblings) {
- int i;
-
- SPRINTF(" [Channel: %02d, Id: %02d, Lun: %02d] ", scd->channel,
- scd->id, scd->lun);
- SPRINTF("%s ", (scd->type < MAX_SCSI_DEVICE_CODE) ?
- scsi_device_types[(short) scd->type] : "Unknown device");
-
- for (i = 0; (i < 8) && (scd->vendor[i] >= 0x20); i++)
- SPRINTF("%c", scd->vendor[i]);
-
- SPRINTF(" ");
-
- for (i = 0; (i < 16) && (scd->model[i] >= 0x20); i++)
- SPRINTF("%c", scd->model[i]);
-
- SPRINTF("\n");
- }
-
- SPRINTF("\n");
-
- /* Calculate start of next buffer, and return value. */
- *start = buffer + offset;
-
- if ((pos - buffer) < offset)
- return (0);
- else if ((pos - buffer - offset) < length)
- return (pos - buffer - offset);
- else
- return (length);
-}
-
MODULE_AUTHOR("Ben Collins <bcollins@debian.org>");
MODULE_DESCRIPTION("IEEE-1394 SBP-2 protocol driver");
MODULE_SUPPORTED_DEVICE(SBP2_DEVICE_NAME);
.name = "SBP-2 IEEE-1394",
.proc_name = SBP2_DEVICE_NAME,
.info = sbp2scsi_info,
- .proc_info = sbp2scsi_proc_info,
.queuecommand = sbp2scsi_queuecommand,
.eh_abort_handler = sbp2scsi_abort,
.eh_device_reset_handler = sbp2scsi_reset,
{
SBP2_DEBUG("sbp2_module_init");
+ printk(KERN_INFO "sbp2: %s\n", version);
+
/* Module load debug option to force one command at a time (serializing I/O) */
if (serialize_io) {
SBP2_ERR("Driver forced to serialize I/O (serialize_io = 1)");
#include <linux/fs.h>
#include <linux/poll.h>
#include <linux/smp_lock.h>
-#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/bitops.h>